Added `shoot` function to Hunt the Wumpus (and updated README path).
[vvhitespace] / examples / hunt-the-wumpus / wump_game.pvvs
index 7d85f8d..a387f48 100644 (file)
@@ -334,4 +334,718 @@ SNN                   | DROP
 SSSTN                 | PUSH 1
 NTN                   | RTS
 
 SSSTN                 | PUSH 1
 NTN                   | RTS
 
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   seed_rng
+@ Description:
+@   Generate seed from keyboard input.
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <logic.pvvs>
+NSSVTSSSSSTTN         | MARK: 10000011 (seed_rng)
+
+SSSTSSSSN             | PUSH 16 (loop counter)
+SSSSN                 | PUSH 0 (rng seed)
+
+NSSVTSSSSSTTSSSSSSSSN | MARK: 10000011 00000000 (seed_rng:main loop)
+@ Get character from user and print ASCII '.' as feedback.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+TNTS                  | GETCHAR
+SSSTSTTTSN            | PUSH ASCII '.'
+TNSS                  | PUTCHAR
+@ Left shift the seed by 4 bits.
+SSSTSSN               | PUSH 4 (shift count)
+NSTTSTTSTN            | JSR > 101101 (lshift)
+@ XOR seed with character from user.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+TTT                   | LOAD
+NSTTSTSTTN            | JSR > 101011 (xor)
+@ Decrement counter
+SNT                   | SWAP
+SSSTN                 | PUSH +1
+TSST                  | SUBTRACT
+@ Test for loop completion
+SNS                   | DUP
+NTSTSSSSSTTSSSSSSSTN  | BRZ > 10000011 00000001 (seed_rng:cleanup and return)
+SNT                   | SWAP
+NSNTSSSSSTTSSSSSSSSN  | JMP > 10000011 00000000 (seed_rng:main loop)
+
+@ Store seed, clean up and return.
+NSSVTSSSSSTTSSSSSSSTN | MARK: 10000011 00000001 (seed_rng:cleanup and return)
+SNN                   | DROP
+SSSSN                 | PUSH 0 (seed address)
+SNT                   | SWAP
+TTS                   | STORE
+SSSTSTSN              | PUSH ASCII '\n'
+SSSTSTSN              | PUSH ASCII '\n'
+TNSS                  | PUTCHAR
+TNSS                  | PUTCHAR
+NTN                   | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   are_rooms_adjacent
+@ Description:
+@   Checks if 'room_number_1' is adjacent to 'room_number_2'.
+@ Call Stack:
+@   room_number_2
+@   room_number_1  <-- TOS
+@ Return Stack:
+@   (1 or 0) for true/false  <-- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <stack.pvvs>
+NSSVTSTSSTSSN         | MARK: 10100100 (are_rooms_adjacent)
+
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (ptr to number_of_tunnels_per_room)
+TTT                   | LOAD
+SSSTN                 | PUSH +1
+TSST                  | SUBTRACT
+
+@ TOS> tunnel_index, room_number_1, room_number_2
+NSSVTSTSSTSSSSSSSSSSN | MARK: 10100100 00000000 (main_loop)
+SSSTTN                | PUSH +3
+NSTTTSSN              | JSR > 1100 (deepdup)
+SSSTTN                | PUSH +3
+NSTTTSSN              | JSR > 1100 (deepdup)
+SSSTTN                | PUSH +3
+NSTTTSSN              | JSR > 1100 (deepdup)
+SNT                   | SWAP
+NSTTSSSTSSSN          | JSR > 10001000 (get_tunnel_destination)
+TSST                  | SUBTRACT
+NTSTSTSSTSSSSSSSSSTN  | BRZ > 10100100 00000001 (found_tunnel)
+SSSTN                 | PUSH +1
+TSST                  | SUBTRACT
+SNS                   | DUP
+NTTTSTSSTSSSSSSSSTSN  | BMI > 10100100 00000010 (no_match)
+NSNTSTSSTSSSSSSSSSSN  | JMP > 10100100 00000000 (main_loop)
+
+NSSVTSTSSTSSSSSSSSSTN | MARK: 10100100 00000001 (found_tunnel)
+SNN                   | DROP
+SNN                   | DROP
+SNN                   | DROP
+SSSTN                 | PUSH +1
+NTN                   | RTS
+
+NSSVTSTSSTSSSSSSSSTSN | MARK: 10100100 00000010 (no_match)
+SNN                   | DROP
+SNN                   | DROP
+SNN                   | DROP
+SSSSN                 | PUSH 0
+NTN                   | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   move_player
+@ Description:
+@   Prompts the player for a room number. Moves to that room, checking the new
+@   environment and executing consequences (fell in a pit, etc) as appropriate.
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <stdio.pvvs>
+#include <convert.pvvs>
+#include <math.pvvs>
+#include <string.pvvs>
+NSSVTSTSSSTTN         | MARK: 10100011 (move_player)
+
+A"To which room do you wish to move?\n"
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer address)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer size)
+NSTTSSSTSN            | JSR > 100010 (get_user_string)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+NSTTTSSSSN            | JSR > 110000 (atoi)
+SNN                   | DROP
+
+@ The desired room number is now on the TOS. Verify that it is valid.
+SNS                   | DUP
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player_location)
+TTT                   | LOAD
+NSTTSTSSTSSN          | JSR > 10100100 (are_rooms_adjacent)
+NTSTSTSSSTTSSSSSSSTN  | BRZ > 10100011 00000001 (invalid room number)
+NSNTSTSSSTTSSSSSSSSN  | JMP > 10100011 00000000 (valid room number)
+
+NSSVTSTSSSTTSSSSSSSTN | MARK: 10100011 00000001 (invalid room number)
+@ TOS> room_number
+SNN                   | DROP
+A"*Oof!* (you hit the wall)\n"
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSTTSSTTN             | JSR > 10011 (fastrand)
+SSSTTSN               | PUSH 6 (chance)
+TSTT                  | MODULO
+NTSTSTSSSTTSSSSSSTSN  | BRZ > 10100011 00000010 (woke the wumpus)
+NTN                   | RTS
+NSSVTSTSSSTTSSSSSSTSN | MARK: 10100011 00000010 (woke the wumpus)
+A"Your colorful comments awaken the wumpus!\n"
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSTTSSTTN             | JSR > 10011 (fastrand)
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (ptr to number of tunnels per room)
+TSTT                  | MODULO
+SSSTSSSSSSSSSTTTN     | PUSH 0x1007 (ptr to wumpus location)
+TTT                   | LOAD
+NSTTSSSTSSSN          | JSR > 10001000 (get_tunnel_destination)
+SSSTSSSSSSSSSTTTN     | PUSH 0x1007 (ptr to wumpus location)
+SNT                   | SWAP
+TTS                   | STORE
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player location)
+TTT                   | LOAD
+NSTTSTSSSSSN          | JSR > 10100000 (room_has_wumpus)
+NTSTSTSSSTTSSSSSSTTN  | BRZ > 10100011 00000011 (wumpus did not move to player)
+NSTTTTTTTTTSSSSSSSSN  | JSR > 11111111 00000000 (wump_kill)
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+NSSVTSTSSSTTSSSSSSTTN | MARK: 10100011 00000011 (wumpus did not move to player)
+NTN                   | RTS
+
+NSSVTSTSSSTTSSSSSSSSN | MARK: 10100011 00000000 (valid room number)
+@ TOS> room_number
+@ Move player to new room
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player location)
+SNT                   | SWAP
+TTS                   | STORE
+@ Check for wumpus in new player location
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player location)
+TTT                   | LOAD
+NSTTSTSSSSSN          | JSR > 10100000 (room_has_wumpus)
+NTSTSTSSSTTSSSSSTSSN  | BRZ > 10100011 00000100 (no wumpus in new room)
+NSTTTTTTTTTSSSSSSSSN  | JSR > 11111111 00000000 (wump_kill)
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+NSSVTSTSSSTTSSSSSTSSN | MARK: 10100011 00000100 (no wumpus in new room)
+@ Check for pits in new player location
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player location)
+TTT                   | LOAD
+NSTTSSSTTSTN          | JSR > 10001101 (room_has_pits)
+NTSTSTSSSTTSSSSSTSTN  | BRZ > 10100011 00000101 (no pits in new room)
+NSTTSSTTN             | JSR > 10011 (fastrand)
+SSSTTSN               | PUSH 6 (chance)
+TSTT                  | MODULO
+NTSTSTSSSTTSSSSSTTSN  | BRZ > 10100011 00000110 (survived the pits)
+NSTTTTTTTTTSSSSSTSTN  | JSR > 11111111 00000101 (pit_kill)
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+NSSVTSTSSSTTSSSSSTTSN | MARK: 10100011 00000110 (survived the pits)
+NSTTTTTTTTTSSSSSTTSN  | JSR > 11111111 00000110 (pit_survive)
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSSVTSTSSSTTSSSSSTSTN | MARK: 10100011 00000101 (no pits in new room)
+@ Check for bats in new player location
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player location)
+TTT                   | LOAD
+NSTTSSSTTSSN          | JSR > 10001100 (room_has_bats)
+NTSTSTSSSTTSSSSSTTSN  | BRZ > 10100011 00000110 (no bats in new room)
+A"*flap*  *flap*  *flap*  (humongous bats pick you up and move you!)\n"
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSTTSSTTN             | JSR > 10011 (fastrand)
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (ptr to number of tunnels per room)
+TSTT                  | MODULO
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player location)
+TTT                   | LOAD
+NSTTSSSTSSSN          | JSR > 10001000 (get_tunnel_destination)
+NSNTSTSSSTTSSSSSSSSN  | JMP > 10100011 00000000 (valid room number)
+NSSVTSTSSSTTSSSSSTTSN | MARK: 10100011 00000110 (no bats in new room)
+NTN                   | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   shoot_arrow
+@ Description:
+@   Prompt user for list of rooms. Shoots an arrow through each room, checking
+@     the new environment and executing consequences (fell in a pit, etc) as
+@     appropriate.
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <string.pvvs>
+#include <stack.pvvs>
+#include <stdio.pvvs>
+#include <math.pvvs>
+#include <wump_strings.pvvs>
+NSSVTSSTTSSTN         | MARK: 10011001 (shoot_arrow)
+
+A"Through which rooms do you wish to shoot your arrow?\n(type %u room numbers separated by spaces)\n"
+SSSTSSSSSSSSSTSSN     | PUSH 0x1004 (ptr to max_arrow_flight_distance)
+TTT                   | LOAD
+SSSTN                 | PUSH 1 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer address)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer size)
+NSTTSSSTSN            | JSR > 100010 (get_user_string)
+
+@ Loop, converting one room number from the user string per pass.
+@ But first, prepare the stack for the loop.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+SSSTSSSSSSSSSTSSN     | PUSH 0x1004 (ptr to max_arrow_flight_distance)
+TTT                   | LOAD
+@ TOS> loop_counter, ptr_to_user_string
+NSSVTSSTTSSTSSSSSSSSN | MARK: 10011001 00000000 (process_room_loop)
+@ Test for end of loop (counter == 0)
+SNS                   | DUP
+NTSTSSTTSSTSSSSSSSTN  | BRZ > 10011001 00000001 (end of process_room_loop)
+@ Now jump forward in the user string to the next ASCII digit (or null term).
+SNT                   | SWAP
+NSSVTSSTTSSTSSSSSSTSN | MARK: 10011001 00000010 (next_ascii_digit_loop)
+SNS                   | DUP
+TTT                   | LOAD
+SNS                   | DUP
+NSTTSSSSTN            | JSR > 100001 (isdigit)
+NTSTSSTTSSTSSSSSSTTN  | BRZ > 10011001 00000011 (ascii_term_test)
+SNN                   | DROP
+NSNTSSTTSSTSSSSSTSSN  | JMP > 10011001 00000100 (next_ascii_digit_loop_end)
+NSSVTSSTTSSTSSSSSSTTN | MARK: 10011001 00000011 (ascii_term_test)
+NTSTSSTTSSTSSSSSTSSN  | BRZ > 10011001 00000100 (next_ascii_digit_loop_end)
+SSSTN                 | PUSH 1
+TSSS                  | ADD
+NSNTSSTTSSTSSSSSSTSN  | JMP > 10011001 00000010 (next_ascii_digit_loop)
+NSSVTSSTTSSTSSSSSTSSN | MARK: 10011001 00000100 (next_ascii_digit_loop_end)
+@ Call atoi with the newly updated pointer to process another room number.
+NSTTTSSSSN            | JSR > 110000 (atoi)
+SNT                   | SWAP
+SSSTTN                | PUSH 3 (rotation_depth)
+NSTTSTSN              | JSR > 1010 (stackrotate)
+@ Decrement the loop counter and loop again.
+SNT                   | SWAP
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+NSNTSSTTSSTSSSSSSSSN  | JMP > 10011001 00000000 (process_room_loop)
+@ Loop is complete. Moving on.
+NSSVTSSTTSSTSSSSSSSTN | MARK: 10011001 00000001 (end of process_room_loop)
+SNN                   | DROP
+SNN                   | DROP
+
+@ Stack now contains only integers for room numbers (zero padded to full count).
+@ They are in reverse order, so reverse again.
+@ Temporarily use the USER_INPUT_BUFFER as a loop counter.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+SSSTSSSSSSSSSTSSN     | PUSH 0x1004 (ptr to max_arrow_flight_distance)
+TTT                   | LOAD
+TTS                   | STORE
+@ Now perform the reversal.
+NSSVTSSTTSSTSSSSSTSTN | MARK: 10011001 00000101 (reverse_loop)
+@ First shift the TOS element back to its final location.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+NSTTSTSN              | JSR > 1010 (stackrotate)
+@ Now decrement the loop counter.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+@ And check for the end of loop condition (counter < 2)
+SNS                   | DUP
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+NTSTSSTTSSTSSSSSTTSN  | BRZ > 10011001 00000110 (reverse_loop_end)
+@ The loop continues. Store the new loop counter and go around again.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+SNT                   | SWAP
+TTS                   | STORE
+NSNTSSTTSSTSSSSSTSTN  | JMP > 10011001 00000101 (reverse_loop)
+@ End of loop. Clean up and continue.
+NSSVTSSTTSSTSSSSSTTSN | MARK: 10011001 00000110 (reverse_loop_end)
+SNN                   | DROP
+
+@@@@@ Initialization complete. @@@@@
+
+@ Stack now contains a list room numbers as integers, in order.
+
+@ Put a loop index and the starting location of the arrow on the stack.
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player_location, now arrow_location)
+TTT                   | LOAD
+SSSTSSSSSSSSSTSSN     | PUSH 0x1004 (ptr to max_arrow_flight_distance)
+TTT                   | LOAD
+
+@ TOS> loop_index, arrow_location, list_of_room_numbers ...
+@ Move the arrow through a new room for each pass of the loop.
+NSSVTSSTTSSTSSSSSTTTN | MARK: 10011001 00000111 (arrow_loop)
+@ Check loop index for end of loop condition (index==0).
+SNS                   | DUP
+NTSTSSTTSSTSSSSTTSTN  | BRZ > 10011001 00001101 (loop_end)
+@ Is the requested room number connected to the arrows current room?
+SNT                   | SWAP
+SNS                   | DUP
+SSSTSSN               | PUSH 4
+NSTTTSSN              | JSR > 1100 (deepdup)
+NSTTSTSSTSSN          | JSR > 10100100 (are_rooms_adjacent)
+NTSTSSTTSSTSSSSTSSSN  | BRZ > 10011001 00001000 (not_adjacent)
+@ Room was adjacent. Print update for user, clean up stack and jump ahead.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+SNT                   | SWAP
+TTS                   | STORE
+SNT                   | SWAP
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+SNT                   | SWAP
+TTS                   | STORE
+A"The arrow sails out of room %u and enters room %u.\n"
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+TTT                   | LOAD
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+SSSTSN                | PUSH 2
+NSTTSSSN              | JSR > 1000 (printf)
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+TTT                   | LOAD
+SNT                   | SWAP
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+SNT                   | SWAP
+NSNTSSTTSSTSSSSTSSTN  | JMP > 10011001 00001001 (room_is_valid)
+@ Room was not adjacent. Select a random adjacent room for the arrow.
+NSSVTSSTTSSTSSSSTSSSN | MARK: 10011001 00001000 (not_adjacent)
+SSSTTN                | PUSH 3
+NSTTSTTN              | JSR > 1011 (stackrotatereverse)
+@ TOS> (invalid) room_number, arrow_location, loop_index, rest_of_room_numbers ...
+@ Start a message to the user.
+@ First, store two values we will need when printing the user message.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+SNT                   | SWAP
+TTS                   | STORE
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+SNT                   | SWAP
+TTS                   | STORE
+A"*thunk* The arrow can't find a way from room %u to room %u "
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+TTT                   | LOAD
+SSSTSN                | PUSH 2
+NSTTSSSN              | JSR > 1000 (printf)
+@ Now locate a random, connected room for the arrow to visit.
+NSTTSSSSN             | JSR > 10000 (random)
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (ptr to number_of_tunnels_per_room)
+TTT                   | LOAD
+TSTT                  | MODULO
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+TTT                   | LOAD
+NSTTSSSTSSSN          | JSR > 10001000 (get_tunnel_destination)
+@ Now finish the message to the user.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+SNT                   | SWAP
+TTS                   | STORE
+A"and flys randomly into room %u!\n"
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+SSSTN                 | PUSH 1
+NSTTSSSN              | JSR > 1000 (printf)
+@ And cleanup the stack before continuing onward.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000
+TTT                   | LOAD
+SNT                   | SWAP
+SSSTTSSSSSSSSSSSTN    | PUSH 0x3001
+TTT                   | LOAD
+SNT                   | SWAP
+
+NSSVTSSTTSSTSSSSTSSTN | MARK: 10011001 00001001 (room_is_valid)
+@ TOS> loop_index, arrow_location, list_of_room_numbers ...
+SSSTTN                | PUSH 3
+NSTTSTSN              | JSR > 1010 (stackrotate)
+SNN                   | DROP
+@ TOS> (new) arrow_location, loop_index, (smaller) list_of_room_numbers ...
+@ Does new room contain a wumpus?
+SNS                   | DUP
+NSTTSTSSSSSN          | JSR > 10100000 (room_has_wumpus)
+NTSTSSTTSSTSSSSTSTSN  | BRZ > 10011001 00001010 (no_wumpus_here)
+@ Player slew the wumpus!
+NSTTTTTTTTTSSSSSSSTN  | JSR > 11111111 00000001 (kill_wump)
+SSSSN                 | PUSH 0
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+@ No wumpus here. Does the new room contain the player?
+NSSVTSSTTSSTSSSSTSTSN | MARK: 10011001 00001010 (no_wumpus_here)
+SNS                   | DUP
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player_location)
+TTT                   | LOAD
+TSST                  | SUBTRACT
+NTSTSSTTSSTSSSSTSTTN  | BRZ > 10011001 00001011 (player_shot_self)
+NSNTSSTTSSTSSSSTTSSN  | JMP > 10011001 00001100 (no_events_in_room)
+NSSVTSSTTSSTSSSSTSTTN | MARK: 10011001 00001011 (player_shot_self)
+@ Player hit by own arrow!
+NSTTTTTTTTTSSSSSSTTN  | JSR > 11111111 00000011 (shoot_self)
+SSSSN                 | PUSH 0
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+@ No player here. Update loop index, cleanup stack and loop again.
+NSSVTSSTTSSTSSSSTTSSN | MARK: 10011001 00001100 (no_events_in_room)
+SNT                   | SWAP
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+NSNTSSTTSSTSSSSSTTTN  | JMP > 10011001 00000111 (arrow_loop)
+NSSVTSSTTSSTSSSSTTSTN | MARK: 10011001 00001101 (loop_end)
+SNN                   | DROP
+SNN                   | DROP
+A"The arrows wavers in its flight and can go no further!\n"
+SSSSN                 | PUSH 0
+NSTTSSSN              | JSR > 1000 (printf)
+
+@ Since the player did not kill the wumpus, there is a chance it will wake and move.
+NSTTSSSSN             | JSR > 10000 (random)
+SSSTTSN               | PUSH 6
+TSTT                  | MODULO
+NTSTSSTTSSTSSSSTTTSN  | BRZ > 10011001 00001110 (move_wumpus)
+NSNTSSTTSSTSSSTSSSSN  | JMP > 10011001 00010000 (wumpus_continues_to_slumber)
+NSSVTSSTTSSTSSSSTTTSN | MARK: 10011001 00001110 (move_wumpus)
+@ Move the wumpus to a random connected room.
+NSTTSSSSN             | JSR > 10000 (random)
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (ptr to number_of_tunnels_per_room)
+TTT                   | LOAD
+TSTT                  | MODULO
+SSSTSSSSSSSSSTTTN     | PUSH 0x1007 (ptr to wumpus_location)
+TTT                   | LOAD
+NSTTSSSTSSSN          | JSR > 10001000 (get_tunnel_destination)
+SSSTSSSSSSSSSTTTN     | PUSH 0x1007 (ptr to wumpus_location)
+SNT                   | SWAP
+TTS                   | STORE
+@ Did the wumpus enter the player room?
+SSSTSSSSSSSSSTTTN     | PUSH 0x1007 (ptr to wumpus_location)
+TTT                   | LOAD
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (ptr to player_location)
+TTT                   | LOAD
+TSST                  | SUBTRACT
+NTSTSSTTSSTSSSSTTTTN  | BRZ > 10011001 00001111 (player_death)
+NSNTSSTTSSTSSSTSSSSN  | JMP > 10011001 00010000 (wumpus_continues_to_slumber)
+NSSVTSSTTSSTSSSSTTTTN | MARK: 10011001 00001111 (player_death)
+NSTTTTTTTTTSSSSSSSSN  | JSR > 11111111 00000000 (wump_kill)
+SSSSN                 | PUSH 0
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+
+NSSVTSSTTSSTSSSTSSSSN | MARK: 10011001 00010000 (wumpus_continues_to_slumber)
+@ Decrement the number of arrows.
+SSSTSSSSSSSSSTSTN     | PUSH 0x1005 (ptr to number_of_arrows)
+TTT                   | LOAD
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+SNS                   | DUP
+SSSTSSSSSSSSSTSTN     | PUSH 0x1005 (ptr to number_of_arrows)
+SNT                   | SWAP
+TTS                   | STORE
+@ Check for empty quiver.
+NTSTSSTTSSTSSSTSSSTN  | BRZ > 10011001 00010001 (empty_quiver)
+NTN                   | RTS
+NSSVTSSTTSSTSSSTSSSTN | MARK: 10011001 00010001 (empty_quiver)
+NSTTTTTTTTTSSSSSSTSN  | JSR > 11111111 00000010 (no_arrows)
+SSSSN                 | PUSH 0
+NSTTSSSN              | JSR > 1000 (printf)
+NNN                   | DIE
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   move_or_shoot
+@ Description:
+@   Parse user input, branching to the appropriate subroutine to move or shoot.
+@   This function does not perform any boundary checks/limits.
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <stdio.pvvs>
+#include <string.pvvs>
+NSSVTSTSSSTSN         | MARK: 10100010 (move_or_shoot)
+
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer address)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer size)
+NSTTSSSTSN            | JSR > 100010 (get_user_string)
+
+@ Examine the first character of the user input buffer for 'm' or 's'.
+@ If character is something else, prompt user to try again.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+TTT                   | LOAD
+SSSSTTSTTSTN          | PUSH 109 (ASCII 'm')
+TSST                  | SUBTRACT
+NTSTSTSSSTSSSSSSSSSN  | BRZ > 10100010 00000000 (move)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+TTT                   | LOAD
+SSSSTTTSSTTN          | PUSH 115 (ASCII 's')
+TSST                  | SUBTRACT
+NTSTSTSSSTSSSSSSSSTN  | BRZ > 10100010 00000001 (shoot)
+NSTTTTTTTTTSSSSTSSSN  | JSR > 11111111 00001000 (problem_with_input)
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSNTSTSSSTSN          | JMP > 10100010 (move_or_shoot)
+
+@ User typed 'm'
+NSSVTSTSSSTSSSSSSSSSN | MARK: 10100010 00000000 (move)
+NSTTSTSSSTTN          | JSR > 10100011 (move_player)
+NTN                   | RTS
+
+@ User typed 's'
+NSSVTSTSSSTSSSSSSSSTN | MARK: 10100010 00000001 (shoot)
+NSTTSSTTSSTN          | JSR > 10011001 (shoot_arrow)
+NTN                   | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   get_answer
+@ Description:
+@   Parse user input, returning 0 if user string started with 'n' or 1 if 'y'.
+@   This function does not perform any boundary checks/limits.
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   (1 or 0 for True/False)   <--- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <stdio.pvvs>
+#include <string.pvvs>
+NSSVTSSTTSSSN         | MARK: 10011000 (get_answer)
+
+@ TODO: Consider extending the GETCHAR instruction in VVS to indicate an empty
+@       buffer instead of blocking. This would allow a character by character
+@       check without printing a slew of retry messages if the buffer is
+@       non-empty.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer address)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (buffer size)
+NSTTSSSTSN            | JSR > 100010 (get_user_string)
+
+@ Examine the first character of the user input buffer for 'y' or 'n'.
+@ If character is something else, prompt user to try again.
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+TTT                   | LOAD
+SSSSTTTTSSTN          | PUSH 121 (ASCII 'y')
+TSST                  | SUBTRACT
+NTSTSSTTSSSSSSSSSSSN  | BRZ > 10011000 00000000 (answer: yes)
+SSSTTSSSSSSSSSSSSN    | PUSH 0x3000 (USER_INPUT_BUFFER address)
+TTT                   | LOAD
+SSSSTTSTTTSN          | PUSH 110 (ASCII 'n')
+TSST                  | SUBTRACT
+NTSTSSTTSSSSSSSSSSTN  | BRZ > 10011000 00000001 (answer: no)
+NSTTTTTTTTTSSSSTSSSN  | JSR > 11111111 00001000 (problem_with_input)
+SSSSN                 | PUSH 0 (number of string substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSNTSSTTSSSN          | JMP > 10011000 (get_answer)
+
+@ User typed 'y'
+NSSVTSSTTSSSSSSSSSSSN | MARK: 10011000 00000000 (answer: yes)
+SSSTN                 | PUSH 1
+NTN                   | RTS
+
+@ User typed 'n'
+NSSVTSSTTSSSSSSSSSSTN | MARK: 10011000 00000001 (answer: no)
+SSSSN                 | PUSH 0
+NTN                   | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   print_cave_description
+@ Description:
+@   Prints information about the cave (number of rooms, etc).
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <stdio.pvvs>
+NSSVTSSTTSTTN         | MARK: 10011011 (print_cave_description)
+NSTTTTTTTTTSSSSTSTSN  | JSR > 11111111 00001010 (cave_description)
+SSSTSSSSSSSSSTSTN     | PUSH 0x1005 (number_of_arrows address)
+TTT                   | LOAD
+SSSTSSSSSSSSSSSTN     | PUSH 0x1001 (number_of_pits address)
+TTT                   | LOAD
+SSSTSSSSSSSSSSTSN     | PUSH 0x1002 (number_of_bats address)
+TTT                   | LOAD
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (number_of_tunnels address)
+TTT                   | LOAD
+SSSTSSSSSSSSSSSSN     | PUSH 0x1000 (number_of_rooms address)
+TTT                   | LOAD
+SSSTSTN               | PUSH 5 (number of substitions)
+NSTTSSSN              | JSR > 1000 (printf)
+NTN                   | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   print_room_stats
+@ Description:
+@   Prints information about current room and hints about nearby rooms.
+@ Call Stack:
+@   <empty>
+@ Return Stack:
+@   <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <wump_game.pvvs>
+#include <stdio.pvvs>
+#include <stack.pvvs>
+NSSVTSTSSSSTN         | MARK: 10100001 (print_room_stats)
+
+@ Print location and arrow quantity remaining.
+A"\n----------\n\nYou are in room %u of the cave and have %u arrows remaining.\n"
+SSSTSSSSSSSSSTSTN     | PUSH 0x1005 (number_of_arrows address)
+TTT                   | LOAD
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (player_location address)
+TTT                   | LOAD
+SSSTSN                | PUSH 2 (number of substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+
+@ Print if bats/pits/wumpus nearby.
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (player_location address)
+TTT                   | LOAD
+SNS                   | DUP
+NSTTSSTTTSSN          | JSR > 10011100 (are_bats_near)
+NTSTSTSSSSTSSSSSSSSN  | BRZ > 10100001 00000000 (no_bats)
+A"*rustle* (Bats must be nearby.)\n"
+SSSSN                 | PUSH 0 (number of substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSSVTSTSSSSTSSSSSSSSN | MARK: 10100001 00000000 (no_bats)
+SNS                   | DUP
+NSTTSSTTTSTN          | JSR > 10011101 (are_pits_near)
+NTSTSTSSSSTSSSSSSSTN  | BRZ > 10100001 00000001 (no_pits)
+A"*whoosh* (You feel a draft from nearby pits.)\n"
+SSSSN                 | PUSH 0 (number of substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSSVTSTSSSSTSSSSSSSTN | MARK: 10100001 00000001 (no_pits)
+NSTTSSTTTTSN          | JSR > 10011110 (is_wumpus_near)
+NTSTSTSSSSTSSSSSSTSN  | BRZ > 10100001 00000010 (no_wumpus)
+A"*sniff* (You smell the evil Wumpus nearby!)\n"
+SSSSN                 | PUSH 0 (number of substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+NSSVTSTSSSSTSSSSSSTSN | MARK: 10100001 00000010 (no_wumpus)
+
+@ Print a list of nearby rooms.
+A"This room contains tunnels to the following rooms:"
+SSSSN                 | PUSH 0 (number of substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+SSSTSSSSSSSSSTTSN     | PUSH 0x1006 (player_location address)
+TTT                   | LOAD
+SSSTSSSSSSSSSSTTN     | PUSH 0x1003 (number_of_links_per_room address)
+TTT                   | LOAD
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+@ Print one room on each pass through this loop.
+@ TOS> tunnel_index, room_number
+NSSVTSTSSSSTSSSSSSTTN | MARK: 10100001 00000011 (print_room_list_loop)
+A" %u"
+SSSTSTN               | PUSH 5
+NSTTTSSN              | JSR > 1100 (deepdup)
+SSSTTTN               | PUSH 7
+NSTTTSSN              | JSR > 1100 (deepdup)
+NSTTSSSTSSSN          | JSR > 10001000 (get_tunnel_destination)
+SSSTN                 | PUSH 1 (number of substitutions)
+NSTTSSSN              | JSR > 1000 (printf)
+@ Test for end of loop
+SNS                   | DUP
+NTSTSTSSSSTSSSSSTSSN  | BRZ > 10100001 00000100 (print_room_list_loop_end)
+SSSTN                 | PUSH 1
+TSST                  | SUBTRACT
+NSNTSTSSSSTSSSSSSTTN  | JMP > 10100001 00000011 (print_room_list_loop)
+@ Clean up and return.
+NSSVTSTSSSSTSSSSSTSSN | MARK: 10100001 00000100 (print_room_list_loop_end)
+SSSTSTSN              | PUSH 10 (ASCII '\n')
+TNSS                  | PUTCHAR
+SNN                   | DROP
+SNN                   | DROP
+NTN                   | RTS
+
 #endif
 #endif