1 /*
2  *	Adventure A - Some really old 'n' crusty speccy game
3  *	[Originally for ZX80/81/82 by Artic Computing]
4  *
5  *	Compiled under z88dk by djm especially for gwl
6  *
7  *	djm 19/3/2000
8  *  stefano 31/05/2010
9  *
10  *	Very few changes were needed to get this to work under
11  *	z88dk (many changes were made to sccz80 though(!))
12  *
13  *	Changes to standard source:
14  *	 - casts removed in structures
15  *	 - Few defines to make life easier
16  *   - tape or disk save     (-DTAPE, -DDISK)
17  *   - disk save in data block mode (-DDISKBLOCK)
18  *   - lowercase text taken from the oz700 port in the 'ozdev' web site
19  *   - opt graphics scenes   (-DPICS)
20  *   - score made optional   (-DCOMPUTE_SCORE)
21  *
22  *	Found at: http://www.penelope.demon.co.uk/pod/
23  *
24  *	From the asm source on the same site:
25  *
26  *	Disassembled, annotated and converted for use with CP/M by
27  *	Paul Taylor 18-Aug-1998 With Special thanks to Tim Olmstead
28  */
29 
30 
31  /*
32   *	Using -DDISKBLOCKS on a ZX Spectrum, will require the inclusion of 'zxbasdos.lib' and few extra BASIC lines.
33   * ZX Microdrive syntax example is given:
34   *
35   * 5000 STOP
36   * 7600 LOAD *"m";d;n$ CODE a,l : STOP
37   * 7650 SAVE *"m";d;n$ CODE a,l : STOP
38   * 7900 ERASE "m";d;n$ : STOP
39   *
40   */
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 
47 
48 #ifdef PICS
49 #include <graphics.h>
50 #include <adv_a.h>
51 #endif
52 
53 #ifdef ACE
54 #include <ace.h>
55 #endif
56 
57 
58 #ifndef getkey
59 #include <conio.h>
60 #define getkey() getch()
61 #endif
62 
63 #ifdef DISK
64 FILE *fpsave;
65 #endif
66 
67 #ifdef DISKBLOCK
68 #define TAPE
69 #endif
70 
71 void GetLine();
72 char i_GetCh();
73 
74 
75 typedef int BOOL;
76 typedef unsigned char BYTE;
77 
78 #define TRUE 1
79 #define FALSE 0
80 
81 int GET_TOK();
82 
83 /*****
84 ; Disassembly of the file "F:\GAMES\SPECCY\A\ARTICADV\Advent_a.sna"
85 ;
86 ; Created with dZ80 v1.30a
87 ;
88 ; on Wednesday, 05 of August 1998 at 11:33 PM
89 ;
90 
91 
92 		.org	$5d6c
93 
94 ROM_SAV	.equ	$04c2
95 ROM_LD	.equ	$0556
96 ROM_CLS	.equ	$0daf
97 
98 SCRCT	.equ	$5c8c	; remaining scroll count (system variable)
99 
100 */
101 
102 /* item location codes */
103 
104 #define NOTX		0xfc
105 #define ITEM_WORN	0xfd
106 #define ITEM_HELD	0xfe
107 
108 
109 /* offsets of game variables */
110 
111 #define	GVAR_NO_ITEMS	0x01
112 #define	GVAR_02			0x02
113 #define	GVAR_03			0x03
114 #define	GVAR_04			0x04
115 #define	GVAR_05			0x05
116 #define	GVAR_06			0x06
117 #define	GVAR_07			0x07
118 #define	GVAR_08			0x08
119 #define	GVAR_09			0x09
120 #define	GVAR_0a			0x0a
121 #define	GVAR_0b			0x0b
122 #define	GVAR_0c			0x0c
123 #define	GVAR_0d			0x0d
124 #define	GVAR_0e			0x0e
125 #define	GVAR_0f			0x0f
126 #define	GVAR_10			0x10
127 #define	GVAR_11			0x11
128 #define	GVAR_12			0x12
129 #define	GVAR_13			0x13
130 #define	GVAR_14			0x14
131 #define	GVAR_15			0x15
132 #define	GVAR_16			0x16
133 #define	GVAR_17			0x17
134 #define	GVAR_18			0x18
135 #define	GVAR_19			0x19
136 #define	GVAR_1a			0x1a
137 #define	GVAR_1b			0x1b
138 #define	GVAR_1c			0x1c
139 #define	GVAR_1d			0x1d
140 #define	GVAR_1e			0x1e
141 
142 
143 
144 int GVARS[0x1e];		/* workspace of $1e bytes of game variables*/
145 
146 int F_NTYET;
147 int		PARAM1;
148 int CMDFLG;
149 /*
150 PREDIX	.equ	$-$29	; PREDIX points here
151 */
152 int VERB_TK;
153 int NOUN_TK;
154 BOOL	FLAG;
155 int		CUR_RM;
156 
157 char	strTokenBuf[4];		/* workspace of $04 bytes to hold a token*/
158 
159 #ifdef COMPUTE_SCORE
160 int nScore;
161 #endif
162 
163 #ifdef SPECTRUM
164 #define MAX_COL 50
165 #endif
166 #ifdef Z88
167 #define MAX_COL 79
168 #endif
169 
170 #ifndef MAX_COL
171 #define MAX_COL 31
172 #endif
173 
174 char chaEditLine[MAX_COL + 1];
175 
176 char* pchEditLine;
177 
178 
179 int	nRemColumns = MAX_COL;
180 
181 
182 
183 
184 typedef struct
185 {
186 	int		nVerbTok;
187 	int		nNounTok;
188 	void*	pPredicates;
189 	void*	pActions;
190 } VNDef;
191 
192 
193 enum blah2 { NA_DO_AUTO, NA_CONTINUE, NA_MAIN, NA_BEGIN, NA_RESTART };
194 
195 int nNextParseAction;
196 
197 VNDef* pvndCurrent;
198 BYTE* pPredicateCurrent;
199 BYTE* pActionCurrent;
200 
201 
202 
203 
204 /* ======================================================================
205 // game instructions
206 // ======================================================================
207 */
208 
209 const char *strInstructions =
210     "Welcome to Adventure 'A' - The Planet of Death.\n"
211 	"In this adventure you find yourself stranded on an alien planet. "
212 	"Your aim is to escape from this planet by finding your, now captured and disabled, space ship."
213 	"You will meet various hazards and dangers on your adventure, some natural, some not, all of which you must overcome to succeed.\n"
214 	"Good luck, you will need it!\n\n"
215 	"PRESS ANY KEY TO START\n";
216 
217 /*
218 // ======================================================================
219 // response messages
220 // ======================================================================
221 */
222 
223 const char* straMsg[] =
224 {
225 	"It shows a man climbing down a pit using a rope\n",
226 	"How? I can't reach\n",
227 	"It has fallen to the floor\n",
228 	"How?\n",
229 	"Its too wide. I fell and broke my neck\n",
230 	"Ugh! He is all slimy\n",
231 	"He vanished in a puff of smoke\n",
232 	"You also broke the mirror\n",
233 	"Computer says: 2 west,2 south for space flight\n",
234 	"It has weakened it\n",
235 	"It had no effect\n",
236 	"I fell and knocked myself out.\n",
237 	"The bars look loose\n",
238 	"What with?\n",
239 	"I see a gold coin\n",
240 	"Brrr. The waters too cold\n",
241 	"The fuse has just blown\n",
242 	"The lift has been activated\n",
243 	"I see nothing special\n",
244 	"Keep off the middle men, one may be shocking!\n",
245 	"Vanity waltz!\n",
246 	"Try help\n",
247 	"Points of compass\n",
248 	"Try looking around\n",
249 	"I can see a steep slope\n",
250 	"An alarm sounds. The security guard shot me for trespassing.\n",
251 	"I can see a rope hanging down the chimney.\n",
252 	"I am not that daft. It is too deep.\n",
253 	"The space ship blew up and killed me.\n",
254 	"The ship has flown into the large lift and is hovering there.\nThere are four buttons outside the window marked 1,2,3 and 4\n",
255 	"The lift has taken me up to a plateau.\nCongratulations, you have managed to complete this adventure\nwithout getting killed.\n",
256 	"The lift has become electrified\n",
257 	"I have been electrocuted\n",
258 	"It is a good job i was wearing rubber soled boots.\n",
259 	"I would kill myself if i did.\n",
260 	"I have turned green and dropped dead.\n",
261 	"The green man awoke and throttled me.\n",
262 	"The guard woke and shot me.\n",
263 	"What at?\n"};
264 
265 
266 
267 /*
268 // ======================================================================
269 // room descriptions
270 // ======================================================================
271 */
272 
273 const char* straRoom[] =
274 {
275     "I am on a mountain plateau\nTo the north there is a steep cliff.\nObvious exits are down, east and west.\n",
276 
277     "I am at the edge of a deep pit\nObvious exits are east\n",
278 
279     "I am in a damp limestone cave with stalactites hanging down.\nThe exit is to the west\nThere is a passage to the north\n",
280 
281     "I am in a dense forest\nThere is a rope hanging from one tree\nObvious exits are south and west\n",
282 
283     "I am beside a lake\nExits are east and north. There is a ravine to the west\n",
284 
285     "I am in a strange house\nThe door is to the north\n",
286 
287 	"I am in an old shed\nThe exit is to the east\n",
288 
289 	"I am in a maze. There are passages everywhere.\n",
290 
291 	"I am in a maze. There are passages everywhere.\n",
292 
293 	"I am in a maze. There are passages everywhere.\n",
294 
295 	"I am in a maze. There are passages everywhere.\n",
296 
297 	"I am in an ice cavern.\nThere is an exit to the east.\n",
298 
299 	"I am in a quiet cavern.\nThere are exits west, east and south.\n",
300 
301 	"I am in a wind tunnel.\nThere is a closed door at the end.\nThere is also an exit to the west.\n",
302 
303 	"I am in a room with a computer in\nThe computer is working and has a keyboard\nThe exit is west\n",
304 
305 	"I am in a passage\nThere is a force field to the south : beware of security\nThere are exits to north,east and west\n",
306 
307     "I am in a large hanger\nThere is a locked door to the west\nThere are also exits east,north and south\n",
308 
309 	"I am in a tall lift. The buttons are very high\nThe exit is west\n",
310 
311 	"I am in the lift control room\nThere are three switches on the wall. They are all off\nA sign says : 5,4 no dusty bin rules\nThe exit is east\n",
312 
313 	"I am in a prison cell\n",
314 
315 	"I am in a space ship. There is no visible exit\nThere is a small open window in the side\nThere are also two buttons,one marked main and the other aux.\n"};
316 
317 
318 
319 /*
320 // ======================================================================
321 // item descriptions
322 // ======================================================================
323 */
324 
325 #define MAX_ITEM 28
326 
327 const char* straItem[MAX_ITEM] =
328 {
329 	"a pair of boots",
330 	"a starter motor",
331 	"a key",
332 	"a laser gun",
333 	"an out of order sign",
334 	"a metal bar",
335 	"a gold coin",
336 	"a mirror",
337 	"broken glass",
338 	"a pair of slimy gloves",
339 	"a rope",
340 	"a floor board",
341 	"a broken floor board",
342 	"stalactites",
343 	"a block of ice",
344 	"a pool of water",
345 	"a small green man sleeping on the mirror",
346 	"a sleeping green man",
347 	"a locked door",
348 	"an open door",
349 	"a barred window",
350 	"a hole in the wall",
351 	"a small but powerfull space ship",
352 	"a sleeping security man",
353 	"a piece of sharp flint",
354 	"some stones",
355 	"a drawing on the wall",
356 	"a loudspeaker with dance music coming out"};
357 
358 
359 
360 /*
361 // ======================================================================
362 // initial positions of items - 1 int per item, holds room number
363 // NOTX indicates item doesn't exist yet
364 // ======================================================================
365 */
366 
367 const int naItemStart[MAX_ITEM] =
368 {
369 	0x05, 0x11, 0x0e, 0x06, 0x11, NOTX, NOTX, 0x0c,
370 	NOTX, 0x0d, NOTX, 0x05, NOTX, NOTX, 0x0b, NOTX,
371 	0x0c, NOTX, 0x13, NOTX, 0x13, NOTX, 0x10, 0x10,
372 	0x00, 0x01, 0x02, 0x0f
373 };
374 
375 /*
376 // ======================================================================
377 // current positions of items - 1 int per item, holds room number
378 // initialized from naItemStart at start, updated during the game
379 // NOTX indicates item doesn't exist yet
380 // ======================================================================
381 */
382 
383 int naItemLoc[MAX_ITEM];
384 
385 
386 
387 /*
388 // the commands and their synonyms
389 // each token is 4 characters, followed by a 1 byte token code
390 // first define the token codes
391 */
392 
393 #define	TOK_DOWN	0x01
394 #define	TOK_NORT	0x02
395 #define	TOK_SOUT	0x03
396 #define	TOK_EAST	0x04
397 #define	TOK_WEST	0x05
398 #define	TOK_GET		0x0d
399 #define	TOK_DROP	0x0e
400 #define	TOK_FIRE	0x0f
401 #define	TOK_BOOT	0x10
402 #define	TOK_STAR	0x11
403 #define	TOK_KEY		0x12
404 #define	TOK_GUN		0x13
405 #define	TOK_USED	0x14
406 #define	TOK_BAR		0x15
407 #define	TOK_COIN	0x16
408 #define	TOK_MIRR	0x17
409 #define	TOK_BROK	0x18
410 #define	TOK_GLOV	0x19
411 #define	TOK_ROPE	0x1a
412 #define	TOK_BOAR	0x1b
413 #define	TOK_STAL	0x1c
414 #define	TOK_ICE		0x1d
415 #define	TOK_WATE	0x1e
416 #define	TOK_MAN		0x1f
417 #define	TOK_DOOR	0x20
418 #define	TOK_OPEN	0x21
419 #define	TOK_WIND	0x22
420 #define	TOK_SHIP	0x23
421 #define	TOK_SECU	0x24
422 #define	TOK_FLIN	0x25
423 #define	TOK_STON	0x26
424 #define	TOK_DRAW	0x27
425 #define	TOK_HELP	0x28
426 #define	TOK_INVE	0x29
427 #define	TOK_QUIT	0x2a
428 #define	TOK_YES		0x2b
429 #define	TOK_NO		0x2c
430 #define	TOK_COMP	0x2d
431 #define	TOK_TYPE	0x2e
432 #define	TOK_TURN	0x2f
433 #define	TOK_HAND	0x30
434 #define	TOK_KILL	0x31
435 #define	TOK_DANC	0x32
436 #define	TOK_REMO	0x33
437 #define	TOK_BREA	0x34
438 #define	TOK_BRIB	0x35
439 #define	TOK_USE		0x36
440 #define	TOK_PUSH	0x37
441 #define	TOK_THRE	0x38
442 #define	TOK_TWO		0x39
443 #define	TOK_ONE		0x3a
444 #define	TOK_MEND	0x3b
445 #define	TOK_FOUR	0x3c
446 #define	TOK_LOOK	0x3d
447 #define	TOK_STAN	0x3e
448 #define	TOK_TREE	0x3f
449 #define	TOK_CUT		0x40
450 #define	TOK_WEAR	0x41
451 #define	TOK_CROS	0x42
452 #define	TOK_JUMP	0x43
453 #define	TOK_RAVI	0x44
454 #define	TOK_UP		0x45
455 #define	TOK_FUSE	0x46
456 #define	TOK_REDE	0x47
457 #define	TOK_MAIN	0x48
458 #define	TOK_AUX		0x49
459 #define	TOK_FIEL	0x4a
460 
461 
462 
463 /* now map the codes to their character representations */
464 
465 typedef struct
466 {
467 	char	strWord[5];
468 	int		nCode;
469 } TOKEN;
470 
471 #define MAX_TOK 111
472 
473 const TOKEN taToken[MAX_TOK] =
474 {
475 	{ "DOWN", TOK_DOWN },
476 	{ "D   ", TOK_DOWN },
477 	{ "NORT", TOK_NORT },
478 	{ "N   ", TOK_NORT },
479 	{ "SOUT", TOK_SOUT },
480 	{ "S   ", TOK_SOUT },
481 	{ "EAST", TOK_EAST },
482 	{ "E   ", TOK_EAST },
483 	{ "WEST", TOK_WEST },
484 	{ "W   ", TOK_WEST },
485 	{ "GET ", TOK_GET },
486 	{ "TAKE", TOK_GET },
487 	{ "PICK", TOK_GET },
488 	{ "DROP", TOK_DROP },
489 	{ "PUT ", TOK_DROP },
490 	{ "FIRE", TOK_FIRE },
491 	{ "SHOO", TOK_FIRE },
492 	{ "BOOT", TOK_BOOT },
493 	{ "STAR", TOK_STAR },
494 	{ "MOTO", TOK_STAR },
495 	{ "KEY ", TOK_KEY },
496 	{ "LASE", TOK_GUN },
497 	{ "GUN ", TOK_GUN },
498 	{ "USED", TOK_USED },
499 	{ "BAR ", TOK_BAR },
500 	{ "BARS", TOK_BAR },
501 	{ "GOLD", TOK_COIN },
502 	{ "COIN", TOK_COIN },
503 	{ "MIRR", TOK_MIRR },
504 	{ "BROK", TOK_BROK },
505 	{ "GLOV", TOK_GLOV },
506 	{ "ROPE", TOK_ROPE },
507 	{ "FLOO", TOK_BOAR },
508 	{ "BOAR", TOK_BOAR },
509 	{ "PLAN", TOK_BOAR },
510 	{ "STAL", TOK_STAL },
511 	{ "BLOC", TOK_ICE },
512 	{ "ICE ", TOK_ICE },
513 	{ "POOL", TOK_WATE },
514 	{ "WATE", TOK_WATE },
515 	{ "LAKE", TOK_WATE },
516 	{ "SLEE", TOK_MAN },
517 	{ "GREE", TOK_MAN },
518 	{ "MAN ", TOK_MAN },
519 	{ "DOOR", TOK_DOOR },
520 	{ "OPEN", TOK_OPEN },
521 	{ "UNLO", TOK_OPEN },
522 	{ "WIND", TOK_WIND },
523 	{ "SMAL", TOK_SHIP },
524 	{ "SPAC", TOK_SHIP },
525 	{ "SHIP", TOK_SHIP },
526 	{ "SECU", TOK_SECU },
527 	{ "FLIN", TOK_FLIN },
528 	{ "STON", TOK_STON },
529 	{ "DRAW", TOK_DRAW },
530 	{ "HELP", TOK_HELP },
531 	{ "INVE", TOK_INVE },
532 	{ "I   ", TOK_INVE },
533 	{ "QUIT", TOK_QUIT },
534 	{ "STOP", TOK_QUIT },
535 	{ "ABOR", TOK_QUIT },
536 	{ "YES ", TOK_YES },
537 	{ "Y   ", TOK_YES },
538 	{ "NO  ", TOK_NO },
539 	{ "COMP", TOK_COMP },
540 	{ "KEYB", TOK_COMP },
541 	{ "TYPE", TOK_TYPE },
542 	{ "TURN", TOK_TURN },
543 	{ "HAND", TOK_HAND },
544 	{ "KILL", TOK_KILL },
545 	{ "DANC", TOK_DANC },
546 	{ "WALT", TOK_DANC },
547 	{ "REMO", TOK_REMO },
548 	{ "KICK", TOK_BREA },
549 	{ "BREA", TOK_BREA },
550 	{ "HIT ", TOK_BREA },
551 	{ "BANG", TOK_BREA },
552 	{ "BRIB", TOK_BRIB },
553 	{ "USE ", TOK_USE },
554 	{ "WITH", TOK_USE },
555 	{ "PUSH", TOK_PUSH },
556 	{ "THRE", TOK_THRE },
557 	{ "3   ", TOK_THRE },
558 	{ "TWO ", TOK_TWO },
559 	{ "2   ", TOK_TWO },
560 	{ "ONE ", TOK_ONE },
561 	{ "1   ", TOK_ONE },
562 	{ "MEND", TOK_MEND },
563 	{ "FIX ", TOK_MEND },
564 	{ "REPA", TOK_MEND },
565 	{ "FOUR", TOK_FOUR },
566 	{ "4   ", TOK_FOUR },
567 	{ "LOOK", TOK_LOOK },
568 	{ "STAN", TOK_STAN },
569 	{ "TREE", TOK_TREE },
570 	{ "CUT ", TOK_CUT },
571 	{ "SAW ", TOK_CUT },
572 	{ "WEAR", TOK_WEAR },
573 	{ "CROS", TOK_CROS },
574 	{ "JUMP", TOK_JUMP },
575 	{ "RAVI", TOK_RAVI },
576 	{ "UP  ", TOK_UP },
577 	{ "U   ", TOK_UP },
578 	{ "CLIM", TOK_UP },
579 	{ "FUSE", TOK_FUSE },
580 	{ "REDE", TOK_REDE },
581 	{ "R   ", TOK_REDE },
582 	{ "MAIN", TOK_MAIN },
583 	{ "AUX ", TOK_AUX },
584 	{ "FIEL", TOK_FIEL },
585 	{ "SHIE", TOK_FIEL }
586 };
587 
588 
589 
590 
591 
592 
593 
594 
595 
596 
597 
598 
599 
600 /*
601 // the directional information, one list for each room
602 // each list entry is of the form <token code>,<room number>
603 // each list is terminated with $ff
604 */
605 
606 const BYTE DIR_00[] =
607 {
608 	TOK_DOWN,0x03,
609 	TOK_EAST,0x02,
610 	TOK_WEST,0x01,
611 	0xff
612 };
613 const BYTE DIR_01[] =
614 {
615 	TOK_EAST,0x00,
616 	0xff
617 };
618 const BYTE DIR_02[] =
619 {
620 	TOK_NORT,0x07,
621 	TOK_WEST,0x00,
622 	0xff
623 };
624 const BYTE DIR_03[] =
625 {
626 	TOK_SOUT,0x04,
627 	TOK_WEST,0x00,
628 	0xff
629 };
630 const BYTE DIR_04[] =
631 {
632 	TOK_NORT,0x03,
633 	TOK_EAST,0x05,
634 	0xff
635 };
636 const BYTE DIR_05[] =
637 {
638 	TOK_NORT,0x04,
639 	0xff
640 };
641 const BYTE DIR_06[] =
642 {
643 	0xff
644 };
645 const BYTE DIR_07[] =
646 {
647 	TOK_DOWN,0x07,
648 	TOK_NORT,0x08,
649 	TOK_SOUT,0x07,
650 	TOK_EAST,0x07,
651 	TOK_WEST,0x07,
652 	0xff
653 };
654 const BYTE DIR_08[] =
655 {
656 	TOK_DOWN,0x07,
657 	TOK_NORT,0x07,
658 	TOK_SOUT,0x09,
659 	TOK_EAST,0x07,
660 	TOK_WEST,0x07,
661 	0xff
662 };
663 const BYTE DIR_09[] =
664 {
665 	TOK_DOWN,0x07,
666 	TOK_NORT,0x07,
667 	TOK_SOUT,0x07,
668 	TOK_EAST,0x0a,
669 	TOK_WEST,0x07,
670 	0xff
671 };
672 const BYTE DIR_0A[] =
673 {
674 	TOK_DOWN,0x07,
675 	TOK_NORT,0x02,
676 	TOK_SOUT,0x07,
677 	TOK_EAST,0x07,
678 	TOK_WEST,0x0b,
679 	0xff
680 };
681 const BYTE DIR_0B[] =
682 {
683 	TOK_EAST,0x07,
684 	0xff
685 };
686 const BYTE DIR_0C[] =
687 {
688 	TOK_SOUT,0x0f,
689 	TOK_EAST,0x0d,
690 	TOK_WEST,0x13,
691 	0xff
692 };
693 const BYTE DIR_0D[] =
694 {
695 	0xff
696 };
697 const BYTE DIR_0E[] =
698 {
699 	TOK_WEST,0x0d,
700 	0xff
701 };
702 const BYTE DIR_0F[] =
703 {
704 	TOK_EAST,0x13,
705 	TOK_WEST,0x13,
706 	0xff
707 };
708 const BYTE DIR_10[] =
709 {
710 	TOK_NORT,0x0f,
711 	TOK_SOUT,0x13,
712 	TOK_EAST,0x11,
713 	0xff
714 };
715 const BYTE DIR_11[] =
716 {
717 	TOK_WEST,0x10,
718 	0xff
719 };
720 const BYTE DIR_12[] =
721 {
722 	TOK_EAST,0x10,
723 	0xff
724 };
725 const BYTE DIR_13[] =
726 {
727 	0xff
728 };
729 
730 
731 /* this vector array contains an address for every room */
732 
733 const BYTE* DIR_V[] =
734 {
735 	DIR_00,
736 	DIR_01,
737 	DIR_02,
738 	DIR_03,
739 	DIR_04,
740 	DIR_05,
741 	DIR_06,
742 	DIR_07,
743 	DIR_08,
744 	DIR_09,
745 	DIR_0A,
746 	DIR_0B,
747 	DIR_0C,
748 	DIR_0D,
749 	DIR_0E,
750 	DIR_0F,
751 	DIR_10,
752 	DIR_11,
753 	DIR_12,
754 	DIR_13,
755 	DIR_13		/* room 0x14 shares room 0x13's data - it's just an 0xff anyway */
756 };
757 
758 
759 
760 
761 
762 
763 
764 /* index codes of predicates */
765 
766 #define COM_CHKROOM	0x00
767 #define COM_CHKHERE	0x01
768 #define COM_CHKRAND	0x02
769 #define COM_CHKAWAY	0x03
770 #define COM_CHKWORN	0x04
771 #define COM_CHKSETF	0x05
772 #define COM_TSTGVAR	0x06
773 #define COM_CHKCLRF	0x07
774 #define COM_CHKHELD	0x08
775 
776 /* a table of predicates */
777 
778 BOOL CHKROOM();
779 BOOL CHKHERE();
780 BOOL CHKRAND();
781 BOOL CHKAWAY();
782 BOOL CHKWORN();
783 BOOL CHKSETF();
784 BOOL TSTGVAR();
785 BOOL CHKCLRF();
786 BOOL CHKHELD();
787 
788 #ifdef SCCZ80
789 int *PRED_V[] =
790 #else
791 const BOOL (*PRED_V[])(void) =
792 #endif
793 {
794 	 CHKROOM,					/* $00 */
795 	 CHKHERE,					/* $01 */
796 	 CHKRAND,					/* $02 */
797 	 CHKAWAY,					/* $03 */
798 	 CHKWORN,					/* $04 */
799 	 CHKSETF,					/* $05 */
800 	 TSTGVAR,					/* $06 */
801 	 CHKCLRF,					/* $07 */
802 	 CHKHELD					/* $08 */
803 };
804 
805 /*
806 // list of predicate entries
807 // first byte is the index of the predicate, see PRED_V
808 // second byte is stored in PARAM1
809 // subsequent bytes of entry are terminated with a 0xff
810 */
811 
812 
813 const BYTE A_GD_BOOT[] =
814 {
815 	COM_CHKHERE,0x00,
816 	0xff
817 };
818 const BYTE A_GD_STAR[] =
819 {
820 	COM_CHKHERE,0x01,
821 	0xff
822 };
823 const BYTE A_GD_KEY[] =
824 {
825 	COM_CHKHERE,0x02,
826 	0xff
827 };
828 const BYTE A_GD_GUN[] =
829 {
830 	COM_CHKHERE,0x03,
831 	0xff
832 };
833 const BYTE A_GD_BAR[] =
834 {
835 	COM_CHKHERE,0x05,
836 	0xff
837 };
838 const BYTE A_GD_COIN[] =
839 {
840 	COM_CHKHERE,0x06,
841 	0xff
842 };
843 const BYTE A_G_MIRR_1[] =
844 {
845 	COM_CHKHERE,0x07,
846 	COM_CHKAWAY,0x10,
847 	0xff
848 };
849 const BYTE A_GD_MIRR_2[] =
850 {
851 	COM_CHKHERE,0x08,
852 	0xff
853 };
854 const BYTE A_GD_GLOV[] =
855 {
856 	COM_CHKHERE,0x09,
857 	0xff
858 };
859 const BYTE A_GD_ROPE[] =
860 {
861 	COM_CHKHERE,0x0a,
862 	0xff
863 };
864 const BYTE A_GD_BOAR_1[] =
865 {
866 	COM_CHKHERE,0x0b,
867 	0xff
868 };
869 const BYTE A_GD_BOAR_2[] =
870 {
871 	COM_CHKHERE,0x0c,
872 	0xff
873 };
874 const BYTE A_GD_STAL[] =
875 {
876 	COM_CHKHERE,0x0d,
877 	0xff
878 };
879 const BYTE A_GD_ICE[] =
880 {
881 	COM_CHKHERE,0x0e,
882 	0xff
883 };
884 const BYTE A_GD_FLIN[] =
885 {
886 	COM_CHKHERE,0x18,
887 	0xff
888 };
889 const BYTE A_GD_STON[] =
890 {
891 	COM_CHKHERE,0x19,
892 	0xff
893 };
894 const BYTE A_D_MIRR[] =
895 {
896 	COM_CHKHERE,0x07,
897 	0xff
898 };
899 const BYTE A_DRAW_STAL[] =
900 {
901 	COM_CHKROOM,0x02,
902 	0xff
903 };
904 const BYTE A_U_ICE_1[] =
905 {
906 	COM_CHKROOM,0x02,
907 	COM_CHKHERE,0x0e,
908 	0xff
909 };
910 const BYTE A_CUT_ROPE[] =
911 {
912 	COM_CHKROOM,0x03,
913 	0xff
914 };
915 const BYTE A_USE_FLIN[] =
916 {
917 	COM_CHKROOM,0x03,
918 	COM_CHKHERE,0x18,
919 	0xff
920 };
921 const BYTE A_C_RAVI_1[] =
922 {
923 	COM_CHKROOM,0x04,
924 	0xff
925 };
926 const BYTE A_C_RAVI_2[] =
927 {
928 	COM_CHKROOM,0x06,
929 	0xff
930 };
931 const BYTE A_C_RAVI_3[] =
932 {
933 	COM_CHKROOM,0x04,
934 	COM_CHKHERE,0x0b,
935 	0xff
936 };
937 const BYTE A_USE_BOAR[] =
938 {
939 	COM_CHKROOM,0x06,
940 	COM_CHKHERE,0x0b,
941 	0xff
942 };
943 const BYTE A_DOWN[] =
944 {
945 	COM_CHKROOM,0x0b,
946 	0xff
947 };
948 const BYTE A_U_ICE_2[] =
949 {
950 	COM_CHKROOM,0x0b,
951 	COM_CHKHELD,0x0e,
952 	0xff
953 };
954 const BYTE A_G_MAN_1[] =
955 {
956 	COM_CHKHERE,0x10,
957 	COM_CHKHERE,0x09,
958 	COM_CHKWORN,0x09,
959 	0xff
960 };
961 const BYTE A_G_MAN_2[] =
962 {
963 	COM_CHKHERE,0x10,
964 	COM_CHKHERE,0x09,
965 	0xff
966 };
967 const BYTE A_G_MAN_3[] =
968 {
969 	COM_CHKHERE,0x10,
970 	0xff
971 };
972 const BYTE A_KD_MAN_1[] =
973 {
974 	COM_CHKHERE,0x11,
975 	0xff
976 };
977 const BYTE A_G_MIRR_3[] =
978 {
979 	COM_CHKHERE,0x07,
980 	COM_CHKAWAY,0x10,
981 	0xff
982 };
983 const BYTE A_K_MAN_2[] =
984 {
985 	COM_CHKHERE,0x10,
986 	0xff
987 };
988 const BYTE A_U_GUN_1[] =
989 {
990 	COM_CHKHERE,0x10,
991 	COM_CHKHERE,0x03,
992 	0xff
993 };
994 const BYTE A_U_GUN_2[] =
995 {
996 	COM_CHKHERE,0x11,
997 	COM_CHKHERE,0x03,
998 	COM_CHKHELD,0x11,
999 	0xff
1000 };
1001 const BYTE A_U_GUN_3[] =
1002 {
1003 	COM_CHKHERE,0x11,
1004 	COM_CHKHERE,0x03,
1005 	0xff
1006 };
1007 const BYTE A_TYPE_HELP[] =
1008 {
1009 	COM_CHKROOM,0x0e,
1010 	0xff
1011 };
1012 const BYTE A_FIRE_GUN[] =
1013 {
1014 	COM_CHKROOM,0x0f,
1015 	0xff
1016 };
1017 const BYTE A_FIEL_1[] =
1018 {
1019 	COM_CHKROOM,0x0f,
1020 	COM_CHKCLRF,GVAR_07,
1021 	COM_CHKHERE,0x03,
1022 	0xff
1023 };
1024 const BYTE A_FIEL_2[] =
1025 {
1026 	COM_CHKSETF,GVAR_07,
1027 	COM_CHKCLRF,GVAR_08,
1028 	COM_CHKROOM,0x0f,
1029 	COM_CHKHERE,0x03,
1030 	0xff
1031 };
1032 const BYTE A_FIEL_3[] =
1033 {
1034 	COM_CHKSETF,GVAR_08,
1035 	COM_CHKROOM,0x0f,
1036 	COM_CHKHERE,0x03,
1037 	0xff
1038 };
1039 const BYTE A_DANC_1[] =
1040 {
1041 	COM_CHKROOM,0x0f,
1042 	COM_CHKHELD,0x07,
1043 	COM_CHKSETF,GVAR_08,
1044 	0xff
1045 };
1046 const BYTE A_DANC_2[] =
1047 {
1048 	COM_CHKROOM,0x0f,
1049 	0xff
1050 };
1051 const BYTE A_O_DOOR_1[] =
1052 {
1053 	COM_CHKROOM,0x10,
1054 	0xff
1055 };
1056 const BYTE A_USE_KEY[] =
1057 {
1058 	COM_CHKROOM,0x10,
1059 	COM_CHKHERE,0x02,
1060 	0xff
1061 };
1062 const BYTE A_K_SECU[] =
1063 {
1064 	COM_CHKROOM,0x10,
1065 	COM_CHKHERE,0x03,
1066 	0xff
1067 };
1068 const BYTE A_LUP_BREA[] =
1069 {
1070 	COM_CHKROOM,0x13,
1071 	0xff
1072 };
1073 const BYTE A_UP[] =
1074 {
1075 	COM_CHKROOM,0x13,
1076 	COM_CHKHERE,0x15,
1077 	0xff
1078 };
1079 const BYTE A_BRSEC[] =
1080 {
1081 	COM_CHKROOM,0x13,
1082 	0xff
1083 };
1084 const BYTE A_U_COIN[] =
1085 {
1086 	COM_CHKROOM,0x13,
1087 	COM_CHKHERE,0x06,
1088 	0xff
1089 };
1090 const BYTE A_B_DOOR[] =
1091 {
1092 	COM_CHKROOM,0x13,
1093 	COM_CHKHERE,0x13,
1094 	0xff
1095 };
1096 const BYTE A_G_COIN[] =
1097 {
1098 	COM_CHKROOM,0x04,
1099 	COM_CHKAWAY,0x06,
1100 	0xff
1101 };
1102 #define A_L_WATE A_G_COIN
1103 const BYTE A_WATE_1[] =
1104 {
1105 	COM_CHKROOM,0x04,
1106 	COM_CHKAWAY,0x06,
1107 	COM_CHKWORN,0x00,
1108 	COM_CHKHERE,0x00,
1109 	0xff
1110 };
1111 const BYTE A_WATE_2[] =
1112 {
1113 	COM_CHKROOM,0x04,
1114 	COM_CHKAWAY,0x06,
1115 	COM_CHKHERE,0x00,
1116 	0xff
1117 };
1118 const BYTE A_O_DOOR_2[] =
1119 {
1120 	COM_CHKROOM,0x0d,
1121 	0xff
1122 };
1123 const BYTE A_PUSH_THRE[] =
1124 {
1125 	COM_CHKROOM,0x12,
1126 	COM_CHKCLRF,GVAR_09,
1127 	COM_CHKCLRF,GVAR_0a,
1128 	0xff
1129 };
1130 const BYTE A_PUSH_DIG[] =
1131 {
1132 	COM_CHKROOM,0x12,
1133 	COM_CHKCLRF,GVAR_0a,
1134 	0xff
1135 };
1136 const BYTE A_PUSH_TWO[] =
1137 {
1138 	COM_CHKROOM,0x12,
1139 	COM_TSTGVAR,GVAR_09,0x01,
1140 	COM_CHKCLRF,GVAR_0a,
1141 	0xff
1142 };
1143 const BYTE A_PUSH_ONE[] =
1144 {
1145 	COM_CHKROOM,0x12,
1146 	COM_TSTGVAR,GVAR_09,0x02,
1147 	COM_CHKCLRF,GVAR_0a,
1148 	0xff
1149 };
1150 const BYTE A_MEND_FUSE[] =
1151 {
1152 	COM_CHKROOM,0x12,
1153 	COM_CHKSETF,GVAR_0a,
1154 	0xff
1155 };
1156 const BYTE A_USE_BAR[] =
1157 {
1158 	COM_CHKROOM,0x12,
1159 	COM_CHKHERE,0x05,
1160 	COM_CHKSETF,GVAR_0a,
1161 	0xff
1162 };
1163 const BYTE A_LOOK[] =
1164 {
1165 	COM_CHKROOM,0x0b,
1166 	0xff
1167 };
1168 const BYTE A_HELP_1[] =
1169 {
1170 	COM_CHKROOM,0x11,
1171 	0xff
1172 };
1173 const BYTE A_HELP_2[] =
1174 {
1175 	COM_CHKROOM,0x0f,
1176 	0xff
1177 };
1178 const BYTE A_HELP_3[] =
1179 {
1180 	COM_CHKROOM,0x0e,
1181 	0xff
1182 };
1183 const BYTE A_HELP_4[] =
1184 {
1185 	COM_CHKROOM,0x07,
1186 	0xff
1187 };
1188 const BYTE A_HELP_5[] =
1189 {
1190 	COM_CHKROOM,0x08,
1191 	0xff
1192 };
1193 const BYTE A_HELP_6[] =
1194 {
1195 	COM_CHKROOM,0x09,
1196 	0xff
1197 };
1198 const BYTE A_HELP_7[] =
1199 {
1200 	COM_CHKROOM,0x0a,
1201 	0xff
1202 };
1203 const BYTE A_HELP_8[] =
1204 {
1205 	COM_CHKROOM,0x14,
1206 	COM_CHKSETF,GVAR_0c,
1207 	0xff
1208 };
1209 const BYTE A_LUP[] =
1210 {
1211 	COM_CHKSETF,GVAR_0b,
1212 	COM_CHKROOM,0x0c,
1213 	0xff
1214 };
1215 const BYTE A_WEST[] =
1216 {
1217 	COM_CHKROOM,0x0d,
1218 	0xff
1219 };
1220 const BYTE A_JUMP[] =
1221 {
1222 	COM_CHKROOM,0x01,
1223 	0xff
1224 };
1225 const BYTE A_USEROP[] =
1226 {
1227 	COM_CHKROOM,0x01,
1228 	COM_CHKHELD,0x0a,
1229 	0xff
1230 };
1231 const BYTE A_UPROPE[] =
1232 {
1233 	COM_CHKROOM,0x0c,
1234 	COM_CHKSETF,GVAR_0b,
1235 	0xff
1236 };
1237 const BYTE A_SHIP[] =
1238 {
1239 	COM_CHKHERE,0x16,
1240 	0xff
1241 };
1242 const BYTE A_P_MAUX[] =
1243 {
1244 	COM_CHKROOM,0x14,
1245 	COM_CHKHERE,0x01,
1246 	0xff
1247 };
1248 const BYTE A_P_32[] =
1249 {
1250 	COM_CHKROOM,0x14,
1251 	COM_CHKSETF,GVAR_0c,
1252 	0xff
1253 };
1254 const BYTE A_P_41[] =
1255 {
1256 	COM_CHKROOM,0x14,
1257 	COM_CHKSETF,GVAR_0c,
1258 	COM_TSTGVAR,GVAR_09,0x03,
1259 	0xff
1260 };
1261 const BYTE A_PSH_ONE_2[] =
1262 {
1263 	COM_CHKROOM,0x14,
1264 	COM_CHKSETF,GVAR_0c,
1265 	COM_CHKWORN,0x00,
1266 	COM_TSTGVAR,GVAR_09,0x03,
1267 	0xff
1268 };
1269 
1270 
1271 
1272 /*
1273 // list of predicate entries for Auto Commands
1274 // first byte is the index of the predicate, see PRED_V
1275 // second byte is stored in PARAM1
1276 // subsequent bytes of entry are terminated with a $ff
1277 // check if we have turned green and died
1278 */
1279 const BYTE A_CHGRN[] =
1280 {
1281 	COM_TSTGVAR,GVAR_05,0x01,		/* if game variable 0x05 = 1     */
1282 	COM_CHKSETF,GVAR_06,			/* and game variable 0x06 is set */
1283 	0xff
1284 };
1285 
1286 /* check if the small green man is to throttle us (version 1) */
1287 const BYTE A_CHTHR[] =
1288 {
1289 	COM_TSTGVAR,GVAR_02,0x01,		/* if game variable 0x02 = 1 */
1290 	COM_CHKHERE,0x10,			/* and is-present the small green man sleeping on the mirror */
1291 	0xff
1292 };
1293 
1294 /* check if the small green man is to throttle us (version 2) */
1295 const BYTE A_C2THR[] =
1296 {
1297 	COM_TSTGVAR,GVAR_02,0x01,		/* if game variable 0x02 = 1 */
1298 	COM_CHKHERE,0x11,				/* and is-present the sleeping green man (moved off mirror) */
1299 	0xff
1300 };
1301 
1302 /* check if we're to be shot by the security guard */
1303 const BYTE A_SHOT[] =
1304 {
1305 	COM_TSTGVAR,GVAR_02,0x01,		/* if game variable 0x02 = 1 */
1306 	COM_CHKHERE,0x17,			/* and is-present the sleeping security man */
1307 	0xff
1308 };
1309 
1310 /* check if ice has melted */
1311 const BYTE A_MELTD[] =
1312 {
1313 	COM_TSTGVAR,GVAR_02,0x01,		/* if game variable 0x02 = 1 */
1314 	COM_CHKHERE,0x0e,			/* and is-present the block of ice */
1315 	0xff
1316 };
1317 
1318 /* an empty action entry */
1319 const BYTE A_NULL[] = { 0Xff };
1320 
1321 const BYTE A_MISC[] = { 0xff };		/* used for auto commands - no predicates required */
1322 
1323 
1324 
1325 
1326 #define	I_SH_INVE	0x00		/* terminates bytecode processing */
1327 #define	I_SH_REMO	0x01
1328 #define	I_SH_GET	0x02
1329 #define	I_SH_DROP	0x03
1330 #define	I_SH_WEAR	0x04
1331 #define	I_SH_MSG	0x05
1332 #define	I_SH_REDE	0x06		/* terminates bytecode processing */
1333 #define	I_SH_AUTO	0x07		/* terminates bytecode processing */
1334 #define	I_SH_GOTO	0x08
1335 #define	I_SH_SETF	0x09
1336 #define	I_SH_CLRF	0x0a
1337 #define	I_SH_SWAP	0x0b
1338 #define	I_SH_DEAD	0x0c		/* terminates bytecode processing */
1339 #define	I_SH_OK		0x0d		/* terminates bytecode processing */
1340 #define	I_SH_QUIT	0x0e		/* terminates bytecode processing */
1341 #define	I_SH_SETV	0x0f
1342 #define	I_SH_CREA	0x10
1343 #define	I_SH_DEST	0x11
1344 #define	I_SH_ADSC	0x12
1345 #define	I_SH_SCOR	0x13
1346 #define	I_SH_FAIL1	0x14
1347 #define	I_SH_TELL	0x15
1348 #define	I_SH_FAIL2	0x16
1349 #define	I_SH_FAIL3	0x17
1350 #define	I_SH_FAIL4	0x18
1351 
1352 
1353 
1354 /* bytecodes for the various commands a user can enter */
1355 
1356 const BYTE SGET_00[] = { I_SH_GET,0x00,I_SH_OK };
1357 const BYTE SGET_01[] = { I_SH_GET,0x01,I_SH_OK };
1358 const BYTE SGET_02[] = { I_SH_GET,0x02,I_SH_OK };
1359 const BYTE SGET_03[] = { I_SH_GET,0x03,I_SH_OK };
1360 const BYTE SGET_05[] = { I_SH_GET,0x05,I_SH_OK };
1361 const BYTE SGET_06[] = { I_SH_GET,0x06,I_SH_OK };
1362 const BYTE SGET_07[] = { I_SH_GET,0x07,I_SH_OK };
1363 const BYTE SGET_08[] = { I_SH_GET,0x08,I_SH_OK };
1364 const BYTE SGET_09[] = { I_SH_GET,0x09,I_SH_OK };
1365 const BYTE SGET_0A[] = { I_SH_GET,0x0a,I_SH_OK };
1366 const BYTE SGET_0B[] = { I_SH_GET,0x0b,I_SH_OK };
1367 const BYTE SGET_0C[] = { I_SH_GET,0x0c,I_SH_OK };
1368 const BYTE SGET_0D[] = { I_SH_GET,0x0d,I_SH_OK };
1369 const BYTE SGET_0E[] = { I_SH_GET,0x0e,I_SH_SETV,GVAR_02,0x09,I_SH_OK };
1370 const BYTE SGET_18[] = { I_SH_GET,0x18,I_SH_OK };
1371 const BYTE SGET_19[] = { I_SH_GET,0x19,I_SH_OK };
1372 const BYTE SINVENT[] = { I_SH_INVE,0x07			 };		/* the 0x07 is ignored */
1373 const BYTE SQUIT[] = { I_SH_QUIT };
1374 const BYTE SPUT_00[] = { I_SH_DROP,0x00,I_SH_OK };
1375 const BYTE SPUT_01[] = { I_SH_DROP,0x01,I_SH_OK };
1376 const BYTE SPUT_02[] = { I_SH_DROP,0x02,I_SH_OK };
1377 const BYTE SPUT_03[] = { I_SH_DROP,0x03,I_SH_OK };
1378 const BYTE SPUT_05[] = { I_SH_DROP,0x05,I_SH_OK };
1379 const BYTE SPUT_06[] = { I_SH_DROP,0x06,I_SH_OK };
1380 const BYTE SPUT_07[] = { I_SH_DROP,0x07,I_SH_OK };
1381 const BYTE SPUT_08[] = { I_SH_DROP,0x08,I_SH_OK };
1382 const BYTE SPUT_09[] = { I_SH_DROP,0x09,I_SH_OK };
1383 const BYTE SPUT_0A[] = { I_SH_DROP,0x0a,I_SH_OK };
1384 const BYTE SPUT_0B[] = { I_SH_DROP,0x0b,I_SH_OK };
1385 const BYTE SPUT_0C[] = { I_SH_DROP,0x0c,I_SH_OK };
1386 const BYTE SPUT_0D[] = { I_SH_DROP,0x0d,I_SH_OK };
1387 const BYTE SPUT_0E[] = { I_SH_DROP,0x0e,I_SH_OK };
1388 const BYTE SPUT_18[] = { I_SH_DROP,0x18,I_SH_OK };
1389 const BYTE SPUT_19[] = { I_SH_DROP,0x19,I_SH_OK };
1390 const BYTE SLK_DRW[] = { I_SH_MSG,0x00,I_SH_AUTO };
1391 const BYTE SBRK_ST[] = { I_SH_MSG,0x01,I_SH_AUTO };
1392 const BYTE SUSE_IC[] = { I_SH_CREA,0x0d,I_SH_MSG,0x02,I_SH_AUTO };
1393 const BYTE SCUT_RP[] = { I_SH_MSG,0x03,I_SH_AUTO };
1394 const BYTE SUSE_FL[] = { I_SH_CREA,0x0a,I_SH_MSG,0x02,I_SH_AUTO };
1395 const BYTE SWR_00[] = { I_SH_WEAR,0x00,I_SH_OK };
1396 const BYTE SRM_00[] = { I_SH_REMO,0x00,I_SH_OK };
1397 const BYTE SCR_RV[] = { I_SH_MSG,0x03,I_SH_AUTO };
1398 const BYTE SUSE_BO[] = { I_SH_GOTO,0x06,I_SH_REDE };
1399 const BYTE SUS2_BO[] = { I_SH_GOTO,0x04,I_SH_DEST,0x0b,I_SH_CREA,0x0c,I_SH_REDE };
1400 const BYTE SJMP_RV[] = { I_SH_MSG,0x04,I_SH_DEAD };
1401 const BYTE SUSE_I2[] = { I_SH_GOTO,0x0c,I_SH_DROP,0x0e,I_SH_SWAP,0x0e,I_SH_SETV,GVAR_02,0x07,I_SH_REDE };
1402 const BYTE SGET_MN[] = { I_SH_GET,0x10,I_SH_SWAP,0x10,I_SH_MSG,0x05,I_SH_SETV,GVAR_05,0x0a,I_SH_CLRF,GVAR_06,I_SH_AUTO };
1403 const BYTE SGET_M2[] = { I_SH_GET,0x10,I_SH_SWAP,0x10,I_SH_OK };
1404 const BYTE SPUT_11[] = { I_SH_DROP,0x11,I_SH_OK };
1405 const BYTE SGE2_07[] = { I_SH_GET,0x07,I_SH_OK };
1406 const BYTE SGE2_08[] = { I_SH_GET,0x08,I_SH_OK };
1407 const BYTE SPU2_07[] = { I_SH_DROP,0x07,I_SH_OK };
1408 const BYTE SPU2_08[] = { I_SH_DROP,0x08,I_SH_OK };
1409 const BYTE SDO_HOW[] = { I_SH_MSG,0x03,I_SH_AUTO };
1410 const BYTE SUSE_GN[] = { I_SH_DEST,0x10,I_SH_SWAP,0x07,I_SH_MSG,0x06,I_SH_MSG,0x07,I_SH_AUTO };
1411 const BYTE SFIR_GN[] = { I_SH_MSG,0x26,I_SH_AUTO };
1412 const BYTE SUS2_GN[] = { I_SH_DEST,0x11,I_SH_MSG,0x06,I_SH_AUTO };
1413 const BYTE SHLP_CM[] = { I_SH_MSG,0x08,I_SH_AUTO };
1414 const BYTE SFLD_1[] = { I_SH_SETF,GVAR_07,I_SH_MSG,0x09,I_SH_AUTO };
1415 const BYTE SFLD_2[] = { I_SH_SETF,GVAR_08,I_SH_MSG,0x09,I_SH_AUTO };
1416 const BYTE SFLD_3[] = { I_SH_MSG,0x0a,I_SH_AUTO };
1417 const BYTE SDANCE[] = { I_SH_GOTO,0x10,I_SH_SETV,GVAR_02,0x09,I_SH_REDE };
1418 const BYTE SDANCE2[] = { I_SH_MSG,0x0b,I_SH_GOTO,0x13,I_SH_REDE };
1419 const BYTE SUSE_KY[] = { I_SH_GOTO,0x12,I_SH_REDE };
1420 const BYTE SKIL_SG[] = { I_SH_DEST,0x17,I_SH_OK };
1421 const BYTE SLK_UP[] = { I_SH_MSG,0x0c,I_SH_AUTO };
1422 const BYTE SBRK_BA[] = { I_SH_SWAP,0x14,I_SH_CREA,0x05,I_SH_REDE };
1423 const BYTE SGO_UP[] = { I_SH_GOTO,0x0c,I_SH_SWAP,0x14,I_SH_REDE };
1424 const BYTE SBRBSEC[] = { I_SH_MSG,0x0d,I_SH_AUTO };
1425 const BYTE SUSE_CN[] = { I_SH_SWAP,0x12,I_SH_DEST,0x06,I_SH_REDE };
1426 const BYTE SBDOOR[] = { I_SH_GOTO,0x0c,I_SH_SWAP,0x12,I_SH_REDE };
1427 const BYTE SLK_WAT[] = { I_SH_MSG,0x0e,I_SH_AUTO };
1428 const BYTE SGET_CN[] = { I_SH_MSG,0x01,I_SH_AUTO };
1429 const BYTE SWATER2[] = { I_SH_MSG,0x0f,I_SH_AUTO };
1430 const BYTE SWATER1[] = { I_SH_CREA,0x06,I_SH_GET,0x06,I_SH_OK };
1431 const BYTE SL2_WAT[] = { I_SH_MSG,0x0f,I_SH_AUTO };
1432 const BYTE SODOOR2[] = { I_SH_GOTO,0x0e,I_SH_REDE };
1433 const BYTE SPSH3A[] = { I_SH_SETV,GVAR_09,0x01,I_SH_OK };
1434 const BYTE SPSHDG[] = { I_SH_MSG,0x10,I_SH_CLRF,GVAR_09,I_SH_SETF,GVAR_0a,I_SH_AUTO };
1435 const BYTE SPSH2A[] = { I_SH_SETV,GVAR_09,0x02,I_SH_OK };
1436 const BYTE SPSH1A[] = { I_SH_MSG,0x11,I_SH_SETV,GVAR_09,0x03,I_SH_AUTO };
1437 const BYTE SMNDFUS[] = { I_SH_MSG,0x0d,I_SH_AUTO };
1438 const BYTE SUSE_BA[] = { I_SH_CLRF,GVAR_0a,I_SH_DEST,0x05,I_SH_OK };
1439 const BYTE SLOOK1[] = { I_SH_MSG,0x18,I_SH_AUTO };
1440 const BYTE SHELP1[] = { I_SH_MSG,0x13,I_SH_AUTO };
1441 const BYTE SHELP2[] = { I_SH_MSG,0x14,I_SH_AUTO };
1442 const BYTE SHELP3[] = { I_SH_MSG,0x15,I_SH_AUTO };
1443 const BYTE SHELP4[] = { I_SH_MSG,0x16,I_SH_AUTO };
1444 const BYTE SLK_UP2[] = { I_SH_MSG,0x1a,I_SH_AUTO };
1445 const BYTE SQUIET[] = { I_SH_GOTO,0x0c,I_SH_SETV,GVAR_02,0x07,I_SH_REDE };
1446 const BYTE SWR_09[] = { I_SH_WEAR,0x09,I_SH_OK };
1447 const BYTE SRM_09[] = { I_SH_REMO,0x09,I_SH_OK };
1448 const BYTE SREDE[] = { I_SH_REDE };
1449 const BYTE SJUMP_D[] = { I_SH_MSG,0x03,I_SH_AUTO };
1450 const BYTE SUSE_RP[] = { I_SH_SETF,GVAR_0b,I_SH_DROP,0x0a,I_SH_GOTO,0x0c,I_SH_REDE };
1451 const BYTE SJUMP[] = { I_SH_MSG,0x1b,I_SH_AUTO };
1452 const BYTE SUP_ROP[] = { I_SH_GOTO,0x01,I_SH_REDE };
1453 const BYTE SSHIP[] = { I_SH_GOTO,0x14,I_SH_REDE };
1454 const BYTE SPSH_MN[] = { I_SH_MSG,0x1c,I_SH_DEAD };
1455 const BYTE SPSH_AU[] = { I_SH_SETF,GVAR_0c,I_SH_MSG,0x1d,I_SH_AUTO };
1456 const BYTE SPSH_32[] = { I_SH_MSG,0x19,I_SH_DEAD };
1457 const BYTE SPSH_4[] = { I_SH_MSG,0x1e,I_SH_QUIT };
1458 const BYTE SPSH_1B[] = { I_SH_MSG,0x1f,I_SH_MSG,0x20,I_SH_DEAD };
1459 const BYTE SPSH_1C[] = { I_SH_MSG,0x1f,I_SH_MSG,0x21,I_SH_MSG,0x1e,I_SH_QUIT };
1460 const BYTE SHELP5[] = { I_SH_MSG,0x17,I_SH_AUTO };
1461 const BYTE SLOOK2[] = { I_SH_MSG,0x12,I_SH_AUTO };
1462 
1463 
1464 
1465 
1466 
1467 /*
1468 // list of available verb/noun combinations
1469 // along with their defining predicates and
1470 // command lists
1471 // terminated with a zero byte
1472 
1473 // for each entry:
1474 // 1st = verb token code
1475 // 2nd = noun token code
1476 // 3rd = address of predicate list entry
1477 // 4th = address of system command list entry
1478 */
1479 
1480 const VNDef vndDefinitions[] =
1481 {
1482 	{ TOK_GET,	TOK_BOOT,	 A_GD_BOOT,		 SGET_00 },
1483 	{ TOK_GET,	TOK_STAR,	 A_GD_STAR,		 SGET_01 },
1484 	{ TOK_GET,	TOK_KEY,	 A_GD_KEY,		 SGET_02 },
1485 	{ TOK_GET,	TOK_GUN,	 A_GD_GUN,		 SGET_03 },
1486 	{ TOK_GET,	TOK_BAR,	 A_GD_BAR,		 SGET_05 },
1487 	{ TOK_GET,	TOK_COIN,	 A_GD_COIN,		 SGET_06 },
1488 	{ TOK_GET,	TOK_MIRR,	 A_G_MIRR_1,		 SGET_07 },
1489 	{ TOK_GET,	TOK_MIRR,	 A_GD_MIRR_2,	 SGET_08 },
1490 	{ TOK_GET,	TOK_BROK,	 A_GD_MIRR_2,	 SGET_08 },
1491 	{ TOK_GET,	TOK_GLOV,	 A_GD_GLOV,		 SGET_09 },
1492 	{ TOK_GET,	TOK_ROPE,	 A_GD_ROPE,		 SGET_0A },
1493 	{ TOK_GET,	TOK_BOAR,	 A_GD_BOAR_1,	 SGET_0B },
1494 	{ TOK_GET,	TOK_BOAR,	 A_GD_BOAR_2,	 SGET_0C },
1495 	{ TOK_GET,	TOK_BROK,	 A_GD_BOAR_2,	 SGET_0C },
1496 	{ TOK_GET,	TOK_STAL,	 A_GD_STAL,	 SGET_0D },
1497 	{ TOK_GET,	TOK_ICE,	 A_GD_ICE,	 SGET_0E },
1498 	{ TOK_GET,	TOK_FLIN,	 A_GD_FLIN,		 SGET_18 },
1499 	{ TOK_GET,	TOK_STON,	 A_GD_STON,		 SGET_19 },
1500 	{ TOK_INVE, 0xff,		 A_MISC,			 SINVENT },
1501 	{ TOK_QUIT, 0xff,		 A_MISC,			 SQUIT },
1502 	{ TOK_DROP,	TOK_BOOT,	 A_GD_BOOT,		 SPUT_00 },
1503 	{ TOK_DROP,	TOK_STAR,	 A_GD_STAR,		 SPUT_01 },
1504 	{ TOK_DROP,	TOK_KEY,	 A_GD_KEY,		 SPUT_02 },
1505 	{ TOK_DROP,	TOK_GUN,	 A_GD_GUN,		 SPUT_03 },
1506 	{ TOK_DROP,	TOK_BAR,	 A_GD_BAR,		 SPUT_05 },
1507 	{ TOK_DROP,	TOK_COIN,	 A_GD_COIN,		 SPUT_06 },
1508 	{ TOK_DROP,	TOK_MIRR,	 A_D_MIRR,		 SPUT_07 },
1509 	{ TOK_DROP,	TOK_MIRR,	 A_GD_MIRR_2,	 SPUT_08 },
1510 	{ TOK_DROP,	TOK_BROK,	 A_GD_MIRR_2,	 SPUT_08 },
1511 	{ TOK_DROP,	TOK_GLOV,	 A_GD_GLOV,		 SPUT_09 },
1512 	{ TOK_DROP,	TOK_ROPE,	 A_GD_ROPE,		 SPUT_0A },
1513 	{ TOK_DROP,	TOK_BOAR,	 A_GD_BOAR_1,	 SPUT_0B },
1514 	{ TOK_DROP,	TOK_BOAR,	 A_GD_BOAR_2,	 SPUT_0C },
1515 	{ TOK_FIRE,	TOK_BROK,	 A_GD_BOAR_2,	 SPUT_0C },
1516 	{ TOK_DROP,	TOK_STAL,	 A_GD_STAL,		 SPUT_0D },
1517 	{ TOK_DROP,	TOK_ICE,	 A_GD_ICE,		 SPUT_0E },
1518 	{ TOK_DROP,	TOK_FLIN,	 A_GD_FLIN,		 SPUT_18 },
1519 	{ TOK_DROP,	TOK_STON,	 A_GD_STON,		 SPUT_19 },
1520 	{ TOK_LOOK,	TOK_DRAW,	 A_DRAW_STAL,	 SLK_DRW },
1521 	{ TOK_BREA,	TOK_STAL,	 A_DRAW_STAL,	 SBRK_ST },
1522 	{ TOK_USE,	TOK_ICE,	 A_U_ICE_1,		 SUSE_IC },
1523 	{ TOK_CUT,	TOK_ROPE,	 A_CUT_ROPE,		 SCUT_RP },
1524 	{ TOK_USE,	TOK_FLIN,	 A_USE_FLIN,		 SUSE_FL },
1525 	{ TOK_WEAR,	TOK_BOOT,	 A_MISC,			 SWR_00 },
1526 	{ TOK_REMO,	TOK_BOOT,	 A_MISC,			 SRM_00 },
1527 	{ TOK_CROS,	TOK_RAVI,	 A_C_RAVI_1,		 SCR_RV },
1528 	{ TOK_CROS,	TOK_RAVI,	 A_C_RAVI_2,		 SCR_RV },
1529 	{ TOK_USE,	TOK_BOAR,	 A_C_RAVI_3,		 SUSE_BO },
1530 	{ TOK_USE,	TOK_BOAR,	 A_USE_BOAR,		 SUS2_BO },
1531 	{ TOK_JUMP,	TOK_RAVI,	 A_C_RAVI_3,		 SJMP_RV },
1532 	{ TOK_JUMP,	TOK_RAVI,	 A_C_RAVI_2,		 SJMP_RV },
1533 	{ TOK_DOWN, 0xff,		 A_DOWN,			 SCR_RV },
1534 	{ TOK_USE,	TOK_ICE,	 A_U_ICE_2,		 SUSE_I2 },
1535 	{ TOK_GET,	TOK_MAN,	 A_G_MAN_1,		 SGET_MN },
1536 	{ TOK_GET,	TOK_MAN,	 A_G_MAN_2,		 SGET_M2 },
1537 	{ TOK_GET,	TOK_MAN,	 A_G_MAN_3,		 SGET_MN },
1538 	{ TOK_DROP,	TOK_MAN,	 A_KD_MAN_1,		 SPUT_11 },
1539 	{ TOK_GET,	TOK_MIRR,	 A_G_MIRR_3,		 SGE2_07 },
1540 	{ TOK_GET,	TOK_BROK,	 A_GD_MIRR_2,	 SGE2_08 },
1541 	{ TOK_DROP,	TOK_MIRR,	 A_D_MIRR,		 SPU2_07 },
1542 	{ TOK_DROP,	TOK_BROK,	 A_GD_MIRR_2,	 SPU2_08 },
1543 	{ TOK_KILL,	TOK_MAN,	 A_K_MAN_2,		 SDO_HOW },
1544 	{ TOK_KILL,	TOK_MAN,	 A_KD_MAN_1,		 SDO_HOW },
1545 	{ TOK_USE,	TOK_GUN,	 A_U_GUN_1,		 SUSE_GN },
1546 	{ TOK_USE,	TOK_GUN,	 A_U_GUN_2,		 SFIR_GN },
1547 	{ TOK_USE,	TOK_GUN,	 A_U_GUN_3,		 SUS2_GN },
1548 	{ TOK_TYPE,	TOK_HELP,	 A_TYPE_HELP,	 SHLP_CM },
1549 	{ TOK_FIRE,	TOK_GUN,	 A_FIRE_GUN,		 SFIR_GN },
1550 	{ TOK_FIEL, 0xff,		 A_FIEL_1,		 SFLD_1 },
1551 	{ TOK_FIEL, 0xff,		 A_FIEL_2,		 SFLD_2 },
1552 	{ TOK_FIEL, 0xff,		 A_FIEL_3,		 SFLD_3 },
1553 	{ TOK_DANC, 0xff,		 A_DANC_1,		 SDANCE },
1554 	{ TOK_DANC, 0xff,		 A_DANC_2,		 SDANCE2 },
1555 	{ TOK_OPEN,	TOK_DOOR,	 A_O_DOOR_1,		 SDO_HOW },
1556 	{ TOK_USE,	TOK_KEY,	 A_USE_KEY,		 SUSE_KY },
1557 	{ TOK_KILL,	TOK_SECU,	 A_K_SECU,		 SKIL_SG },
1558 	{ TOK_LOOK,	TOK_UP,		 A_LUP_BREA,		 SLK_UP },
1559 	{ TOK_BREA,	TOK_BAR,	 A_LUP_BREA,		 SBRK_BA },
1560 	{ TOK_UP,	0xff,		 A_UP,			 SGO_UP },
1561 	{ TOK_BRIB,	TOK_SECU,	 A_BRSEC,		 SBRBSEC },
1562 	{ TOK_USE,	TOK_COIN,	 A_U_COIN,		 SUSE_CN },
1563 	{ TOK_DOOR, 0xff,		 A_B_DOOR,		 SBDOOR },
1564 	{ TOK_LOOK,	TOK_WATE,	 A_L_WATE,		 SLK_WAT },
1565 	{ TOK_GET,	TOK_COIN,	 A_G_COIN,		 SGET_CN },
1566 	{ TOK_WATE, 0xff,		 A_WATE_1,		 SWATER1 },
1567 	{ TOK_WATE, 0xff,		 A_WATE_2,		 SWATER2 },
1568 	{ TOK_WATE, 0xff,		 A_L_WATE,		 SL2_WAT },
1569 	{ TOK_OPEN,	TOK_DOOR,	 A_O_DOOR_2,		 SODOOR2 },
1570 	{ TOK_PUSH,	TOK_THRE,	 A_PUSH_THRE,	 SPSH3A },
1571 	{ TOK_PUSH,	TOK_THRE,	 A_PUSH_DIG,		 SPSHDG },
1572 	{ TOK_PUSH,	TOK_TWO,	 A_PUSH_TWO,		 SPSH2A },
1573 	{ TOK_PUSH,	TOK_TWO,	 A_PUSH_DIG,		 SPSHDG },
1574 	{ TOK_PUSH,	TOK_ONE,	 A_PUSH_ONE,		 SPSH1A },
1575 	{ TOK_PUSH,	TOK_ONE,	 A_PUSH_DIG,		 SPSHDG },
1576 	{ TOK_MEND,	TOK_FUSE,	 A_MEND_FUSE,	 SMNDFUS },
1577 	{ TOK_USE,	TOK_BAR,	 A_USE_BAR,		 SUSE_BA },
1578 	{ TOK_LOOK, 0xff,		 A_LOOK,			 SLOOK1 },
1579 	{ TOK_HELP, 0xff,		 A_HELP_1,		 SHELP1 },
1580 	{ TOK_HELP, 0xff,		 A_HELP_2,		 SHELP2 },
1581 	{ TOK_HELP, 0xff,		 A_HELP_3,		 SHELP3 },
1582 	{ TOK_HELP, 0xff,		 A_HELP_4,		 SHELP4 },
1583 	{ TOK_HELP, 0xff,		 A_HELP_5,		 SHELP4 },
1584 	{ TOK_HELP, 0xff,		 A_HELP_6,		 SHELP4 },
1585 	{ TOK_HELP, 0xff,		 A_HELP_7,		 SHELP4 },
1586 	{ TOK_HELP, 0xff,		 A_HELP_8,		 SHELP1 },
1587 	{ TOK_LOOK,	TOK_UP,		 A_LUP,			 SLK_UP2 },
1588 	{ TOK_WEST, 0xff,		 A_WEST,			 SQUIET },
1589 	{ TOK_NORT, 0xff,		 A_HELP_2,		 SQUIET },
1590 	{ TOK_WEAR,	TOK_GLOV,	 A_MISC,			 SWR_09 },
1591 	{ TOK_REMO,	TOK_GLOV,	 A_MISC,			 SRM_09 },
1592 	{ TOK_REDE, 0xff,		 A_MISC,			 SREDE },
1593 	{ TOK_DOWN, 0xff,		 A_JUMP,			 SJUMP_D },
1594 	{ TOK_USE,	TOK_ROPE,	 A_USEROP,		 SUSE_RP },
1595 	{ TOK_JUMP, 0xff,		 A_JUMP,			 SJUMP },
1596 	{ TOK_UP,	TOK_ROPE,	 A_UPROPE,		 SUP_ROP },
1597 	{ TOK_SHIP, 0xff,		 A_SHIP,			 SSHIP },
1598 	{ TOK_PUSH,	TOK_MAIN,	 A_P_MAUX,		 SPSH_MN },
1599 	{ TOK_PUSH,	TOK_AUX,	 A_P_MAUX,		 SPSH_AU },
1600 	{ TOK_PUSH,	TOK_THRE,	 A_P_32,			 SPSH_32 },
1601 	{ TOK_PUSH,	TOK_TWO,	 A_P_32,			 SPSH_32 },
1602 	{ TOK_PUSH,	TOK_FOUR,	 A_P_41,			 SPSH_4 },
1603 	{ TOK_PUSH,	TOK_ONE,	 A_PSH_ONE_2,	 SPSH_1C },
1604 	{ TOK_PUSH,	TOK_ONE,	 A_P_41,			 SPSH_1B },
1605 	{ TOK_HELP, 0xff,		 A_MISC,			 SHELP5 },
1606 	{ TOK_LOOK, 0xff,		 A_MISC,			 SLOOK2 },
1607 	{ 0x00,		0x00,		 0,				 0 }
1608 };
1609 
1610 
1611 
1612 
1613 
1614 
1615 /* bytecodes for the auto commands */
1616 const BYTE STURNGR[] = { I_SH_MSG,0x23,I_SH_DEAD };
1617 const BYTE STHROTL[] = { I_SH_MSG,0x24,I_SH_DEAD };
1618 const BYTE SSHOT[] = { I_SH_MSG,0x25,I_SH_DEAD };
1619 const BYTE SMELT_I[] = { I_SH_SWAP,0x0e,I_SH_TELL };
1620 const BYTE STELLME[] = { I_SH_TELL };
1621 
1622 
1623 
1624 /*
1625 // list of auto command combinations
1626 // terminated with a zero byte
1627 // these processed at the end of each parse cycle
1628 
1629 // for each entry:
1630 // 1st = verb token code (wildcard, matches any verb)
1631 // 2nd = noun token code (wildcard, matches any noun)
1632 // 3rd = address of predicate list entry
1633 // 4th = unknown address
1634 */
1635 
1636 const VNDef AUT_LST[] =
1637 {
1638 	{ 0xff, 0xff,  A_CHGRN,  STURNGR },
1639 	{ 0xff, 0xff,  A_CHTHR,  STHROTL },
1640 	{ 0xff, 0xff,  A_C2THR,  STHROTL },
1641 	{ 0xff, 0xff,  A_SHOT,   SSHOT },
1642 	{ 0xff, 0xff,  A_MELTD,  SMELT_I },
1643 	{ 0xff, 0xff,  A_NULL,   STELLME }
1644 };
1645 
1646 
1647 
1648 /*
1649 // ======================================================================
1650 // output a character to the display
1651 // ======================================================================
1652 */
1653 
i_PutCh(char ch)1654 void i_PutCh(char ch)
1655 {
1656 	putchar(ch);
1657 
1658 	if (ch == '\n')
1659 		nRemColumns = MAX_COL;
1660 
1661 }
1662 
1663 /*
1664 // ======================================================================
1665 // throw a new line on the display
1666 // ======================================================================
1667 */
1668 
PrintCR()1669 void PrintCR()
1670 {
1671 	i_PutCh('\n');
1672 }
1673 
1674 /*
1675 // ======================================================================
1676 // clear the screen
1677 // ======================================================================
1678 */
1679 
ClearScr()1680 void ClearScr()
1681 {
1682 	putchar(12);
1683 #ifdef PICS
1684 	clg();
1685 #endif
1686 	/*
1687 	int n;
1688 	for (n = 0; n < 50; ++n)
1689 		printf("\n");
1690 
1691 	nRemColumns = MAX_COL;
1692 	*/
1693 }
1694 
1695 /*
1696 // ======================================================================
1697 // print the zero-terminated string pointed to by HL
1698 // performing word-wrap and scrolling if necessary
1699 // ======================================================================
1700 */
1701 
PrintStr(unsigned char * hl)1702 void PrintStr(unsigned char* hl)
1703 {
1704 	unsigned char ch;
1705 	unsigned char *temphl;
1706 	int b;
1707 
1708 
1709 	for (;;)
1710 	{
1711 		ch = *hl++;
1712 		if (ch == 0)
1713 			return;
1714 
1715 		switch (ch)
1716 		{
1717 		case '\n':
1718 			PrintCR();
1719 			break;
1720 
1721 		case ' ':
1722 			break;
1723 
1724 		default:
1725 			--hl;
1726 			temphl = hl;
1727 			b = 0;
1728 
1729 			for (;;)
1730 			{
1731 				ch = *hl;
1732 				if ((ch == ' ') || (ch == '\0') || (ch == '\n'))
1733 					break;
1734 				++b;
1735 				++hl;
1736 			}
1737 
1738 			if (b > nRemColumns)
1739 				PrintCR();
1740 
1741 			hl = temphl;
1742 
1743 			for (;;)
1744 			{
1745 				ch = *hl;
1746 				if ((ch == ' ') || (ch == '\0') || (ch == '\n'))
1747 					break;
1748 
1749 				i_PutCh(ch);
1750 				++hl;
1751 			}
1752 
1753 			if ((nRemColumns - b) != 0)
1754 			{
1755 				i_PutCh(' ');
1756 				nRemColumns = nRemColumns - b - 1;
1757 			}
1758 			else
1759 				nRemColumns = nRemColumns - b;
1760 
1761 			break;
1762 		}
1763 	}
1764 }
1765 
1766 
1767 
1768 
1769 /****
1770 
1771 ; main program starts here
1772 
1773 START	ld      hl,GVARS				; zero all game variables
1774       	ld      b,$1e
1775 INITLP	ld      (hl),$00
1776       	inc     hl
1777         djnz    INITLP
1778 
1779       	ld      hl,$0000
1780       	ld      (SCORE),hl
1781       	call    PrintInstr					; display instructions
1782 
1783 		// copied to main - initialize naItemLoc
1784 
1785       	ld      ix,GVARS				; initialize ix to point at the game variables
1786       	ld      (CUR_RM),$00	; set current room to 0 (starting room)
1787       	push    hl						; save hl (points at naItemLoc)
1788       	jr      RESTG					; skip message data...
1789 
1790 RESTG_M	.text	"WANT TO RESTORE A GAME?"
1791 		.byte	$0d,$00
1792 
1793 RESTG	ld      hl,RESTG_M				; prompt - restore game?
1794       	call    PrintStr					; print it
1795       	pop     hl						; restore hl (points at naItemLoc)
1796       	call    i_GetCh
1797 
1798       	cp      'Y'
1799       	call    z,LCASS					; user typed 'Y', go and restore game
1800 
1801 
1802 ; main execution loop
1803 
1804 MAIN	call    ClearScr
1805         xor     a
1806       	cp      (ix+$00)				; if (ix+$00) is zero,
1807       	jr      z,ROOM					; go and display the room description
1808       	cp      (ix+$03)				; if (ix+$03) is zero,
1809       	jr      z,DARK_CH				; go straight to the dark check
1810         dec     (ix+$03)				; otherwise, decrement (ix+$03)
1811 
1812 DARK_CH	ld      a,(naItemLoc)				; get location of item $00
1813       	cp      (CUR_RM)		; check whether it's in the current room
1814       	jr      z,ROOM					; if it is, it's not dark
1815       	push    hl
1816       	jr      DARK					; skip message data...
1817 
1818 DARK_M	.text	"EVERYTHING IS DARK.I CANT SEE."
1819 		.byte	$0d,$00
1820 
1821 DARK	ld      hl,DARK_M				; say it's dark and we can't see
1822       	call    PrintStr
1823       	pop     hl
1824         xor     a
1825       	cp      (ix+$04)				; if (ix+$04) is zero,
1826       	jr      z,DARK_ND				; go straight to ????????
1827         dec     (ix+$04)				; otherwise, decrement (ix+$04)
1828 
1829 DARK_ND	jr      DO_AUTO					; (96)
1830 
1831 
1832 ****/
1833 
1834 
1835 /* display description for current room */
1836 
ShowRoom()1837 void ShowRoom()
1838 {
1839 	int nItem;
1840 
1841 #ifdef PICS
1842 	switch(CUR_RM)
1843 	{
1844 		case 0:
1845 			draw_profile(60, 60, 160, mountain);
1846 			draw_profile(63, 63, 152, mountain);
1847 			draw(135,73,175,71);
1848 			draw_profile(80, 80, 240, tree2);
1849 			draw_profile(80, 120, 80, mountain);
1850 			draw_profile(60, 110, 200, tree2);
1851 			break;
1852 		case 3:
1853 			for (nItem = 1; nItem < 5; ++nItem) {
1854 				draw_profile(nItem*10-rand()%100, 20+rand()%40, 170+nItem*20, tree2);
1855 				draw_profile(60-rand()%100, nItem+rand()%40, 170+nItem*20, tree1);
1856 			}
1857 			break;
1858 		case 4:
1859 			draw_profile(50, 20, 160, lake);
1860 			break;
1861 		case 5:
1862 			//draw_profile(50, 20, 240, strange_house);
1863 			break;
1864 		case 6:
1865 			draw_profile(60, 3, 180, shed);
1866 			break;
1867 		case 7:
1868 		case 8:
1869 		case 9:
1870 		case 10:
1871 			draw_profile(60, 60, 240, maze);
1872 			break;
1873 		case 14:
1874 			draw_profile(20, 100, 200, keyboard);
1875 			break;
1876 		case 19:
1877 			draw_profile(60, 20, 160, jail);
1878 			break;
1879 
1880 	}
1881 #endif
1882 
1883 	PrintStr(straRoom[CUR_RM]);
1884 
1885 	FLAG = FALSE;
1886 	for (nItem = 0; nItem < MAX_ITEM; ++nItem)
1887 	{
1888 		if (naItemLoc[nItem] == CUR_RM)
1889 		{
1890 			if (!FLAG)
1891 			{
1892 				PrintStr("I can also see :\n");
1893 				FLAG = TRUE;
1894 			}
1895 			PrintStr(straItem[nItem]);
1896 			PrintCR();
1897 		}
1898 	}
1899 
1900 	nNextParseAction = NA_DO_AUTO;
1901 }
1902 /*****
1903 
1904 // ======================================================================
1905 // perform regular automatic functions, e.g. the little green man
1906 // ======================================================================
1907 
1908 void DO_AUTO()
1909 {
1910 	ld      hl,AUT_LST				; select the auto command list (wildcards, every command matches)
1911       	jp      PARS_LP					; and restart parser
1912 
1913 
1914 ***/
1915 
1916 /*
1917 // ======================================================================
1918 // system command - TELL command
1919 // generates the "tell me what to do" prompt
1920 // ======================================================================
1921 */
1922 
SH_TELL()1923 void SH_TELL()
1924 {
1925 	BYTE* pDirections;
1926 
1927 	if (GVARS[GVAR_02] > 0)
1928 		--GVARS[GVAR_02];
1929 
1930 	if (GVARS[GVAR_05] > 0)
1931 		--GVARS[GVAR_05];
1932 
1933 	/***
1934 	{
1935 		char sz[256];
1936 		sprintf(sz, "02 = %u\n", GVARS[0x02]);
1937 		PrintStr(sz);
1938 	}
1939 	***/
1940 
1941 	PrintStr("Tell me what to do \n");
1942 
1943 	GetLine();
1944 	F_NTYET = FALSE;
1945 /*
1946 // ======================================================================
1947 // fetch verb token from the input buffer
1948 // ======================================================================
1949 */
1950 
1951 	pchEditLine = chaEditLine;
1952 
1953 	for (;;)
1954 	{
1955 		VERB_TK = GET_TOK();
1956 		if (VERB_TK == 0xff)
1957 		{
1958 			BOOL bDont = FALSE;
1959 			if ((*pchEditLine == '\n') || (*pchEditLine == '\0'))
1960 				bDont = TRUE;
1961 			else
1962 			{
1963 				for (;;)
1964 				{
1965 					if (*pchEditLine == ' ')
1966 					{
1967 						++pchEditLine;
1968 						goto verb_outer_continue;
1969 					}
1970 					else if ((*pchEditLine == '\n') || (*pchEditLine == '\0'))
1971 					{
1972 						bDont = TRUE;
1973 						break;
1974 					}
1975 					++pchEditLine;
1976 				}
1977 			}
1978 
1979 			if (bDont)
1980 			{
1981 				PrintStr("I don't understand\n");
1982 				nNextParseAction = NA_DO_AUTO;
1983 				return;
1984 			}
1985 		}
1986 		else
1987 			break;		/* verb ok */
1988 
1989 verb_outer_continue:
1990 		continue;
1991 	}
1992 
1993 	/* verb recognized */
1994 	NOUN_TK = 0xff;		/* assume noun unrecognized before reading on */
1995 
1996 
1997 	/* trim off excess characters from the verb */
1998 	for (;;)
1999 	{
2000 		char ch = *pchEditLine;
2001 
2002 		if (ch == ' ')
2003 			break;
2004 
2005 		if (ch == '\0')
2006 			goto P_DIR;
2007 
2008 		if (ch == '\n')
2009 			goto P_DIR;
2010 
2011 		++pchEditLine;
2012 	}
2013 
2014 /*
2015 // ======================================================================
2016 // fetch noun token from the input buffer
2017 // ======================================================================
2018 */
2019 
2020 	for (;;)
2021 	{
2022 		++pchEditLine;
2023 		NOUN_TK = GET_TOK();
2024 
2025 
2026 		if (NOUN_TK != 0xff)
2027 			break;
2028 
2029 		for (;;)
2030 		{
2031 			char ch = *pchEditLine;
2032 
2033 			if (ch == ' ')
2034 				break;
2035 
2036 			if (ch == '\0')
2037 				goto P_DIR;
2038 
2039 			if (ch == '\n')
2040 				goto P_DIR;
2041 
2042 			++pchEditLine;
2043 		}
2044 	}
2045 
2046 /*
2047 // ======================================================================
2048 // attempt to parse a direction verb
2049 // ======================================================================
2050 */
2051 
2052 P_DIR:
2053 
2054 	pDirections = DIR_V[CUR_RM];
2055 
2056 	for (;;)
2057 	{
2058 		int nDir  =  *pDirections;
2059 
2060 		if (nDir == 0xff)
2061 			break;
2062 
2063 		if (nDir == VERB_TK)
2064 		{
2065 			CUR_RM = pDirections[1];
2066 			nNextParseAction = NA_MAIN;
2067 			return;
2068 		}
2069 
2070 		pDirections += 2;
2071 	}
2072 
2073 	pvndCurrent = vndDefinitions;
2074 	CMDFLG = FALSE;
2075 	nNextParseAction = NA_BEGIN;
2076 }
2077 
2078 extern const void *SYS_V[];
2079 
PARSE_LP()2080 void PARSE_LP()
2081 {
2082 	int nVerbTok = pvndCurrent->nVerbTok;
2083 
2084 	if (nVerbTok == 0)
2085 	{
2086 		if (!CMDFLG)
2087 		{
2088 			if (VERB_TK < TOK_GET)		/* direction? */
2089 				PrintStr("I can't go in that direction\n");
2090 			else if (F_NTYET)
2091 				PrintStr("I can't do that yet\n");
2092 			else
2093 				PrintStr("I can't\n");
2094 		}
2095 		nNextParseAction = NA_DO_AUTO;
2096 		return;
2097 	}
2098 
2099 	if ((nVerbTok == 0xff) || (nVerbTok == VERB_TK))
2100 	{
2101 		int nNounTok = pvndCurrent->nNounTok;
2102 
2103 		if ((nNounTok == 0xff) || (nNounTok == NOUN_TK))
2104 		{
2105 			int nPred;
2106 			pPredicateCurrent = (BYTE*) pvndCurrent->pPredicates;
2107 
2108 			while ((nPred = *pPredicateCurrent++) != 0xff)
2109 			{
2110 				BOOL (*pfn)() = PRED_V[nPred];
2111 				PARAM1 = *pPredicateCurrent;
2112 				if (!pfn())
2113 				{
2114 					F_NTYET = TRUE;
2115 					nNextParseAction = NA_CONTINUE;
2116 					return;
2117 				}
2118 				++pPredicateCurrent;
2119 			}
2120 			/* execute command */
2121 			pActionCurrent = (BYTE*) pvndCurrent->pActions;
2122 			CMDFLG = TRUE;
2123 
2124 			nNextParseAction = NA_CONTINUE;
2125 
2126 			for (;;)
2127 			{
2128 				if (*pActionCurrent == 0xff)
2129 					return;
2130 				else
2131 				{
2132 					void (*pfn)() = (void*) (SYS_V[*pActionCurrent++]);
2133 
2134 					PARAM1 = *pActionCurrent;
2135 					pfn();
2136 
2137 					if (nNextParseAction != NA_CONTINUE)
2138 						return;
2139 
2140 					++pActionCurrent;
2141 				}
2142 			}
2143 
2144 
2145 
2146 			PrintStr("Executed!\n");
2147 		}
2148 	}
2149 
2150 	nNextParseAction = NA_CONTINUE;
2151 	return;
2152 }
2153 
2154 
2155 
2156 
2157 
2158 
2159 
2160 /* predicates */
2161 
2162 
2163 /*
2164 // predicate CHKROOM - this tests the current room number to make sure it's the specified room number.
2165 // if it is, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2166 // this handler interprets PARAM1 as the room number
2167 */
2168 
CHKROOM()2169 BOOL CHKROOM()
2170 {
2171 	return PARAM1 == CUR_RM;
2172 }
2173 
2174 
2175 /*
2176 // predicate for GET and DROP commands
2177 // this handler interprets PARAM1 as the item number
2178 */
2179 
CHKHERE()2180 BOOL CHKHERE()
2181 {
2182 	int nLoc = naItemLoc[PARAM1];
2183 
2184 	return (nLoc == CUR_RM) || (nLoc >= ITEM_WORN);
2185 }
2186 
2187 /*
2188 // predicate CHKRAND - randomly allows or disallows the user's command.
2189 // if allowed, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2190 */
2191 
CHKRAND()2192 BOOL CHKRAND()
2193 {
2194 	return (rand() % 256) < PARAM1;
2195 }
2196 
2197 
2198 /*
2199 // predicate CHKAWAY - checks that the specified item is not carried, held or in the current room.
2200 // if it is NOT, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2201 // this handler interprets PARAM1 as the item number
2202 */
2203 
CHKAWAY()2204 BOOL CHKAWAY()
2205 {
2206 	return !CHKHERE();
2207 }
2208 
2209 
2210 /*
2211 // predicate CHKWORN - checks that the specified item is being worn.
2212 // if it is, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2213 // this handler interprets PARAM1 as the item number
2214 */
2215 
CHKWORN()2216 BOOL CHKWORN()
2217 {
2218 	return naItemLoc[PARAM1] == ITEM_WORN;
2219 }
2220 
2221 
2222 /*
2223 // predicate CHKSETF - checks the game variable specified by PARAM1.
2224 // if it is non-zero, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2225 // this handler interprets PARAM1 as the game variable number
2226 // used by "field" and "look up"
2227 */
2228 
CHKSETF()2229 BOOL CHKSETF()
2230 {
2231 	return !!GVARS[PARAM1];
2232 }
2233 
2234 
2235 
2236 /*
2237 // predicate TSTGVAR - compares the game variable specified by PARAM1 with the value specified as
2238 // the next byte after the command.
2239 // if it is equal, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2240 // this handler interprets PARAM1 as the game variable number
2241 */
2242 
TSTGVAR()2243 BOOL TSTGVAR()
2244 {
2245 	int nParam2 = *++pPredicateCurrent;
2246 	return GVARS[PARAM1] == nParam2;
2247 }
2248 
2249 
2250 /*
2251 // predicate CHKCLRF - checks the game variable specified by PARAM1.
2252 // if it is zero, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2253 // this handler interprets PARAM1 as the game variable number
2254 */
2255 
CHKCLRF()2256 BOOL CHKCLRF()
2257 {
2258 	return !CHKSETF();
2259 }
2260 
2261 
2262 /*
2263 // predicate CHKHELD - checks that the specified item is being carried (or worn!).
2264 // if it is, we move on to the next command, otherwise we trigger a "i can't do that yet" response.
2265 // this handler interprets PARAM1 as the item number
2266 */
2267 
CHKHELD()2268 BOOL CHKHELD()
2269 {
2270 	return (naItemLoc[PARAM1] == ITEM_HELD) || (naItemLoc[PARAM1] == ITEM_WORN);
2271 }
2272 
2273 
2274 /***
2275 
2276 
2277 
2278 
2279 
2280 
2281 ; fetch location for an item
2282 ; item number is in PARAM1
2283 ; location is returned in A
2284 ; address of location entry is returned in HL
2285 
2286 GET_LOC	ld      hl,naItemLoc
2287       	ld      b,$00
2288         ld      c,(PARAM1)
2289       	add     hl,bc
2290       	ld      a,(hl)
2291       	ret
2292 
2293 
2294 
2295 
2296 ***/
2297 
2298 
2299 
SH_INVE()2300 void SH_INVE()
2301 {
2302 	int bNothing=TRUE;
2303 	int nItem;
2304 	int nLoc;
2305 
2306 	PrintStr("I have with me the following:\n");
2307 
2308 	for (nItem = 0; nItem < MAX_ITEM; ++nItem)
2309 	{
2310 		nLoc = naItemLoc[nItem];
2311 
2312 		if (nLoc >= ITEM_WORN)
2313 		{
2314 			bNothing = FALSE;
2315 			PrintStr(straItem[nItem]);
2316 			if (nLoc == ITEM_WORN)
2317 				PrintStr(" which i am wearing");
2318 			PrintCR();
2319 		}
2320 	}
2321 
2322 	if (bNothing)
2323 		PrintStr("Nothing at all\n");
2324 
2325 	nNextParseAction = NA_DO_AUTO;
2326 }
2327 
2328 
2329 /*
2330 // ======================================================================
2331 // system command - REMOVE command
2332 // item to be removed is specified in PARAM1
2333 // ======================================================================
2334 */
2335 
SH_REMO()2336 void SH_REMO()
2337 {
2338 	if (naItemLoc[PARAM1] == ITEM_WORN)
2339 	{
2340 		if (GVARS[GVAR_NO_ITEMS] == 6)
2341 		{
2342 			PrintStr("I cant. My hands are full\n");
2343 			nNextParseAction = NA_DO_AUTO;
2344 		}
2345 		else
2346 		{
2347 			naItemLoc[PARAM1] = ITEM_HELD;
2348 			++GVARS[GVAR_NO_ITEMS];
2349 		}
2350 	}
2351 	else
2352 	{
2353 		PrintStr("I am not wearing it\n");
2354 		nNextParseAction = NA_DO_AUTO;
2355 	}
2356 }
2357 
2358 
2359 
2360 
2361 /*
2362 // ======================================================================
2363 // system command - GET command
2364 // item to be got is specified in PARAM1
2365 // ======================================================================
2366 */
2367 
SH_GET()2368 void SH_GET()
2369 {
2370 	if (GVARS[GVAR_NO_ITEMS] == 6)
2371 	{
2372 		PrintStr("I can't carry any more\n");
2373 		nNextParseAction = NA_DO_AUTO;
2374 	}
2375 	else if (naItemLoc[PARAM1] == CUR_RM)
2376 	{
2377 		naItemLoc[PARAM1] = ITEM_HELD;
2378 		++GVARS[GVAR_NO_ITEMS];
2379 	}
2380 	else if ((naItemLoc[PARAM1] == ITEM_WORN) || (naItemLoc[PARAM1] == ITEM_HELD))
2381 	{
2382 		PrintStr("I already have it\n");
2383 		nNextParseAction = NA_DO_AUTO;
2384 	}
2385 	else
2386 	{
2387 		PrintStr("I don't see it here\n");
2388 		nNextParseAction = NA_DO_AUTO;
2389 	}
2390 }
2391 
2392 /*
2393 // ======================================================================
2394 // system command - DROP command
2395 // item to be dropped is specified in PARAM1
2396 // ======================================================================
2397 */
2398 
SH_DROP()2399 void SH_DROP()
2400 {
2401 	if (naItemLoc[PARAM1] == CUR_RM)
2402 	{
2403 		PrintStr("I don't have it\n");
2404 		nNextParseAction = NA_DO_AUTO;
2405 	}
2406 	else if (naItemLoc[PARAM1] == ITEM_WORN)
2407 	{
2408 		naItemLoc[PARAM1] = CUR_RM;
2409 	}
2410 	else if (naItemLoc[PARAM1] == ITEM_HELD)
2411 	{
2412 		--GVARS[GVAR_NO_ITEMS];
2413 		naItemLoc[PARAM1] = CUR_RM;
2414 	}
2415 	else
2416 	{
2417 		PrintStr("I don't have it\n");
2418 		nNextParseAction = NA_DO_AUTO;
2419 	}
2420 }
2421 
2422 
2423 /*
2424 // ======================================================================
2425 // system command - WEAR command
2426 // item to be worn is specified in PARAM1
2427 // ======================================================================
2428 */
2429 
SH_WEAR()2430 void SH_WEAR()
2431 {
2432 	if (naItemLoc[PARAM1] == ITEM_HELD)
2433 	{
2434 		naItemLoc[PARAM1] = ITEM_WORN;
2435 		--GVARS[GVAR_NO_ITEMS];
2436 	}
2437 	else if (naItemLoc[PARAM1] == ITEM_WORN)
2438 	{
2439 		PrintStr("I am already wearing it\n");
2440 		nNextParseAction = NA_DO_AUTO;
2441 	}
2442 	else
2443 	{
2444 		PrintStr("I don't have it\n");
2445 		nNextParseAction = NA_DO_AUTO;
2446 	}
2447 }
2448 
2449 
2450 /*
2451 // ======================================================================
2452 // system command - display a response
2453 // index of response to be displayed is specified in PARAM1
2454 // ======================================================================
2455 */
2456 
2457 
SH_MSG()2458 BOOL SH_MSG()
2459 {
2460 	PrintStr(straMsg[PARAM1]);
2461 	return TRUE;
2462 }
2463 
2464 
2465 /*
2466 // ======================================================================
2467 // system command - REDE
2468 // redescribe current room, terminating execution of system commands
2469 // ======================================================================
2470 */
2471 
SH_REDE()2472 void SH_REDE()
2473 {
2474 	nNextParseAction = NA_MAIN;
2475 }
2476 
2477 /*
2478 // ======================================================================
2479 // exactly the same effect as SH_FAIL - it halts further system command
2480 // processing,
2481 // and proceeds to execute the auto commands.
2482 // ======================================================================
2483 */
2484 
SH_AUTO()2485 void SH_AUTO()
2486 {
2487 	nNextParseAction = NA_DO_AUTO;
2488 }
2489 
2490 /*
2491 // ======================================================================
2492 // system command - go directly to specific room (do not pass go)
2493 // index of room is specified in PARAM1
2494 // NB: room description not automatically displayed
2495 // ======================================================================
2496 */
2497 
SH_GOTO()2498 void SH_GOTO()
2499 {
2500 	CUR_RM = PARAM1;
2501 }
2502 
2503 
2504 /*
2505 // ======================================================================
2506 // system command SETF - set game variable to $ff
2507 // index of variable to set is specified in PARAM1
2508 // ======================================================================
2509 */
2510 
SH_SETF()2511 void SH_SETF()
2512 {
2513 	GVARS[PARAM1] = 0xff;
2514 }
2515 
2516 
2517 /*
2518 // ======================================================================
2519 // system command CLRF - clear game variable to $00
2520 // index of variable to clear is specified in PARAM1
2521 // ======================================================================
2522 */
2523 
SH_CLRF()2524 void SH_CLRF()
2525 {
2526 	GVARS[PARAM1] = 0x00;
2527 }
2528 
2529 /*
2530 // ======================================================================
2531 // system command - SWAP
2532 // swap an item's location with the location of the following item
2533 // item to be swapped is specified in PARAM1
2534 // ======================================================================
2535 */
2536 
SH_SWAP()2537 void SH_SWAP()
2538 {
2539 	int nTemp = naItemLoc[PARAM1];
2540 	naItemLoc[PARAM1] = naItemLoc[PARAM1 + 1];
2541 	naItemLoc[PARAM1 + 1] = nTemp;
2542 }
2543 
2544 /*
2545 // ======================================================================
2546 // system command - DEAD
2547 // immediately terminate game, stop executing system commands
2548 // ======================================================================
2549 */
2550 
SH_DEAD()2551 void SH_DEAD()
2552 {
2553 
2554 	PrintStr("Do you wish to try again?\n");
2555 
2556 	for (;;)
2557 	{
2558 		char ch;
2559 
2560 		PrintStr("Answer yes or no\n");
2561 		ch = i_GetCh();
2562 		if (ch == 'Y')
2563 		{
2564 			nNextParseAction = NA_RESTART;
2565 			return;
2566 		}
2567 		if (ch == 'N')
2568 		{
2569 			exit(0);
2570 		}
2571 	}
2572 }
2573 
2574 
2575 
2576 
2577 
2578 
2579 
2580 
2581 
2582 /* display "OK.." prompt and cease processing system commands */
2583 
2584 
SH_OK()2585 void SH_OK()
2586 {
2587 	PrintStr("OK..\n");
2588 	nNextParseAction = NA_DO_AUTO;
2589 }
2590 
2591 
2592 
2593 
SH_QUIT()2594 void SH_QUIT()
2595 {
2596 
2597 /* TAPE and DISKBLOCK mode save */
2598 #ifdef TAPE
2599 	PrintStr("Do you want to save the game?\n");
2600 
2601 	if (i_GetCh() == 'Y')
2602 	{
2603 		/* save */
2604 #ifdef DISKBLOCK
2605 		PrintStr("\nPrepare disc or cartrige, then press a key\n");
2606 #else
2607 		PrintStr("\nStart tape, then press a key\n");
2608 #endif
2609 		i_GetCh();
2610 
2611 #ifdef DISKBLOCK
2612 		rnd_erase("GVARS.SAV");
2613 		rnd_saveblock("GVARS.SAV", GVARS, sizeof(GVARS));
2614 #else
2615 		tape_save_block(GVARS, sizeof(GVARS), 1);
2616 #endif
2617 
2618 #ifdef COMPUTE_SCORE
2619 #ifdef DISKBLOCK
2620 		rnd_erase("SCORE.SAV");
2621 		rnd_saveblock("SCORE.SAV", &nScore, sizeof(nScore));
2622 #else
2623 		tape_save_block(&nScore, sizeof(nScore), 2);
2624 #endif
2625 #endif
2626 
2627 #ifdef DISKBLOCK
2628 		rnd_erase("ITEMS.SAV");
2629 		rnd_erase("ROOM.SAV");
2630 		rnd_saveblock("ITEMS.SAV", &naItemLoc, sizeof(naItemLoc));
2631 		rnd_saveblock("ROOM.SAV", &CUR_RM, sizeof(CUR_RM));
2632 #else
2633 		tape_save_block(naItemLoc, sizeof(naItemLoc), 3);
2634 		tape_save_block(&CUR_RM, sizeof(CUR_RM), 4);
2635 #endif
2636 
2637 #endif
2638 
2639 
2640 /*  Save game to DISK with standard C functions */
2641 #ifdef DISK
2642 	PrintStr("Do you want to save the game?\n");
2643 
2644 	if (i_GetCh() == 'Y')
2645 	{
2646 		/* save */
2647 		fpsave=fopen("adv_a.sav","wb");
2648 		fwrite(GVARS, sizeof(GVARS),1, fpsave);
2649 #ifdef COMPUTE_SCORE
2650 		fwrite(&nScore, sizeof(nScore),1, fpsave);
2651 #endif
2652 		fwrite(naItemLoc, sizeof(naItemLoc),1, fpsave);
2653 		fwrite(&CUR_RM, sizeof(CUR_RM),1, fpsave);
2654 		fclose(fpsave);
2655 #endif
2656 
2657 		PrintStr("Do you wish to continue?\n");
2658 
2659 		if (i_GetCh() == 'Y')
2660 		{
2661 			nNextParseAction = NA_DO_AUTO;
2662 			return;
2663 		}
2664 #ifdef TAPE
2665 	}
2666 #endif
2667 #ifdef DISK
2668 	}
2669 #endif
2670 
2671 	SH_DEAD();
2672 }
2673 
2674 
2675 
2676 
2677 
2678 /*
2679 // ======================================================================
2680 // system command SETV - set game variable to a specific value
2681 // index of variable to set is specified in PARAM1
2682 // the new value is specified as the byte after this command
2683 // ======================================================================
2684 */
2685 
SH_SETV()2686 void SH_SETV()
2687 {
2688 	int nParam2 = *++pActionCurrent;
2689 
2690 	GVARS[PARAM1] = nParam2;
2691 }
2692 
2693 
2694 /*
2695 // ======================================================================
2696 // system command CREA - create item in current room
2697 // index of item to be created is specified in PARAM1
2698 // ======================================================================
2699 */
2700 
SH_CREA()2701 void SH_CREA()
2702 {
2703 	naItemLoc[PARAM1] = CUR_RM;
2704 }
2705 
2706 
2707 /*
2708 // ======================================================================
2709 // system command DEST - destroy item in current room
2710 // index of item to be destoyed is specified in PARAM1
2711 // ======================================================================
2712 */
2713 
SH_DEST()2714 void SH_DEST()
2715 {
2716 	naItemLoc[PARAM1] = NOTX;
2717 }
2718 
2719 
2720 
2721 
2722 
2723 
2724 /* clean-up and abort execution of system commands, continuing with auto commands */
2725 
SH_FAIL()2726 void SH_FAIL()
2727 {
2728 	nNextParseAction = NA_DO_AUTO;
2729 }
2730 
2731 
2732 /*
2733 // ======================================================================
2734 // system command ADSC - add value to the current score.
2735 // value to be added is specified in PARAM1
2736 // ======================================================================
2737 */
2738 
SH_ADSC()2739 void SH_ADSC()
2740 {
2741 #ifdef COMPUTE_SCORE
2742 	nScore += PARAM1;
2743 #endif
2744 }
2745 
SH_SCOR()2746 void SH_SCOR()
2747 {
2748 #ifdef COMPUTE_SCORE
2749 	char szScore[32];
2750 
2751 	PrintStr("You have a score of ");
2752 
2753 #ifndef printn
2754 	sprintf(szScore, "%04x", nScore);		// hex! (really)
2755 	PrintStr(szScore);
2756 #else
2757 	printn(nScore,16,stdout);
2758 #endif
2759 	PrintCR();
2760 #endif
2761 }
2762 
2763 /* addresses of various system function handlers */
2764 
2765 const void* SYS_V[] =
2766 {
2767 	SH_INVE,
2768 	SH_REMO,
2769 	SH_GET,
2770 	SH_DROP,
2771 	SH_WEAR,
2772 	SH_MSG,
2773 	SH_REDE,
2774 	SH_AUTO,
2775 	SH_GOTO,
2776 	SH_SETF,
2777 	SH_CLRF,
2778 	SH_SWAP,
2779 	SH_DEAD,
2780 	SH_OK,
2781 	SH_QUIT,
2782 	SH_SETV,
2783 	SH_CREA,
2784 	SH_DEST,
2785 	SH_ADSC,
2786 	SH_SCOR,
2787 	SH_FAIL,
2788 	SH_TELL,
2789 	SH_FAIL,
2790 	SH_FAIL,
2791 	SH_FAIL
2792 };
2793 
2794 /*
2795 // ======================================================================
2796 // fetch command token from the input buffer, starting at position HL
2797 // on return, A contains the token code (or $ff if not recognized)
2798 // and HL points to the character after the token
2799 // ======================================================================
2800 */
2801 
GET_TOK()2802 int GET_TOK()
2803 {
2804 	char *pchTokenBuffer = strTokenBuf;
2805 	int nResult = 0xff;
2806 	int n;
2807 
2808 	strncpy(strTokenBuf, "    ", 4);	/* clear the token buffer to spaces */
2809 
2810 	for (n = 0; n < 4; ++n)
2811 	{
2812 		char ch = *pchEditLine;
2813 		if (ch == ' ')
2814 			break;
2815 
2816 		if (ch == '\0')
2817 			break;
2818 
2819 		if (ch == '\n')
2820 			break;
2821 
2822 		*pchTokenBuffer++ = ch;
2823 		++pchEditLine;
2824 	}
2825 
2826 	for (n = 0; n < MAX_TOK; ++n)
2827 	{
2828 		if (strncmp(strTokenBuf, taToken[n].strWord, 4) == 0)
2829 		{
2830 			nResult = taToken[n].nCode;
2831 			break;
2832 		}
2833 	}
2834 
2835 	return nResult;
2836 }
2837 
2838 
2839 /***
2840 
2841 
2842 
2843 ; ======================================================================
2844 
2845 
2846 
2847 LCASS	push    hl
2848       	jr      LCASS_1                   ; (16)
2849 
2850 LCASS_M	.text	"READY CASSETTE"
2851 		.byte	$0d,$00
2852 
2853 LCASS_1	ld      hl,LCASS_M
2854       	call    PrintStr
2855       	pop     hl
2856       	call    i_GetCh
2857       	push    ix
2858       	ld      ix,FLAG
2859       	ld      de,$0029
2860       	ld      a,$ff
2861         scf
2862       	call    ROM_LD
2863       	ld      ix,naItemLoc
2864       	ld      de,$001d
2865       	ld      a,$ff
2866         scf
2867       	call    ROM_LD
2868       	pop     ix
2869       	ret
2870 
2871 ****/
2872 /*
2873 // ======================================================================
2874 // fetch key from buffer
2875 // waits for keypress, returns ascii code in A
2876 // ======================================================================
2877 */
2878 
i_GetCh()2879 char i_GetCh()
2880 {
2881         return toupper(fgetc(stdin));
2882 }
2883 
2884 /***
2885 
2886 		; unused keyboard-reading code (left over from ZX81 version?)
2887 
2888       	push    de
2889       	ld      d,a
2890       	ld      a,$7f
2891         in      a,($fe)
2892         rra
2893       	jr      c,ZX_END2
2894       	ld      a,$fe
2895         in      a,($fe)
2896         rra
2897       	jr      c,ZX_END2
2898       	ld      a,$01
2899         or      a
2900 
2901 ZX_END	ld      a,d
2902       	pop     de
2903       	ret
2904 
2905 ZX_END2	xor     a
2906 		jr      ZX_END                   ; (-6)
2907 
2908 
2909 ***/
2910 
2911 /*
2912 // ======================================================================
2913 // get a line of input from the user
2914 // store the data in the buffer pointed to by HL
2915 // ======================================================================
2916 */
2917 
GetLine()2918 void GetLine()
2919 {
2920         fgets(chaEditLine, MAX_COL, stdin);
2921         strupr(chaEditLine);
2922 }
2923 
2924 
2925 /*
2926 // ======================================================================
2927 // clear screen, display instructions and wait for keypress
2928 // ======================================================================
2929 */
2930 
PrintInstr()2931 void PrintInstr()
2932 {
2933 	ClearScr();
2934 	PrintStr(strInstructions);
2935 	i_GetCh();
2936 }
2937 
2938 
2939 
2940 
2941 /****
2942 
2943 
2944 
2945 
2946 
2947 
2948 
2949 
2950 
2951 
2952 
2953 
2954 
2955 
2956 
2957 ****/
2958 
2959 
2960 
2961 
2962 /****
2963 
2964 ; spurious data found in the original game
2965 
2966 GARBAGE	.word	$5200,$4c4f,$5220,$004f
2967 
2968 
2969 		.end
2970 ****/
2971 
2972 
2973 
2974 
main()2975 int main()
2976 {
2977 	int n;
2978 
2979 	printf("%cE",27);
2980 	for (;;)		/* restart game loop */
2981 	{
2982 		/* initialize the game variables */
2983 		for (n = 0; n <= 0x1e; ++n)
2984 			GVARS[n] = 0;
2985 
2986 #ifdef COMPUTE_SCORE
2987 		nScore = 0;
2988 #endif
2989 
2990 		PrintInstr();
2991 
2992 		/* copy data from naItemStart to naItemLoc at start of game */
2993 		for (n = 0; n < MAX_ITEM; ++n)
2994 			naItemLoc[n] = naItemStart[n];
2995 
2996 		CUR_RM = 0;
2997 
2998 #ifdef TAPE
2999 		PrintStr("Want to restore a game?\n");
3000 		if (i_GetCh() == 'Y')
3001 		{
3002 			/* restore */
3003 #ifdef DISKBLOCK
3004 			rnd_loadblock("GVARS.SAV", GVARS, sizeof(GVARS));
3005 #else
3006 			tape_load_block(GVARS, sizeof(GVARS), 1);
3007 #endif
3008 #ifdef COMPUTE_SCORE
3009 #ifdef DISKBLOCK
3010 			rnd_loadblock("SCORE.SAV", &nScore, sizeof(nScore));
3011 #else
3012 			tape_load_block(&nScore, sizeof(nScore), 2);
3013 #endif
3014 #endif
3015 #ifdef DISKBLOCK
3016 			rnd_loadblock("ITEMS.SAV", &naItemLoc, sizeof(naItemLoc));
3017 			rnd_loadblock("ROOM.SAV", &CUR_RM, sizeof(CUR_RM));
3018 #else
3019 			tape_load_block(naItemLoc, sizeof(naItemLoc), 3);
3020 			tape_load_block(&CUR_RM, sizeof(CUR_RM), 4);
3021 #endif
3022 		}
3023 #endif
3024 
3025 #ifdef DISK
3026 		PrintStr("Want to restore a game?\n");
3027 		if (i_GetCh() == 'Y')
3028 		{
3029 		/* restore */
3030 			fpsave=fopen("adv_a.sav","rb");
3031 			fread(GVARS, sizeof(GVARS),1, fpsave);
3032 #ifdef COMPUTE_SCORE
3033 			fread(&nScore, sizeof(nScore),1, fpsave);
3034 #endif
3035 			fread(naItemLoc, sizeof(naItemLoc),1, fpsave);
3036 			fread(&CUR_RM, sizeof(CUR_RM),1, fpsave);
3037 			fclose(fpsave);
3038 		}
3039 #endif
3040 
3041 /*
3042 			PrintStr("Restore not supported\n");
3043 			PrintStr("Press a key");
3044 			i_GetCh();
3045 */
3046 
3047 		for (;;)		/* main loop */
3048 		{
3049 			ClearScr();
3050 
3051 			if (GVARS[0] == 0)
3052 			{
3053       			ShowRoom();
3054 			}
3055 			else
3056 			{
3057 				if (GVARS[3] > 0)
3058 					--GVARS[3];
3059 
3060 				if (naItemLoc[0] == CUR_RM)
3061 				{
3062 	      			ShowRoom();
3063 				}
3064 				else
3065 				{
3066 					PrintStr("Everything is dark. I can't see.\n");
3067 					if (GVARS[4] > 0)
3068 						--GVARS[4];
3069 
3070 					nNextParseAction = NA_DO_AUTO;
3071 				}
3072 			}
3073 
3074 			for (;;)		/* parse loop */
3075 			{
3076 				switch (nNextParseAction)
3077 				{
3078 				case NA_DO_AUTO:
3079 					pvndCurrent = AUT_LST;
3080 					break;
3081 				case NA_CONTINUE:
3082 					++pvndCurrent;
3083 					break;
3084 				case NA_MAIN:
3085 				case NA_RESTART:
3086 					goto outer_cont;
3087 					break;
3088 				case NA_BEGIN:
3089 					break;
3090 				default:
3091 					PrintStr("Error\n");
3092 					++pvndCurrent;
3093 					break;
3094 				}
3095 
3096 				PARSE_LP();
3097 			}
3098 
3099 	outer_cont:
3100 			if (nNextParseAction == NA_RESTART)
3101 				break;
3102 		}
3103 	}
3104 
3105 	return 0;
3106 }
3107