Decoded: Rogue (1980) by Toy, Arnold, Wichman
DOS version (1983) by Mel Sibony and Jon Lane
Source file: COMMAND.C
Beginner friendly, line-by-line code walkthrough by MaiZure

COMMAND.C provides functions to read and handle user input

Original code:
https://britzl.github.io/roguearchive/

Original code with line numbers
http://www.maizure.org/projects/decoded-rogue/COMMAND_linenum.txt




1     COMMENT
2     COMMENT
3     COMMENT
4     COMMENT
5     COMMENT
6     BLANK
7     Includes the game header
8     Includes the console management header
9     BLANK
10    Declares a compilation unit level static integer for counting
11    Declares three static bytes for input character buffer and obj pointers
12    BLANK

USER INPUT HANDLER

13    Declares command with no arguments
14    BLOCK START - command, handles input. Called every cycle of game loop
15    Declares an interger counting the number of commands to handle
16    BLANK
17    If the player has the Haste condition
18    Then the player can act 2 or 3 times per command loop
19    Otherwise...
20    The player gets one turn per loop
21    While there are still turns for the loop..
22    Update the status bar
23    Checks keyboard for utility keys (caps, numlock, etc) via DOS interrupts
24    Checks if we're in wizard mode (we're not)
25    If wizard mode is active...
26    Then there is no score
27    End check for wizard mode
28    If the player cannot move now (sleeping, too much food, etc)
29    Decrement the no_command counter and check if it's 0
30    Print a message that the player can move
31    Set no_command to zero
32    End check for no_command at ero
33    Otherwise, the player is free to move
34    Execute the most recent command
35    Update single-shot timers
36    Update background tasks
37    Clever loop to cover both ring slots and apply effects if needed. Note
      this loop is an inner loop for the outer while but reuses the main 
	  iterator. In any case, we loop from 0 to 1 to cover L and R slots
38    Check if the slot has a ring
39    SWITCH on the type of ring
40    CASE ring of searching
41    Execute a search
42    CASE ring of teleport
43    Roll a random number and if it matches 17 (2% chance)
44    Teleport the player randomly
45    End Switch
46    End command loop
47    BLOCK END - command
48    BLANK
49    Defines com_char with no arguments

CHECK FIRST CHARACTER (ESCAPE CHARACTER CHECK)

50    BLOCK START - com_char, returns an escaped character and sets state
51    Declare a local integer for a previous state flag and the return char
52    BLANK
53    Grab the current state of the text parsing (for running, etc)
54    Read in the input character from the keyboard. Note that this could
      change the faststate setting, which is why we grabbed it earlier
55    If the state matches
56    Then set the fastmode to match
57    Otherwise...
58    Make them different
59    SWITCH on the character to return
60    CASE backspace: set it to h (move left)
61    CASE plus: map it to 't' for throw
62    CASE minus: map it to 'z' for zapping wands
63    End switch
64    If the cursor is in the room of play and the player isn't running
65    Clear the status line
66    Return the character to the player
67    BLOCK END - com_char
68    BLANK
69    COMMENT
70    COMMENT
71    COMMENT
72    COMMENT
73    BLANK
74    Define get_prefix with no arguments

GET COMMAND PREFIX (FIRST LETTER)

75    BLOCK START - get_prefix, returns the first character of input
76    Declare integers for return, storage, and temporary values
77    BLANK
78    Command is executed after the background update daemons
79    Match the running/detection mode
80    Update the screen to the current location
81    If the player isn't running...
82    Then don't stop the player that encounters a door
83    Pick up items that the player runs in to
84    Assume the command isn't repeated
85    If the command is to be issued at least once...
86    Update the item taking from the global buffer variable
87    Update the last returned character from global buffer
88    Disable fast mode
89    Otherwise there was only one command to issue (or none?)
90    Make sure count is zero (could be -1 at this point?)
91    If the player is currently running
92    Update the return character to the current running direction
93    Update the take state
94    Otherwise, the character is not running so...
95    Loop while there is no return character (process multichar input)
96    SWITCH on the first input character (after escaping via com_char)
97    If the first character is 0-4...
98    ...or 5-9...
99    Setting up repeated commands: multiply the first digit by 10
100   Check and add more input. If it's less than 10000 total..
101   Use the input number for future repeated processing loops
102   Display the number of times the next command will repeat
103   CASE input is 'f' (searching)
104   Toggle fast mode for item searching
105   CASE input is 'g' (item get)
106   Clear the last item take state
107   CASE input is 'a' (repeat last input)
108   Set return character to the last returned character
109   Set the repeat counter to the last used repeat counter
110   Set the take state to the previous state
111   Mark flag for repeat
112   CASE space (ignore)
113   CASE escape (cancel input)
114   Don't allow door interruptions
115   No repeats
116   Show the updated counter
117   For everything else...
118   Set the return value and we'll process later
119   End Switch on input character
120   End loop while reading input
121   End check for player not running input case
122   End case for only one input repeat loop remaining
123   If we are repeating a command..
124   Set the fastmode to false so we can be interrupted by interesting things
125   SWITCH on input character now that we've looped through all repeats
126   If input is a single step cardinal direction..
127   or if input is a single step ordinal direction..
128   Check if we're in fastmode and not running (we must simulate running).
129   If the player isn't blind...
130   Stop on doors
131   This is the first movement
132   End check for blindness
133   Return the upper case of the movement directionm
134   End check for fast mode but not running
135   If input is a running cardinal...
136   ...or a running ordinal...
137   ...or an item usage command...
138   ...or throw or wait...
139   Preprocessor check for wiz mode
140   ...or the wizard command to create items...
141   End check for wiz mode
142   All these above cases require no extra processing, retch is already set
143   For all other cases...
144   Set count to 0, nothing to repeat
145   End Switch
146   If there is something to repeat or we're in the middle of repeating
147   Show the count display
148   Set the global buffer history to reflect this character
149   Set the global counter to the now updated count
150   Set the global take state to reflect current take state
151   Return the character determined character
152   BLOCK END - get_prefix
153   BLANK
154   Define show_count with no arguments

