Commit | Line | Data |
---|---|---|
2da74194 AT |
1 | #ifndef WUMP_INIT |
2 | #define WUMP_INIT | |
3 | ||
4 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
5 | @ (c) 2019 Aaron Taylor <ataylor at subgeniuskitty dot com> | |
6 | @ See LICENSE.txt file for copyright and license details. | |
7 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
8 | ||
9 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
10 | @ Name: | |
11 | @ wump_init | |
12 | @ Description: | |
13 | @ Master function that creates a new cave, links the rooms, and populates them | |
14 | @ according to the options set by the user in wump_conf.pvvs. | |
15 | @ Call Stack: | |
16 | @ <empty> | |
17 | @ Return Stack: | |
18 | @ <empty> | |
19 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
20 | #include <stdio.pvvs> | |
21 | #include <wump_conf.pvvs> | |
22 | #include <wump_strings.pvvs> | |
310931d2 | 23 | #include <wump_game.pvvs> |
2da74194 AT |
24 | NSSVTSSSSSTSN | MARK: 10000010 (wump_init) |
25 | ||
26 | @ Load the user-configurable options. | |
27 | NSTTSSSSSSTN | JSR > 10000001 (set_config_values) | |
28 | ||
29 | @ Seed the RNG. | |
30 | NSTTTTTTTTTSSSSSTTTN | JSR > 11111111 00000111 (please_seed_rng) | |
31 | SSSSN | PUSH 0 (number of string substitutions) | |
32 | NSTTSSSN | JSR > 1000 (printf) | |
33 | NSTTSSSSSTTN | JSR > 10000011 (seed_rng) | |
34 | ||
35 | @ Build the cave. | |
36 | NSTTSSSSTSSN | JSR > 10000100 (build_cave) | |
37 | ||
38 | @ Populate the cave. | |
39 | NSTTSSSSTSTN | JSR > 10000101 (populate_cave) | |
40 | ||
41 | @ Initialization is complete. | |
42 | NTN | RTS | |
43 | ||
44 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
45 | @ Name: | |
46 | @ build_circular_tunnels | |
47 | @ Description: | |
48 | @ Builds a set of tunnels that ensures every room in the cave is connected. | |
49 | @ Assumes that tunnel slots 0 and 1 are set to the value -1 (unconnected). | |
50 | @ Call Stack: | |
51 | @ <empty> | |
52 | @ Return Stack: | |
53 | @ <empty> | |
54 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
55 | #include <stack.pvvs> | |
56 | #include <wump_game.pvvs> | |
57 | NSSVTSSSTTTSN | MARK: 10001110 (build_circular_tunnels) | |
58 | ||
59 | @ Prepare TOS> current_room, hop_length | |
60 | NSTTSSSSTTTN | JSR > 10000111 (generate_cave_hop_length) | |
61 | SSSSN | PUSH 0 (current room) | |
62 | ||
63 | @ Have we already built a tunnel from this room? | |
64 | @ If so, tunnel slot 0 will not be -1. | |
65 | NSSVTSSSTTTSSSSSSSSSN | MARK: 10001110 00000000 (tunnel_loop) | |
66 | SNS | DUP | |
67 | SSSSN | PUSH 0 (first tunnel slot) | |
68 | SNT | SWAP | |
69 | NSTTSSSTSSSN | JSR > 10001000 (get_tunnel_destination) | |
70 | NTTTSSSTTTSSSSSSSTSN | BMI > 10001110 00000010 | |
71 | NSNTSSSTTTSSSSSSSSTN | JMP > 10001110 00000001 (loop_complete) | |
72 | NSSVTSSSTTTSSSSSSSTSN | MARK: 10001110 00000010 | |
73 | @ No tunnel yet, so start building a tunnel. | |
74 | @ TOS> current_room, hop_length | |
75 | SNS | DUP | |
76 | SNS | DUP | |
77 | SSSTSSN | PUSH 4 | |
78 | NSTTTSSN | JSR > 1100 (deepdup) | |
79 | TSSS | ADD | |
80 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = num_rooms address) | |
81 | TTT | LOAD | |
82 | TSTT | MODULO | |
83 | SNT | SWAP | |
84 | SSSSN | PUSH 0 (slot number) | |
85 | SNT | SWAP | |
86 | NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) | |
87 | @ One direction of the tunnel is built. Now build the other direction. | |
88 | SNS | DUP | |
89 | SSSSN | PUSH 0 (slot number) | |
90 | SNT | SWAP | |
91 | NSTTSSSTSSSN | JSR > 10001000 (get_tunnel_destination) | |
92 | SNT | SWAP | |
93 | SSSTSN | PUSH 2 | |
94 | NSTTTSSN | JSR > 1100 (deepdup) | |
95 | SSSTN | PUSH 1 | |
96 | SNT | SWAP | |
97 | NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) | |
98 | @ Loop again to build the next tunnel. | |
99 | NSNTSSSTTTSSSSSSSSSN | JMP > 10001110 00000000 (tunnel_loop) | |
100 | ||
101 | @ Clean up and return | |
102 | NSSVTSSSTTTSSSSSSSSTN | MARK: 10001110 00000001 (loop_complete) | |
103 | SNN | DROP | |
104 | SNN | DROP | |
105 | NTN | RTS | |
106 | ||
107 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
108 | @ Name: | |
109 | @ get_next_tunnel_slot | |
110 | @ Description: | |
111 | @ Returns the index of next available tunnel slot for room_num, or -1 if full. | |
112 | @ Call Stack: | |
113 | @ room_num <-- TOS | |
114 | @ Return Stack: | |
115 | @ tunnel_index <-- TOS | |
116 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
117 | #include <wump_game.pvvs> | |
118 | NSSVTSSTSTTTN | MARK: 10010111 (get_next_tunnel_slot) | |
119 | ||
120 | @ Build the pointer: (room_num * size_of_room_struct) + 2 + ROOM_DATA_BASE | |
121 | @ Where the '+2' skips over the 'pits' and 'bats' booleans for this room. | |
122 | NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) | |
123 | TSSN | MULTIPLY | |
124 | SSSTSN | PUSH 2 | |
125 | TSSS | ADD | |
126 | SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (ROOM_DATA_BASE address) | |
127 | TSSS | ADD | |
128 | ||
129 | @ Save a copy of this pointer for later use when recovering the tunnel index. | |
130 | SNS | DUP | |
131 | ||
132 | @ Push a loop counter onto the stack. | |
133 | SSSSN | PUSH 0 (counter) | |
134 | SNT | SWAP | |
135 | ||
136 | @ Main loop - Search for an available tunnel slot. | |
137 | @ TOS> ptr_to_tunnel_slot, loop_counter, ptr_to_first_tunnel_slot | |
138 | NSSVTSSTSTTTSSSSSSSSN | MARK: 10010111 00000000 (main_loop) | |
139 | SNS | DUP | |
140 | TTT | LOAD | |
141 | NTTTSSTSTTTSSSSSSSTN | BMI > 10010111 00000001 (found_open_slot) | |
142 | @ No match. | |
143 | @ Increment the pointer. | |
144 | SSSTN | PUSH 1 | |
145 | TSSS | ADD | |
146 | @ Increment the loop counter. | |
147 | SNT | SWAP | |
148 | SSSTN | PUSH 1 | |
149 | TSSS | ADD | |
150 | @ See if we have run out of possible tunnel slots. | |
151 | SNS | DUP | |
152 | SSSTSSSSSSSSSSTTN | PUSH 0x1003 (GAME_DATA_BASE+3 = links_per_room address) | |
153 | TTT | LOAD | |
154 | TSST | SUBTRACT | |
155 | NTSTSSTSTTTSSSSSSTSN | BRZ > 10010111 00000010 (no_open_slots) | |
156 | @ There are still more slots to check. Prepare to loop again. | |
157 | SNT | SWAP | |
158 | NSNTSSTSTTTSSSSSSSSN | JMP > 10010111 00000000 (main_loop) | |
159 | ||
160 | @ No available tunnel slots for this room. | |
161 | NSSVTSSTSTTTSSSSSSTSN | MARK: 10010111 00000010 (no_open_slots) | |
162 | SNN | DROP | |
163 | SNN | DROP | |
164 | SNN | DROP | |
165 | SSTTN | PUSH -1 | |
166 | NTN | RTS | |
167 | ||
168 | @ Found an open tunnel slot. | |
169 | NSSVTSSTSTTTSSSSSSSTN | MARK: 10010111 00000001 (found_open_slot) | |
170 | @ Drop the loop counter. | |
171 | SNT | SWAP | |
172 | SNN | DROP | |
173 | @ Recover the tunnel slot index from the tunnel slot pointer. | |
174 | SNT | SWAP | |
175 | TSST | SUBTRACT | |
176 | NTN | RTS | |
177 | ||
178 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
179 | @ Name: | |
180 | @ build_random_tunnels | |
181 | @ Description: | |
182 | @ Randomly builds tunnels between rooms until all tunnels slots are used. | |
183 | @ Call Stack: | |
184 | @ <empty> | |
185 | @ Return Stack: | |
186 | @ <empty> | |
187 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
188 | #include <heap.pvvs> | |
189 | #include <math.pvvs> | |
190 | #include <stack.pvvs> | |
191 | NSSVTSSTSTTSN | MARK: 10010110 (build_random_tunnels) | |
192 | ||
193 | @ Build a temporary data structure in the buffer residing at 0x3000. | |
194 | @ | |
195 | @ 0x3000 contains the number of elements in an array that starts at 0x3001. | |
196 | @ Each array element is one word long and contains the index of a room | |
197 | @ with open tunnel slots. | |
198 | @ | |
199 | @ This init code is here rather than a subroutine since the structure it builds | |
200 | @ is private to this function. | |
201 | @ Before looping, push the number of elements in the array (=num_rooms). | |
202 | @ Keep a copy of this number to use as a loop counter. | |
203 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE = num_rooms address) | |
204 | TTT | LOAD | |
205 | SNS | DUP | |
206 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
207 | SNT | SWAP | |
208 | TTS | STORE | |
209 | @ Init loop - Populates the 'rooms with available tunnel slots' array. | |
210 | @ TOS> loop_counter | |
211 | NSSVTSSTSTTSSSSSSSTSN | MARK: 10010110 00000010 (init_loop) | |
212 | @ Populate one of the array entries. | |
213 | SNS | DUP | |
214 | SNS | DUP | |
215 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
216 | TSSS | ADD | |
217 | SNT | SWAP | |
218 | SSSTN | PUSH +1 | |
219 | TSST | SUBTRACT | |
220 | TTS | STORE | |
221 | @ Decrement the loop counter and test for end of loop. | |
222 | SSSTN | PUSH +1 | |
223 | TSST | SUBTRACT | |
224 | SNS | DUP | |
225 | NTSTSSTSTTSSSSSSSTTN | BRZ > 10010110 00000011 (init_loop_end) | |
226 | NSNTSSTSTTSSSSSSSTSN | JMP > 10010110 00000010 (init_loop) | |
227 | NSSVTSSTSTTSSSSSSSTTN | MARK: 10010110 00000011 (init_loop_end) | |
228 | SNN | DROP | |
229 | NSNTSSTSTTSSSSSSSSTN | JMP > 10010110 00000001 (main_loop) | |
230 | ||
231 | @@@@@ INIT IS COMPLETE - STACK IS EMPTY @@@@@ | |
232 | ||
233 | @ Build one random tunnel connection per pass through this loop. | |
234 | NSSVTSSTSTTSSSSSSSSTN | MARK: 10010110 00000001 (main_loop) | |
235 | @ Use 'random_number mod number_of_array_entries' to select a starting room. | |
83a8624e | 236 | NSTTSSTTN | JSR > 10011 (fastrand) |
2da74194 AT |
237 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) |
238 | TTT | LOAD | |
239 | TSTT | MODULO | |
240 | SSSTN | PUSH 1 | |
241 | TSSS | ADD | |
242 | SNS | DUP | |
243 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
244 | TSSS | ADD | |
245 | TTT | LOAD | |
246 | @ TOS> start_room_num, start_array_index | |
247 | @ Now we randomly select a room for the endpoint. | |
248 | NSSVTSSTSTTSSSSSSTSSN | MARK: 10010110 00000100 (select_random_dst_room) | |
83a8624e | 249 | NSTTSSTTN | JSR > 10011 (fastrand) |
2da74194 AT |
250 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) |
251 | TTT | LOAD | |
252 | TSTT | MODULO | |
253 | SSSTN | PUSH 1 | |
254 | TSSS | ADD | |
255 | SNS | DUP | |
256 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
257 | TSSS | ADD | |
258 | TTT | LOAD | |
259 | @ TOS> end_room_num, end_array_index, start_room_num, start_array_index | |
260 | @ Verify the endpoint room is different from the startpoint room. | |
261 | SNS | DUP | |
262 | SSSTSSN | PUSH 4 | |
263 | NSTTTSSN | JSR > 1100 (deepdup) | |
264 | TSST | SUBTRACT | |
265 | NTSTSSTSTTSSSSSSTSTN | BRZ > 10010110 00000101 (rooms_matched) | |
266 | NSNTSSTSTTSSSSSSTTSN | JMP > 10010110 00000110 (connect_rooms) | |
267 | @ The rooms matched. Drop the selected destination room and try again. | |
268 | NSSVTSSTSTTSSSSSSTSTN | MARK: 10010110 00000101 (rooms_matched) | |
269 | SNN | DROP | |
270 | SNN | DROP | |
271 | NSNTSSTSTTSSSSSSTSSN | JMP > 10010110 00000100 (select_random_dst_room) | |
272 | @ TOS> end_room_num, end_array_index, start_room_num, start_array_index | |
273 | @ The rooms are different. Time to build a connection between them. | |
274 | NSSVTSSTSTTSSSSSSTTSN | MARK: 10010110 00000110 (connect_rooms) | |
275 | @ First build a one-way tunnel. | |
276 | SSSTTN | PUSH 3 | |
277 | NSTTTSSN | JSR > 1100 (deepdup) | |
278 | SSSTSN | PUSH 2 | |
279 | NSTTTSSN | JSR > 1100 (deepdup) | |
280 | SNS | DUP | |
281 | NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) | |
282 | SNT | SWAP | |
283 | NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) | |
284 | @ Then make it a two-way tunnel. | |
285 | SNS | DUP | |
286 | SSSTSSN | PUSH 4 | |
287 | NSTTTSSN | JSR > 1100 (deepdup) | |
288 | SNS | DUP | |
289 | NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) | |
290 | SNT | SWAP | |
291 | NSTTSSSTSSTN | JSR > 10001001 (set_tunnel_destination) | |
292 | @ TOS> end_room_num, end_array_index, start_room_num, start_array_index | |
293 | @ If that was the last tunnel slot in either room, remove it | |
294 | @ from the 'rooms_with_available_tunnel_slots' array. | |
295 | NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) | |
296 | NTTTSSTSTTSSSSSSTTTN | BMI > 10010110 00000111 (remove_empty_room_1) | |
297 | SNN | DROP | |
298 | NSNTSSTSTTSSSSSTSSSN | JMP > 10010110 00001000 (check_second_room) | |
299 | NSSVTSSTSTTSSSSSSTTTN | MARK: 10010110 00000111 (remove_empty_room_1) | |
300 | SNS | DUP | |
301 | NSTTSSTSTTSSSSSTTSSN | JSR > 10010110 00001100 (remove_element_from_array) | |
302 | SSSTTN | PUSH 3 | |
303 | NSTTTSSN | JSR > 1100 (deepdup) | |
304 | TSST | SUBTRACT | |
305 | NTTTSSTSTTSSSSSTTSTN | BMI > 10010110 00001101 (update_second_room_index) | |
306 | NSNTSSTSTTSSSSSTSSSN | JMP > 10010110 00001000 (check_second_room) | |
307 | NSSVTSSTSTTSSSSSTTSTN | MARK: 10010110 00001101 (update_second_room_index) | |
308 | SNT | SWAP | |
309 | SSSTN | PUSH 1 | |
310 | TSST | SUBTRACT | |
311 | SNT | SWAP | |
312 | NSSVTSSTSTTSSSSSTSSSN | MARK: 10010110 00001000 (check_second_room) | |
313 | NSTTSSTSTTTN | JSR > 10010111 (get_next_tunnel_slot) | |
314 | NTTTSSTSTTSSSSSTSSTN | BMI > 10010110 00001001 (remove_empty_room_2) | |
315 | SNN | DROP | |
316 | NSNTSSTSTTSSSSSTSTSN | JMP > 10010110 00001010 (main_loop_end_test) | |
317 | NSSVTSSTSTTSSSSSTSSTN | MARK: 10010110 00001001 (remove_empty_room_2) | |
318 | NSTTSSTSTTSSSSSTTSSN | JSR > 10010110 00001100 (remove_element_from_array) | |
319 | @ If the array is now empty or only contains one room, return. | |
320 | @ Otherwise, loop again and build another random tunnel. | |
321 | NSSVTSSTSTTSSSSSTSTSN | MARK: 10010110 00001010 (main_loop_end_test) | |
322 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
323 | TTT | LOAD | |
324 | SSSTSN | PUSH 2 | |
325 | TSST | SUBTRACT | |
326 | NTTTSSTSTTSSSSSTSTTN | BMI > 10010110 00001011 (return) | |
327 | NSNTSSTSTTSSSSSSSSTN | JMP > 10010110 00000001 (main_loop) | |
328 | NSSVTSSTSTTSSSSSTSTTN | MARK: 10010110 00001011 (return) | |
329 | NTN | RTS | |
330 | ||
331 | @ A private subroutine to remove one element from the temp array. | |
332 | @ Consumes the array index from TOS. | |
333 | NSSVTSSTSTTSSSSSTTSSN | MARK: 10010110 00001100 (remove_element_from_array) | |
334 | @ First, stash a copy of the array index immediately after the temporary array. | |
335 | @ This allows us to find it using the num_array_elements for use with spew | |
336 | @ after slurp has filled the stack with a variable number of elements. | |
337 | SNS | DUP | |
338 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
339 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
340 | TTT | LOAD | |
341 | TSSS | ADD | |
342 | SSSTN | PUSH 1 | |
343 | TSSS | ADD | |
344 | SNT | SWAP | |
345 | TTS | STORE | |
346 | @ Now slurp and spew the array to delete the desired element. | |
347 | SSSTN | PUSH 1 | |
348 | TSSS | ADD | |
349 | SNS | DUP | |
350 | @ TOS> index+1, index+1 | |
351 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
352 | TTT | LOAD | |
353 | SNT | SWAP | |
354 | TSST | SUBTRACT | |
355 | @ Special case: deleting last element of array means no need to delete. | |
356 | SNS | DUP | |
357 | NTTTSSTSTTSSSSSTTTSN | BMI > 10010110 00001110 (deleting_last_element) | |
358 | NSNTSSTSTTSSSSSTTTTN | JMP > 10010110 00001111 (not_deleting_last_element) | |
359 | NSSVTSSTSTTSSSSSTTTSN | MARK: 10010110 00001110 (deleting_last_element) | |
360 | SNN | DROP | |
361 | SNN | DROP | |
362 | NSNTSSTSTTSSSSTSSSSN | JMP > 10010110 00010000 (decrement_array_counter) | |
363 | NSSVTSSTSTTSSSSSTTTTN | MARK: 10010110 00001111 (not_deleting_last_element) | |
364 | SNT | SWAP | |
365 | @ TOS> index+1, count=num_array_elements-(index+1) | |
366 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
367 | TSSS | ADD | |
368 | SNT | SWAP | |
369 | @ TOS> count=num_array_elements-(index+1), address=0x3000+index+1 | |
370 | NSTTTTTSN | JSR > 11110 (slurp) | |
371 | @ Recover the array index that we stashed on the heap. | |
372 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
373 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
374 | TTT | LOAD | |
375 | TSSS | ADD | |
376 | SSSTN | PUSH 1 | |
377 | TSSS | ADD | |
378 | TTT | LOAD | |
379 | @ TOS> index | |
380 | SNS | DUP | |
381 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
382 | TSSS | ADD | |
383 | SNT | SWAP | |
384 | @ TOS> index, address=0x3000+index | |
385 | SSSTN | PUSH 1 | |
386 | TSSS | ADD | |
387 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
388 | TTT | LOAD | |
389 | SNT | SWAP | |
390 | TSST | SUBTRACT | |
391 | @ TOS> count = num_array_elements-(index+1), address=0x3000+index | |
392 | NSTTTTTTN | JSR > 11111 (spew) | |
393 | @ Decrement the array element counter. | |
394 | NSSVTSSTSTTSSSSTSSSSN | MARK: 10010110 00010000 (decrement_array_counter) | |
395 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
396 | TTT | LOAD | |
397 | SSSTN | PUSH 1 | |
398 | TSST | SUBTRACT | |
399 | SSSTTSSSSSSSSSSSSN | PUSH 0x3000 (BUFFER) | |
400 | SNT | SWAP | |
401 | TTS | STORE | |
402 | NTN | RTS | |
403 | ||
404 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
405 | @ Name: | |
406 | @ build_cave | |
407 | @ Description: | |
408 | @ Clears the cave data structure on the heap and builds new tunnels. | |
409 | @ Call Stack: | |
410 | @ <empty> | |
411 | @ Return Stack: | |
412 | @ <empty> | |
413 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
414 | NSSVTSSSSTSSN | MARK: 10000100 (build_cave) | |
415 | NSTTSSSSTTSN | JSR > 10000110 (clear_cave_data) | |
416 | NSTTSSSTTTSN | JSR > 10001110 (build_circular_tunnels) | |
417 | NSTTSSTSTTSN | JSR > 10010110 (build_random_tunnels) | |
418 | NTN | RTS | |
419 | ||
420 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
421 | @ Name: | |
422 | @ set_tunnel_destination | |
423 | @ Description: | |
424 | @ Sets 'slot' of 'room_number' to point to 'dst_room_number'. | |
425 | @ Call Stack: | |
426 | @ dst_room_number | |
427 | @ slot | |
428 | @ room_number <-- TOS | |
429 | @ Return Stack: | |
430 | @ <empty> | |
431 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
432 | #include <wump_game.pvvs> | |
433 | NSSVTSSSTSSTN | MARK: 10001001 (set_tunnel_destination) | |
434 | @ The pointer we seek is: | |
435 | @ (room_number * room_struct_size) + 2 + slot + ROOM_DATA_BASE | |
436 | @ Where the '+2' accounts for the pit and bat booleans. | |
437 | NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) | |
438 | TSSN | MULTIPLY | |
439 | SSSTSN | PUSH +2 | |
440 | TSSS | ADD | |
441 | TSSS | ADD | |
442 | SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (ROOM_DATA_BASE address) | |
443 | TSSS | ADD | |
444 | SNT | SWAP | |
445 | TTS | STORE | |
446 | NTN | RTS | |
447 | ||
448 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
449 | @ Name: | |
450 | @ generate_cave_hop_length | |
451 | @ Description: | |
452 | @ In order to ensure cave is fully connected, generate a number, 'hop_length', | |
453 | @ that is relatively prime to the number of rooms in the cave. | |
454 | @ Call Stack: | |
455 | @ <empty> | |
456 | @ Return Stack: | |
457 | @ hop_length | |
458 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
459 | #include <math.pvvs> | |
460 | NSSVTSSSSTTTN | MARK: 10000111 (generate_cave_hop_length) | |
461 | NSTTSSSTSTSN | JSR > 10001010 (get_random_room) | |
462 | @ Check for gcd(hop_length,num_rooms) = 1. | |
463 | SNS | DUP | |
464 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = num_rooms address) | |
465 | TTT | LOAD | |
466 | NSTTSSTSN | JSR > 10010 (gcd) | |
467 | SSSTN | PUSH +1 | |
468 | TSST | SUBTRACT | |
469 | NTSTSSSSTTTSSSSSSSSN | BRZ > 10000111 00000000 | |
470 | SNN | DROP | |
471 | NSNTSSSSTTTN | JMP > 10000111 (generate_cave_hop_length) | |
472 | NSSVTSSSSTTTSSSSSSSSN | MARK: 10000111 00000000 | |
473 | NTN | RTS | |
474 | ||
475 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
476 | @ Name: | |
477 | @ clear_cave_data | |
478 | @ Description: | |
479 | @ Writes -1 over the entire cave data array. | |
480 | @ This ensures each room starts unconnected. | |
481 | @ Call Stack: | |
482 | @ <empty> | |
483 | @ Return Stack: | |
484 | @ <empty> | |
485 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
486 | #include <heap.pvvs> | |
487 | #include <wump_game.pvvs> | |
488 | NSSVTSSSSTTSN | MARK: 10000110 (clear_cave_data) | |
489 | SSTTN | PUSH -1 (pattern) | |
490 | SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (ROOM_DATA_BASE address) | |
491 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE address) | |
492 | TTT | LOAD | |
493 | NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) | |
494 | TSSN | MULTIPLY | |
495 | NSTTTSSSN | JSR > 11000 (memset) | |
496 | NTN | RTS | |
497 | ||
498 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
499 | @ Name: | |
500 | @ get_random_room | |
501 | @ Description: | |
502 | @ Returns a valid room number | |
503 | @ Call Stack: | |
504 | @ <empty> | |
505 | @ Return Stack: | |
506 | @ room_num <-- TOS | |
507 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
508 | #include <math.pvvs> | |
509 | NSSVTSSSTSTSN | MARK: 10001010 (get_random_room) | |
83a8624e | 510 | NSTTSSTTN | JSR > 10011 (fastrand) |
2da74194 AT |
511 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = num_rooms address) |
512 | TTT | LOAD | |
513 | TSTT | MODULO | |
514 | NTN | RTS | |
515 | ||
516 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
517 | @ Name: | |
518 | @ set_bats | |
519 | @ Description: | |
520 | @ Set the 'bats' boolean for a specific room. | |
521 | @ Call Stack: | |
522 | @ value (0 or 1) | |
523 | @ room_number | |
524 | @ Return Stack: | |
525 | @ <empty> | |
526 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
527 | #include <wump_game.pvvs> | |
528 | NSSVTSSTSSSSN | MARK: 10010000 (set_bats) | |
529 | @ We seek the pointer: | |
530 | @ (room_number * room_struct_size) + 1 + ROOM_DATA_BASE | |
531 | @ where '+1' accounts for the offset of the bat boolean in the desired room. | |
532 | NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) | |
533 | TSSN | MULTIPLY | |
534 | SSSTN | PUSH +1 | |
535 | TSSS | ADD | |
536 | SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (GAME_DATA_BASE address) | |
537 | TSSS | ADD | |
538 | SNT | SWAP | |
539 | TTS | STORE | |
540 | NTN | RTS | |
541 | ||
542 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
543 | @ Name: | |
544 | @ set_pits | |
545 | @ Description: | |
546 | @ Set the 'pits' boolean for a specific room. | |
547 | @ Call Stack: | |
548 | @ value (0 or 1) | |
549 | @ room_number | |
550 | @ Return Stack: | |
551 | @ <empty> | |
552 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
553 | #include <wump_game.pvvs> | |
554 | NSSVTSSTSSSTN | MARK: 10010001 (set_pits) | |
555 | @ We seek the pointer: | |
556 | @ (room_number * room_struct_size) + 0 + ROOM_DATA_BASE | |
557 | @ where '+0' accounts for the offset of the pit boolean in the desired room. | |
558 | NSTTSSSTSTTN | JSR > 10001011 (get_room_struct_size) | |
559 | TSSN | MULTIPLY | |
560 | SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (GAME_DATA_BASE address) | |
561 | TSSS | ADD | |
562 | SNT | SWAP | |
563 | TTS | STORE | |
564 | NTN | RTS | |
565 | ||
566 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
567 | @ Name: | |
568 | @ reset_cave_population | |
569 | @ Description: | |
570 | @ Remove all bats and pits from the cave. | |
571 | @ Call Stack: | |
572 | @ <empty> | |
573 | @ Return Stack: | |
574 | @ <empty> | |
575 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
576 | NSSVTSSTSSTSN | MARK: 10010010 (reset_cave_population) | |
577 | ||
578 | @ Clear the bat and pit booleans by setting every room to false(=0). | |
579 | @ First prepare a loop index. | |
580 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (GAME_DATA_BASE+0 = number_of_rooms address) | |
581 | TTT | LOAD | |
582 | SSSTN | PUSH 1 | |
583 | TSST | SUBTRACT | |
584 | NSSVTSSTSSTSSSSSSSSSN | MARK: 10010010 00000000 (empty_cave_loop) | |
585 | @ Scare all the bats out of the room. | |
586 | SNS | DUP | |
587 | SSSSN | PUSH 0 (false) | |
588 | SNT | SWAP | |
589 | NSTTSSTSSSSN | JSR > 10010000 (set_bats) | |
590 | @ Fill any pits. | |
591 | SNS | DUP | |
592 | SSSSN | PUSH 0 (false) | |
593 | SNT | SWAP | |
594 | NSTTSSTSSSTN | JSR > 10010001 (set_pits) | |
595 | @ Decrement loop counter and test for end of loop. | |
596 | SSSTN | PUSH 1 | |
597 | TSST | SUBTRACT | |
598 | SNS | DUP | |
599 | NTTTSSTSSTSSSSSSSSTN | BMI > 10010010 00000001 (empty_cave_loop_end) | |
600 | NSNTSSTSSTSSSSSSSSSN | JMP > 10010010 00000000 (empty_cave_loop) | |
601 | @ Loop is complete. Clean up and return. | |
602 | NSSVTSSTSSTSSSSSSSSTN | MARK: 10010010 00000001 (empty_cave_loop_end) | |
603 | SNN | DROP | |
604 | NTN | RTS | |
605 | ||
606 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
607 | @ Name: | |
608 | @ populate_bats | |
609 | @ Description: | |
610 | @ Randomly place a user-defined number of bats in the cave. | |
611 | @ Call Stack: | |
612 | @ <empty> | |
613 | @ Return Stack: | |
614 | @ <empty> | |
615 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
616 | #include <wump_game.pvvs> | |
617 | NSSVTSSTSSTTN | MARK: 10010011 (populate_bats) | |
618 | ||
619 | @ First prepare a loop index. | |
620 | SSSTSSSSSSSSSSTSN | PUSH 0x1002 (GAME_DATA_BASE+2 = number_of_bats address) | |
621 | TTT | LOAD | |
622 | SSSTN | PUSH 1 | |
623 | TSST | SUBTRACT | |
624 | @ Find a random room that does not already contain bats. | |
625 | NSSVTSSTSSTTSSSSSSTSN | MARK: 10010011 00000010 (place_bats) | |
626 | NSTTSSSTSTSN | JSR > 10001010 (get_random_room) | |
627 | SNS | DUP | |
628 | NSTTSSSTTSSN | JSR > 10001100 (room_has_bats) | |
629 | NTSTSSTSSTTSSSSSSTTN | BRZ > 10010011 00000011 (no_bats_in_room) | |
630 | SNN | DROP | |
631 | NSNTSSTSSTTSSSSSSTSN | JMP > 10010011 00000010 (place_bats) | |
632 | @ Room is empty. Place bats. | |
633 | NSSVTSSTSSTTSSSSSSTTN | MARK: 10010011 00000011 (no_bats_in_room) | |
634 | SSSTN | PUSH 1 (true) | |
635 | SNT | SWAP | |
636 | NSTTSSTSSSSN | JSR > 10010000 (set_bats) | |
637 | @ Decrement loop counter and test for loop completion. | |
638 | SSSTN | PUSH 1 | |
639 | TSST | SUBTRACT | |
640 | SNS | DUP | |
641 | NTTTSSTSSTTSSSSSTSSN | BMI > 10010011 00000100 (place_bats_loop_end) | |
642 | NSNTSSTSSTTSSSSSSTSN | JMP > 10010011 00000010 (place_bats) | |
643 | @ Loop is complete. Clean up and return. | |
644 | NSSVTSSTSSTTSSSSSTSSN | MARK: 10010011 00000100 (place_bats_loop_end) | |
645 | SNN | DROP | |
646 | NTN | RTS | |
647 | ||
648 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
649 | @ Name: | |
650 | @ populate_pits | |
651 | @ Description: | |
652 | @ Randomly place a user-defined number of pits in the cave. | |
653 | @ Call Stack: | |
654 | @ <empty> | |
655 | @ Return Stack: | |
656 | @ <empty> | |
657 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
658 | #include <wump_game.pvvs> | |
659 | NSSVTSSTSTSSN | MARK: 10010100 (populate_pits) | |
660 | ||
661 | @ First prepare a loop index. | |
662 | SSSTSSSSSSSSSSSTN | PUSH 0x1001 (GAME_DATA_BASE+1 = number_of_pits address) | |
663 | TTT | LOAD | |
664 | SSSTN | PUSH 1 | |
665 | TSST | SUBTRACT | |
666 | @ Find a random room that does not already contain pits. | |
667 | NSSVTSSTSTSSSSSSSSTSN | MARK: 10010100 00000010 (place_pits) | |
668 | NSTTSSSTSTSN | JSR > 10001010 (get_random_room) | |
669 | SNS | DUP | |
670 | NSTTSSSTTSTN | JSR > 10001101 (room_has_pits) | |
671 | NTSTSSTSTSSSSSSSSTTN | BRZ > 10010100 00000011 (no_pits_in_room) | |
672 | SNN | DROP | |
673 | NSNTSSTSTSSSSSSSSTSN | JMP > 10010100 00000010 (place_pits) | |
674 | @ Room is empty. Place pits. | |
675 | NSSVTSSTSTSSSSSSSSTTN | MARK: 10010100 00000011 (no_pits_in_room) | |
676 | SSSTN | PUSH 1 (true) | |
677 | SNT | SWAP | |
678 | NSTTSSTSSSTN | JSR > 10010001 (set_pits) | |
679 | @ Decrement loop counter and test for loop completion. | |
680 | SSSTN | PUSH 1 | |
681 | TSST | SUBTRACT | |
682 | SNS | DUP | |
683 | NTTTSSTSTSSSSSSSTSSN | BMI > 10010100 00000100 (place_pits_loop_end) | |
684 | NSNTSSTSTSSSSSSSSTSN | JMP > 10010100 00000010 (place_pits) | |
685 | @ Loop is complete. Clean up and return. | |
686 | NSSVTSSTSTSSSSSSSTSSN | MARK: 10010100 00000100 (place_pits_loop_end) | |
687 | SNN | DROP | |
688 | NTN | RTS | |
689 | ||
690 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
691 | @ Name: | |
692 | @ place_player | |
693 | @ Description: | |
694 | @ Place the player in a suitable starting room. | |
695 | @ Call Stack: | |
696 | @ <empty> | |
697 | @ Return Stack: | |
698 | @ <empty> | |
699 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
700 | NSSVTSSTSTSTN | MARK: 10010101 (place_player) | |
701 | ||
702 | @ Find out where the wumpus is located. | |
703 | SSSTSSSSSSSSSTTTN | PUSH 0x1007 (GAME_DATA_BASE+7 = wumpus_room address) | |
704 | TTT | LOAD | |
705 | @ Place the player in a different room than the wumpus. | |
706 | NSSVTSSTSTSTSSSSSSSSN | MARK: 10010101 00000000 (place_player_loop) | |
707 | NSTTSSSTSTSN | JSR > 10001010 (get_random_room) | |
708 | SNT | SWAP | |
709 | SNS | DUP | |
710 | SSSTTN | PUSH 3 | |
711 | NSTTTSSN | JSR > 1100 (deepdup) | |
712 | @ TOS> rand_room, wump_room, wump_room, rand_room | |
713 | TSST | SUBTRACT | |
714 | NTSTSSTSTSTSSSSSSSTN | BRZ > 10010101 00000001 (same_room) | |
715 | NSNTSSTSTSTSSSSSSTSN | JMP > 10010101 00000010 (different_rooms) | |
716 | NSSVTSSTSTSTSSSSSSSTN | MARK: 10010101 00000001 (same_room) | |
717 | SNN | DROP | |
718 | NSNTSSTSTSTSSSSSSSSN | JMP > 10010101 00000000 (place_player_loop) | |
719 | NSSVTSSTSTSTSSSSSSTSN | MARK: 10010101 00000010 (different_rooms) | |
720 | SNN | DROP | |
721 | SSSTSSSSSSSSSTTSN | PUSH 0x1006 (GAME_DATA_BASE+6 = player_room address) | |
722 | SNT | SWAP | |
723 | TTS | STORE | |
724 | NTN | RTS | |
725 | ||
726 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
727 | @ Name: | |
728 | @ populate_cave | |
729 | @ Description: | |
730 | @ Populate the cave with various creatures and features. | |
731 | @ Call Stack: | |
732 | @ <empty> | |
733 | @ Return Stack: | |
734 | @ <empty> | |
735 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
736 | NSSVTSSSSTSTN | MARK: 10000101 (populate_cave) | |
737 | ||
738 | @ Initialize the cave to an unpopulated state. | |
739 | NSTTSSTSSTSN | JSR > 10010010 (reset_cave_population) | |
740 | ||
741 | @ Place bats in the now-empty cave. | |
742 | NSTTSSTSSTTN | JSR > 10010011 (populate_bats) | |
743 | ||
744 | @ Place pits in the now-empty cave. | |
745 | NSTTSSTSTSSN | JSR > 10010100 (populate_pits) | |
746 | ||
747 | @ Place the wumpus. | |
748 | SSSTSSSSSSSSSTTTN | PUSH 0x1007 (GAME_DATA_BASE+7 = wumpus_room address) | |
749 | NSTTSSSTSTSN | JSR > 10001010 (get_random_room) | |
750 | TTS | STORE | |
751 | ||
752 | @ Place the player. | |
753 | NSTTSSTSTSTN | JSR > 10010101 (place_player) | |
754 | ||
755 | NTN | RTS | |
756 | ||
757 | #endif |