#ifndef WUMP_INIT #define WUMP_INIT @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ (c) 2019 Aaron Taylor @ See LICENSE.txt file for copyright and license details. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ wump_init @ Description: @ Master function that creates a new cave, links the rooms, and populates them @ according to the options set by the user in wump_conf.pvvs. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include #include #include #include NSSVTSSSSSTSN | MARK: 10000010 (wump_init) @ Load the user-configurable options. NSTTSSSSSSTN | JSR > 10000001 (set_config_values) @ Seed the RNG. NSTTTTTTTTTSSSSSTTTN | JSR > 11111111 00000111 (please_seed_rng) SSSSN | PUSH 0 (number of string substitutions) NSTTSSSN | JSR > 1000 (printf) NSTTSSSSSTTN | JSR > 10000011 (seed_rng) @ Build the cave. NSTTSSSSTSSN | JSR > 10000100 (build_cave) @ Populate the cave. NSTTSSSSTSTN | JSR > 10000101 (populate_cave) @ Initialization is complete. NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ build_circular_tunnels @ Description: @ Builds a set of tunnels that ensures every room in the cave is connected. @ Assumes that tunnel slots 0 and 1 are set to the value -1 (unconnected). @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include #include NSSVTSSSTTTSN | MARK: 10001110 (build_circular_tunnels) @ Prepare TOS> current_room, hop_length NSTTSSSSTTTN | JSR > 10000111 (generate_cave_hop_length) SSSSN | PUSH 0 (current room) @ Have we already built a tunnel from this room? @ If so, tunnel slot 0 will not be -1. NSSVTSSSTTTSSSSSSSSSN | MARK: 10001110 00000000 (tunnel_loop) SNS | DUP SSSSN | PUSH 0 (first tunnel slot) SNT | SWAP NSTTSSSTSSSN | JSR > 10001000 (get_tunnel_destination) NTTTSSSTTTSSSSSSSTSN | BMI > 10001110 00000010 NSNTSSSTTTSSSSSSSSTN | JMP > 10001110 00000001 (loop_complete) NSSVTSSSTTTSSSSSSSTSN | MARK: 10001110 00000010 @ No tunnel yet, so start building a tunnel. @ TOS> current_room, hop_length SNS | DUP SNS | DUP SSSTSSN | PUSH 4 NSTTTSSN | JSR > 1100 (deepdup) TSSS | ADD SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = num_rooms address) TTT | LOAD TSTT | MODULO SNT | SWAP SSSSN | PUSH 0 (slot number) SNT | SWAP NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) @ One direction of the tunnel is built. Now build the other direction. SNS | DUP SSSSN | PUSH 0 (slot number) SNT | SWAP NSTTSSSTSSSN | JSR > 10001000 (get_tunnel_destination) SNT | SWAP SSSTSN | PUSH 2 NSTTTSSN | JSR > 1100 (deepdup) SSSTN | PUSH 1 SNT | SWAP NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) @ Loop again to build the next tunnel. NSNTSSSTTTSSSSSSSSSN | JMP > 10001110 00000000 (tunnel_loop) @ Clean up and return NSSVTSSSTTTSSSSSSSSTN | MARK: 10001110 00000001 (loop_complete) SNN | DROP SNN | DROP NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ get_next_tunnel_slot @ Description: @ Returns the index of next available tunnel slot for room_num, or -1 if full. @ Call Stack: @ room_num <-- TOS @ Return Stack: @ tunnel_index <-- TOS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSTSTTTN | MARK: 10010111 (get_next_tunnel_slot) @ Build the pointer: (room_num * size_of_room_struct) + 2 + ROOM_DATA_BASE @ Where the '+2' skips over the 'pits' and 'bats' booleans for this room. NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) TSSN | MULTIPLY SSSTSN | PUSH 2 TSSS | ADD SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (ROOM_DATA_BASE address) TSSS | ADD @ Save a copy of this pointer for later use when recovering the tunnel index. SNS | DUP @ Push a loop counter onto the stack. SSSSN | PUSH 0 (counter) SNT | SWAP @ Main loop - Search for an available tunnel slot. @ TOS> ptr_to_tunnel_slot, loop_counter, ptr_to_first_tunnel_slot NSSVTSSTSTTTSSSSSSSSN | MARK: 10010111 00000000 (main_loop) SNS | DUP TTT | LOAD NTTTSSTSTTTSSSSSSSTN | BMI > 10010111 00000001 (found_open_slot) @ No match. @ Increment the pointer. SSSTN | PUSH 1 TSSS | ADD @ Increment the loop counter. SNT | SWAP SSSTN | PUSH 1 TSSS | ADD @ See if we have run out of possible tunnel slots. SNS | DUP SSSTSSSSSSSSSSTTN | PUSH 0x1003 (GAME_DATA_BASE+3 = links_per_room address) TTT | LOAD TSST | SUBTRACT NTSTSSTSTTTSSSSSSTSN | BRZ > 10010111 00000010 (no_open_slots) @ There are still more slots to check. Prepare to loop again. SNT | SWAP NSNTSSTSTTTSSSSSSSSN | JMP > 10010111 00000000 (main_loop) @ No available tunnel slots for this room. NSSVTSSTSTTTSSSSSSTSN | MARK: 10010111 00000010 (no_open_slots) SNN | DROP SNN | DROP SNN | DROP SSTTN | PUSH -1 NTN | RTS @ Found an open tunnel slot. NSSVTSSTSTTTSSSSSSSTN | MARK: 10010111 00000001 (found_open_slot) @ Drop the loop counter. SNT | SWAP SNN | DROP @ Recover the tunnel slot index from the tunnel slot pointer. SNT | SWAP TSST | SUBTRACT NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ build_random_tunnels @ Description: @ Randomly builds tunnels between rooms until all tunnels slots are used. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include #include #include NSSVTSSTSTTSN | MARK: 10010110 (build_random_tunnels) @ Build a temporary data structure in the buffer residing at 0x3000. @ @ 0x3000 contains the number of elements in an array that starts at 0x3001. @ Each array element is one word long and contains the index of a room @ with open tunnel slots. @ @ This init code is here rather than a subroutine since the structure it builds @ is private to this function. @ Before looping, push the number of elements in the array (=num_rooms). @ Keep a copy of this number to use as a loop counter. SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE = num_rooms address) TTT | LOAD SNS | DUP SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) SNT | SWAP TTS | STORE @ Init loop - Populates the 'rooms with available tunnel slots' array. @ TOS> loop_counter NSSVTSSTSTTSSSSSSSTSN | MARK: 10010110 00000010 (init_loop) @ Populate one of the array entries. SNS | DUP SNS | DUP SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TSSS | ADD SNT | SWAP SSSTN | PUSH +1 TSST | SUBTRACT TTS | STORE @ Decrement the loop counter and test for end of loop. SSSTN | PUSH +1 TSST | SUBTRACT SNS | DUP NTSTSSTSTTSSSSSSSTTN | BRZ > 10010110 00000011 (init_loop_end) NSNTSSTSTTSSSSSSSTSN | JMP > 10010110 00000010 (init_loop) NSSVTSSTSTTSSSSSSSTTN | MARK: 10010110 00000011 (init_loop_end) SNN | DROP NSNTSSTSTTSSSSSSSSTN | JMP > 10010110 00000001 (main_loop) @@@@@ INIT IS COMPLETE - STACK IS EMPTY @@@@@ @ Build one random tunnel connection per pass through this loop. NSSVTSSTSTTSSSSSSSSTN | MARK: 10010110 00000001 (main_loop) @ Use 'random_number mod number_of_array_entries' to select a starting room. NSTTSSTTN | JSR > 10011 (fastrand) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD TSTT | MODULO SSSTN | PUSH 1 TSSS | ADD SNS | DUP SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TSSS | ADD TTT | LOAD @ TOS> start_room_num, start_array_index @ Now we randomly select a room for the endpoint. NSSVTSSTSTTSSSSSSTSSN | MARK: 10010110 00000100 (select_random_dst_room) NSTTSSTTN | JSR > 10011 (fastrand) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD TSTT | MODULO SSSTN | PUSH 1 TSSS | ADD SNS | DUP SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TSSS | ADD TTT | LOAD @ TOS> end_room_num, end_array_index, start_room_num, start_array_index @ Verify the endpoint room is different from the startpoint room. SNS | DUP SSSTSSN | PUSH 4 NSTTTSSN | JSR > 1100 (deepdup) TSST | SUBTRACT NTSTSSTSTTSSSSSSTSTN | BRZ > 10010110 00000101 (rooms_matched) NSNTSSTSTTSSSSSSTTSN | JMP > 10010110 00000110 (connect_rooms) @ The rooms matched. Drop the selected destination room and try again. NSSVTSSTSTTSSSSSSTSTN | MARK: 10010110 00000101 (rooms_matched) SNN | DROP SNN | DROP NSNTSSTSTTSSSSSSTSSN | JMP > 10010110 00000100 (select_random_dst_room) @ TOS> end_room_num, end_array_index, start_room_num, start_array_index @ The rooms are different. Time to build a connection between them. NSSVTSSTSTTSSSSSSTTSN | MARK: 10010110 00000110 (connect_rooms) @ First build a one-way tunnel. SSSTTN | PUSH 3 NSTTTSSN | JSR > 1100 (deepdup) SSSTSN | PUSH 2 NSTTTSSN | JSR > 1100 (deepdup) SNS | DUP NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) SNT | SWAP NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) @ Then make it a two-way tunnel. SNS | DUP SSSTSSN | PUSH 4 NSTTTSSN | JSR > 1100 (deepdup) SNS | DUP NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) SNT | SWAP NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) @ TOS> end_room_num, end_array_index, start_room_num, start_array_index @ If that was the last tunnel slot in either room, remove it @ from the 'rooms_with_available_tunnel_slots' array. NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) NTTTSSTSTTSSSSSSTTTN | BMI > 10010110 00000111 (remove_empty_room_1) SNN | DROP NSNTSSTSTTSSSSSTSSSN | JMP > 10010110 00001000 (check_second_room) NSSVTSSTSTTSSSSSSTTTN | MARK: 10010110 00000111 (remove_empty_room_1) SNS | DUP NSTTSSTSTTSSSSSTTSSN | JSR > 10010110 00001100 (remove_element_from_array) SSSTTN | PUSH 3 NSTTTSSN | JSR > 1100 (deepdup) TSST | SUBTRACT NTTTSSTSTTSSSSSTTSTN | BMI > 10010110 00001101 (update_second_room_index) NSNTSSTSTTSSSSSTSSSN | JMP > 10010110 00001000 (check_second_room) NSSVTSSTSTTSSSSSTTSTN | MARK: 10010110 00001101 (update_second_room_index) SNT | SWAP SSSTN | PUSH 1 TSST | SUBTRACT SNT | SWAP NSSVTSSTSTTSSSSSTSSSN | MARK: 10010110 00001000 (check_second_room) NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) NTTTSSTSTTSSSSSTSSTN | BMI > 10010110 00001001 (remove_empty_room_2) SNN | DROP NSNTSSTSTTSSSSSTSTSN | JMP > 10010110 00001010 (main_loop_end_test) NSSVTSSTSTTSSSSSTSSTN | MARK: 10010110 00001001 (remove_empty_room_2) NSTTSSTSTTSSSSSTTSSN | JSR > 10010110 00001100 (remove_element_from_array) @ If the array is now empty or only contains one room, return. @ Otherwise, loop again and build another random tunnel. NSSVTSSTSTTSSSSSTSTSN | MARK: 10010110 00001010 (main_loop_end_test) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD SSSTSN | PUSH 2 TSST | SUBTRACT NTTTSSTSTTSSSSSTSTTN | BMI > 10010110 00001011 (return) NSNTSSTSTTSSSSSSSSTN | JMP > 10010110 00000001 (main_loop) NSSVTSSTSTTSSSSSTSTTN | MARK: 10010110 00001011 (return) NTN | RTS @ A private subroutine to remove one element from the temp array. @ Consumes the array index from TOS. NSSVTSSTSTTSSSSSTTSSN | MARK: 10010110 00001100 (remove_element_from_array) @ First, stash a copy of the array index immediately after the temporary array. @ This allows us to find it using the num_array_elements for use with spew @ after slurp has filled the stack with a variable number of elements. SNS | DUP SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD TSSS | ADD SSSTN | PUSH 1 TSSS | ADD SNT | SWAP TTS | STORE @ Now slurp and spew the array to delete the desired element. SSSTN | PUSH 1 TSSS | ADD SNS | DUP @ TOS> index+1, index+1 SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD SNT | SWAP TSST | SUBTRACT @ Special case: deleting last element of array means no need to delete. SNS | DUP NTTTSSTSTTSSSSSTTTSN | BMI > 10010110 00001110 (deleting_last_element) NSNTSSTSTTSSSSSTTTTN | JMP > 10010110 00001111 (not_deleting_last_element) NSSVTSSTSTTSSSSSTTTSN | MARK: 10010110 00001110 (deleting_last_element) SNN | DROP SNN | DROP NSNTSSTSTTSSSSTSSSSN | JMP > 10010110 00010000 (decrement_array_counter) NSSVTSSTSTTSSSSSTTTTN | MARK: 10010110 00001111 (not_deleting_last_element) SNT | SWAP @ TOS> index+1, count=num_array_elements-(index+1) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TSSS | ADD SNT | SWAP @ TOS> count=num_array_elements-(index+1), address=0x3000+index+1 NSTTTTTSN | JSR > 11110 (slurp) @ Recover the array index that we stashed on the heap. SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD TSSS | ADD SSSTN | PUSH 1 TSSS | ADD TTT | LOAD @ TOS> index SNS | DUP SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TSSS | ADD SNT | SWAP @ TOS> index, address=0x3000+index SSSTN | PUSH 1 TSSS | ADD SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD SNT | SWAP TSST | SUBTRACT @ TOS> count = num_array_elements-(index+1), address=0x3000+index NSTTTTTTN | JSR > 11111 (spew) @ Decrement the array element counter. NSSVTSSTSTTSSSSTSSSSN | MARK: 10010110 00010000 (decrement_array_counter) SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) TTT | LOAD SSSTN | PUSH 1 TSST | SUBTRACT SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) SNT | SWAP TTS | STORE NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ build_cave @ Description: @ Clears the cave data structure on the heap and builds new tunnels. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ NSSVTSSSSTSSN | MARK: 10000100 (build_cave) NSTTSSSSTTSN | JSR > 10000110 (clear_cave_data) NSTTSSSTTTSN | JSR > 10001110 (build_circular_tunnels) NSTTSSTSTTSN | JSR > 10010110 (build_random_tunnels) NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ set_tunnel_destination @ Description: @ Sets 'slot' of 'room_number' to point to 'dst_room_number'. @ Call Stack: @ dst_room_number @ slot @ room_number <-- TOS @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSSTSSTN | MARK: 10001001 (set_tunnel_destination) @ The pointer we seek is: @ (room_number * room_struct_size) + 2 + slot + ROOM_DATA_BASE @ Where the '+2' accounts for the pit and bat booleans. NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) TSSN | MULTIPLY SSSTSN | PUSH +2 TSSS | ADD TSSS | ADD SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (ROOM_DATA_BASE address) TSSS | ADD SNT | SWAP TTS | STORE NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ generate_cave_hop_length @ Description: @ In order to ensure cave is fully connected, generate a number, 'hop_length', @ that is relatively prime to the number of rooms in the cave. @ Call Stack: @ @ Return Stack: @ hop_length @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSSSTTTN | MARK: 10000111 (generate_cave_hop_length) NSTTSSSTSTSN | JSR > 10001010 (get_random_room) @ Check for gcd(hop_length,num_rooms) = 1. SNS | DUP SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = num_rooms address) TTT | LOAD NSTTSSTSN | JSR > 10010 (gcd) SSSTN | PUSH +1 TSST | SUBTRACT NTSTSSSSTTTSSSSSSSSN | BRZ > 10000111 00000000 SNN | DROP NSNTSSSSTTTN | JMP > 10000111 (generate_cave_hop_length) NSSVTSSSSTTTSSSSSSSSN | MARK: 10000111 00000000 NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ clear_cave_data @ Description: @ Writes -1 over the entire cave data array. @ This ensures each room starts unconnected. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include #include NSSVTSSSSTTSN | MARK: 10000110 (clear_cave_data) SSTTN | PUSH -1 (pattern) SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (ROOM_DATA_BASE address) SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE address) TTT | LOAD NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) TSSN | MULTIPLY NSTTTSSSN | JSR > 11000 (memset) NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ get_random_room @ Description: @ Returns a valid room number @ Call Stack: @ @ Return Stack: @ room_num <-- TOS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSSTSTSN | MARK: 10001010 (get_random_room) NSTTSSTTN | JSR > 10011 (fastrand) SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = num_rooms address) TTT | LOAD TSTT | MODULO NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ set_bats @ Description: @ Set the 'bats' boolean for a specific room. @ Call Stack: @ value (0 or 1) @ room_number @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSTSSSSN | MARK: 10010000 (set_bats) @ We seek the pointer: @ (room_number * room_struct_size) + 1 + ROOM_DATA_BASE @ where '+1' accounts for the offset of the bat boolean in the desired room. NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) TSSN | MULTIPLY SSSTN | PUSH +1 TSSS | ADD SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (GAME_DATA_BASE address) TSSS | ADD SNT | SWAP TTS | STORE NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ set_pits @ Description: @ Set the 'pits' boolean for a specific room. @ Call Stack: @ value (0 or 1) @ room_number @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSTSSSTN | MARK: 10010001 (set_pits) @ We seek the pointer: @ (room_number * room_struct_size) + 0 + ROOM_DATA_BASE @ where '+0' accounts for the offset of the pit boolean in the desired room. NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) TSSN | MULTIPLY SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (GAME_DATA_BASE address) TSSS | ADD SNT | SWAP TTS | STORE NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ reset_cave_population @ Description: @ Remove all bats and pits from the cave. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ NSSVTSSTSSTSN | MARK: 10010010 (reset_cave_population) @ Clear the bat and pit booleans by setting every room to false(=0). @ First prepare a loop index. SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = number_of_rooms address) TTT | LOAD SSSTN | PUSH 1 TSST | SUBTRACT NSSVTSSTSSTSSSSSSSSSN | MARK: 10010010 00000000 (empty_cave_loop) @ Scare all the bats out of the room. SNS | DUP SSSSN | PUSH 0 (false) SNT | SWAP NSTTSSTSSSSN | JSR > 10010000 (set_bats) @ Fill any pits. SNS | DUP SSSSN | PUSH 0 (false) SNT | SWAP NSTTSSTSSSTN | JSR > 10010001 (set_pits) @ Decrement loop counter and test for end of loop. SSSTN | PUSH 1 TSST | SUBTRACT SNS | DUP NTTTSSTSSTSSSSSSSSTN | BMI > 10010010 00000001 (empty_cave_loop_end) NSNTSSTSSTSSSSSSSSSN | JMP > 10010010 00000000 (empty_cave_loop) @ Loop is complete. Clean up and return. NSSVTSSTSSTSSSSSSSSTN | MARK: 10010010 00000001 (empty_cave_loop_end) SNN | DROP NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ populate_bats @ Description: @ Randomly place a user-defined number of bats in the cave. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSTSSTTN | MARK: 10010011 (populate_bats) @ First prepare a loop index. SSSTSSSSSSSSSSTSN | PUSH 0x1002 (GAME_DATA_BASE+2 = number_of_bats address) TTT | LOAD SSSTN | PUSH 1 TSST | SUBTRACT @ Find a random room that does not already contain bats. NSSVTSSTSSTTSSSSSSTSN | MARK: 10010011 00000010 (place_bats) NSTTSSSTSTSN | JSR > 10001010 (get_random_room) SNS | DUP NSTTSSSTTSSN | JSR > 10001100 (room_has_bats) NTSTSSTSSTTSSSSSSTTN | BRZ > 10010011 00000011 (no_bats_in_room) SNN | DROP NSNTSSTSSTTSSSSSSTSN | JMP > 10010011 00000010 (place_bats) @ Room is empty. Place bats. NSSVTSSTSSTTSSSSSSTTN | MARK: 10010011 00000011 (no_bats_in_room) SSSTN | PUSH 1 (true) SNT | SWAP NSTTSSTSSSSN | JSR > 10010000 (set_bats) @ Decrement loop counter and test for loop completion. SSSTN | PUSH 1 TSST | SUBTRACT SNS | DUP NTTTSSTSSTTSSSSSTSSN | BMI > 10010011 00000100 (place_bats_loop_end) NSNTSSTSSTTSSSSSSTSN | JMP > 10010011 00000010 (place_bats) @ Loop is complete. Clean up and return. NSSVTSSTSSTTSSSSSTSSN | MARK: 10010011 00000100 (place_bats_loop_end) SNN | DROP NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ populate_pits @ Description: @ Randomly place a user-defined number of pits in the cave. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include NSSVTSSTSTSSN | MARK: 10010100 (populate_pits) @ First prepare a loop index. SSSTSSSSSSSSSSSTN | PUSH 0x1001 (GAME_DATA_BASE+1 = number_of_pits address) TTT | LOAD SSSTN | PUSH 1 TSST | SUBTRACT @ Find a random room that does not already contain pits. NSSVTSSTSTSSSSSSSSTSN | MARK: 10010100 00000010 (place_pits) NSTTSSSTSTSN | JSR > 10001010 (get_random_room) SNS | DUP NSTTSSSTTSTN | JSR > 10001101 (room_has_pits) NTSTSSTSTSSSSSSSSTTN | BRZ > 10010100 00000011 (no_pits_in_room) SNN | DROP NSNTSSTSTSSSSSSSSTSN | JMP > 10010100 00000010 (place_pits) @ Room is empty. Place pits. NSSVTSSTSTSSSSSSSSTTN | MARK: 10010100 00000011 (no_pits_in_room) SSSTN | PUSH 1 (true) SNT | SWAP NSTTSSTSSSTN | JSR > 10010001 (set_pits) @ Decrement loop counter and test for loop completion. SSSTN | PUSH 1 TSST | SUBTRACT SNS | DUP NTTTSSTSTSSSSSSSTSSN | BMI > 10010100 00000100 (place_pits_loop_end) NSNTSSTSTSSSSSSSSTSN | JMP > 10010100 00000010 (place_pits) @ Loop is complete. Clean up and return. NSSVTSSTSTSSSSSSSTSSN | MARK: 10010100 00000100 (place_pits_loop_end) SNN | DROP NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ place_player @ Description: @ Place the player in a suitable starting room. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ NSSVTSSTSTSTN | MARK: 10010101 (place_player) @ Find out where the wumpus is located. SSSTSSSSSSSSSTTTN | PUSH 0x1007 (GAME_DATA_BASE+7 = wumpus_room address) TTT | LOAD @ Place the player in a different room than the wumpus. NSSVTSSTSTSTSSSSSSSSN | MARK: 10010101 00000000 (place_player_loop) NSTTSSSTSTSN | JSR > 10001010 (get_random_room) SNT | SWAP SNS | DUP SSSTTN | PUSH 3 NSTTTSSN | JSR > 1100 (deepdup) @ TOS> rand_room, wump_room, wump_room, rand_room TSST | SUBTRACT NTSTSSTSTSTSSSSSSSTN | BRZ > 10010101 00000001 (same_room) NSNTSSTSTSTSSSSSSTSN | JMP > 10010101 00000010 (different_rooms) NSSVTSSTSTSTSSSSSSSTN | MARK: 10010101 00000001 (same_room) SNN | DROP NSNTSSTSTSTSSSSSSSSN | JMP > 10010101 00000000 (place_player_loop) NSSVTSSTSTSTSSSSSSTSN | MARK: 10010101 00000010 (different_rooms) SNN | DROP SSSTSSSSSSSSSTTSN | PUSH 0x1006 (GAME_DATA_BASE+6 = player_room address) SNT | SWAP TTS | STORE NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: @ populate_cave @ Description: @ Populate the cave with various creatures and features. @ Call Stack: @ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ NSSVTSSSSTSTN | MARK: 10000101 (populate_cave) @ Initialize the cave to an unpopulated state. NSTTSSTSSTSN | JSR > 10010010 (reset_cave_population) @ Place bats in the now-empty cave. NSTTSSTSSTTN | JSR > 10010011 (populate_bats) @ Place pits in the now-empty cave. NSTTSSTSTSSN | JSR > 10010100 (populate_pits) @ Place the wumpus. SSSTSSSSSSSSSTTTN | PUSH 0x1007 (GAME_DATA_BASE+7 = wumpus_room address) NSTTSSSTSTSN | JSR > 10001010 (get_random_room) TTS | STORE @ Place the player. NSTTSSTSTSTN | JSR > 10010101 (place_player) NTN | RTS #endif