SHOW REPEATED COMMAND COUNTS

155   BLOCK START - show_count, displays the current count of repeated actions
156   Move the cursor to (almost) the bottom right
157   If there is a repeating count in progress...
158   Print the value to the status line
159   Otherwise...
160   Print nothing
161   BLOCK END - show_count
162   BLANK
163   Define execcom with no arguments

EXECUTE COMMANDS

164   BLOCK START - execcom, dispatches command input to the proper handler
165   Declare a local coordinate struct
166   Declare a local variable to hold input char values
167   BLANK
168   Start the main input loop
169   SWITCH on the input character
170   CASE walking cardinal direction (fallthrough)
171   CASE walking ordinal direction
172   Set the motion offset in to the temp coordinate
173   Apply the change to the character
174   CASE running cardinal direction (fallthrough)
175   CASE walking ordinal direction
176   Run to the indicated direction based on the input
177   CASE throw
178   If the player chooses a valid direction
179   Launch the item in the correct direction
180   Otherwise...
181   No valid options were chosen, redo turn
182   CASE quit: quit the game
183   CASE inventory: check the player inventory
184   CASE drop: drop items
185   CASE quaff: drink a potion
186   CASE read: read a scroll
187   CASE eat: eat something
188   CASE wield: equip a weapon
189   CASE wear: put on armor
190   CASE take off: rake off armor
191   CASE wear ring: put on a ring
192   CASE take off ring: do iiiit!
193   CASE rename item: change an item name, no turn passes
194   CASE go down: Take stairs down to the next level, no turn passes
195   CASE go up: Take stairs up to the previous level, no turn passes
196   CASE object help: Shows the game legend
197   CASE command help: Shows the commands
198   CASE boss key: Jump to fake DOS while playing on the job. DOS at work?
      Maybe if you're in a Government job.
199   CASE search: Search function
200   CASE zap:
201   If player inputs a valid direction
202   Zap the wand that way
203   Otherwise...
204   Redo the turn
205   CASE discoveries: Show the list of discoveries
206   CASE terse mode:
207   No turn passes
208   Out a message condition on the toggle value of the expert mode
209   Message if mode is now on
210   Message if mode is now off
211   CASE macro: create a new macro, no turn passes
212   CASE function: Set the executing macro
213   CASE repeat last message: repeat it!
214   CASE show version:
215   Pass no time
216   If the player is some hidden fun super user guy
217   Return the current checksum
218   Output the game version, including the Easter egg coder/hacker tag
219   CASE save game: Save!
220   CASE pass time: check healing routine and pass time
221   CASE identify trap:
222   No turn passes
223   If the player provides a valid direction...
224   Declare temp coordinate
225   BLANK
226   Set the x coordinate based on player position plus offset
227   Set the y coordinate based on player position plus offset
228   If there is no trap at the chosen location
229   Say so
230   Otherwise
231   Say that there is a trap..
232   and include the name using the flag lookup index
233   Otherwise the player didn't choose a valid direction
234   CASE 'o' input: No time passes and a useless message is output
235   CASE ctrl-l:
236   No time passes
237   Another coder/hacker easter egg message
238   Check if wizard mode is enabled
239   Handle create object
240   End check for wizard mode
241   CASE no command matches
242   No time passes
243   Disable message buffer
244   Output bad command message
245   Reset count to 0 (don't repeat nonsense commands)
246   Enable message buffer
247   End switch
248   If take mode and an object are identified
249   Pick up the object
250   Deassert the take flag
251   If the player is walking...
252   Don't get stopped by hitting a door
253   Redo the main input loop while there isn't a valid command to process
254   BLOCK END - execcom
255   EOF