#include #include #include #include typedef int BOOL; typedef unsigned char BYTE; enum { FALSE, TRUE }; /***** ; Disassembly of the file "F:\GAMES\SPECCY\A\ARTICADV\Advent_a.sna" ; ; Created with dZ80 v1.30a ; ; on Wednesday, 05 of August 1998 at 11:33 PM ; .org $5d6c ROM_SAV .equ $04c2 ROM_LD .equ $0556 ROM_CLS .equ $0daf SCRCT .equ $5c8c ; remaining scroll count (system variable) */ // item location codes #define NOTX 0xfc #define ITEM_WORN 0xfd #define ITEM_HELD 0xfe /* ; offsets of ZX Spectrum system variables #define SVAR_KEYBUF -$32 */ int F_NTYET; int PARAM1; int CMDFLG; /* PREDIX .equ $-$29 ; PREDIX points here */ int VERB_TK; int NOUN_TK; BOOL FLAG; int CUR_RM; /* */ int GVARS[0x1e]; // workspace of $1e bytes of game variables // offsets of game variables #define GVAR_NO_ITEMS 0x01 #define GVAR_02 0x02 #define GVAR_03 0x03 #define GVAR_04 0x04 #define GVAR_05 0x05 #define GVAR_06 0x06 #define GVAR_07 0x07 #define GVAR_08 0x08 #define GVAR_09 0x09 #define GVAR_0a 0x0a #define GVAR_0b 0x0b #define GVAR_0c 0x0c #define GVAR_0d 0x0d #define GVAR_0e 0x0e #define GVAR_0f 0x0f #define GVAR_10 0x10 #define GVAR_11 0x11 #define GVAR_12 0x12 #define GVAR_13 0x13 #define GVAR_14 0x14 #define GVAR_15 0x15 #define GVAR_16 0x16 #define GVAR_17 0x17 #define GVAR_18 0x18 #define GVAR_19 0x19 #define GVAR_1a 0x1a #define GVAR_1b 0x1b #define GVAR_1c 0x1c #define GVAR_1d 0x1d #define GVAR_1e 0x1e char strTokenBuf[4]; // workspace of $04 bytes to hold a token int nScore; #define MAX_COL 32 char chaEditLine[MAX_COL + 1]; char* pchEditLine; int nRemColumns = MAX_COL; typedef struct { int nVerbTok; int nNounTok; void* pPredicates; void* pActions; } VNDef; enum { NA_DO_AUTO, NA_CONTINUE, NA_MAIN, NA_BEGIN, NA_RESTART }; int nNextParseAction; VNDef* pvndCurrent; BYTE* pPredicateCurrent; BYTE* pActionCurrent; // ====================================================================== // game instructions // ====================================================================== char* strInstructions = "WELCOME TO ADVENTURE 'A'\n" "THE PLANET OF DEATH\n\n" "IN THIS ADVENTURE YOU FIND " "YOURSELF STRANDED ON AN " "ALIEN PLANET. YOUR AIM IS " "TO ESCAPE FROM THIS PLANET " "BY FINDING YOUR, NOW " "CAPTURED AND DISABLED, " "SPACE SHIP\n" "YOU WILL MEET VARIOUS " "HAZARDS AND DANGERS ON YOUR " "ADVENTURE, SOME NATURAL, " "SOME NOT, ALL OF WHICH YOU " "MUST OVERCOME TO SUCCEED\n\n" "GOOD LUCK, YOU WILL NEED IT!\n\n" "PRESS ANY KEY TO START\n"; // ====================================================================== // response messages // ====================================================================== char* straMsg[] = { "IT SHOWS A MAN CLIMBING DOWN A PIT USING A ROPE\n", "HOW? I CANT REACH\n", "IT HAS FALLEN TO THE FLOOR\n", "HOW?\n", "ITS TOO WIDE.I FELL AND BROKE MY NECK\n", "UGH! HE IS ALL SLIMY\n", "HE VANISHED IN A PUFF OF SMOKE\n", "YOU ALSO BROKE THE MIRROR\n", "COMPUTER SAYS: 2 WEST,2 SOUTH FOR SPACE FLIGHT\n", "IT HAS WEAKENED IT\n", "IT HAD NO EFFECT\n", "I FELL AND KNOCKED MYSELF OUT.\n", "THE BARS LOOK LOOSE\n", "WHAT WITH?\n", "I SEE A GOLD COIN\n", "BRRR.THE WATERS TOO COLD\n", "THE FUSE HAS JUST BLOWN\n", "THE LIFT HAS BEEN ACTIVATED\n", "I SEE NOTHING SPECIAL\n", "KEEP OFF THE MIDDLE MEN,ONE MAY BE SHOCKING!\n", "VANITY WALTZ!\n", "TRY HELP\n", "POINTS OF COMPASS\n", "TRY LOOKING AROUND\n", "I CAN SEE A STEEP SLOPE\n", "AN ALARM SOUNDS.THE SECURITY GUARD SHOT ME FOR TRESPASSING.\n", "I CAN SEE A ROPE HANGING DOWN THE CHIMNEY.\n", "I AM NOT THAT DAFT.IT IS TOO DEEP.\n", "THE SPACE SHIP BLEW UP AND KILLED ME.\n", "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", "THE LIFT HAS TAKEN ME UP TO A PLATEAU.\nCONGRATULATIONS, YOU HAVE MANAGED TO COMPLETE THIS ADVENTURE\nWITHOUT GETTING KILLED.\n", "THE LIFT HAS BECOME ELECTRIFIED\n", "I HAVE BEEN ELECTROCUTED\n", "IT IS A GOOD JOB I WAS WEARING RUBBER SOLED BOOTS.\n", "I WOULD KILL MYSELF IF I DID.\n", "I HAVE TURNED GREEN AND DROPPED DEAD.\n", "THE GREEN MAN AWOKE AND THROTTLED ME.\n", "THE GUARD WOKE AND SHOT ME.\n", "WHAT AT?\n" }; // ====================================================================== // room descriptions // ====================================================================== char* straRoom[] = { "I AM ON A MOUNTAIN PLATEAU\n" "TO THE NORTH THERE IS A STEEP CLIFF\n" "OBVIOUS EXITS ARE DOWN,EAST AND WEST\n", "I AM AT THE EDGE OF A DEEP PIT\n" "OBVIOUS EXITS ARE EAST\n", "I AM IN A DAMP LIMESTONE CAVE WITH STALACTITES HANGING DOWN.\n" "THE EXIT IS TO THE WEST\n" "THERE IS A PASSAGE TO THE NORTH\n", "I AM IN A DENSE FOREST\n" "THERE IS A ROPE HANGING FROM ONE TREE\n" "OBVIOUS EXITS ARE SOUTH AND WEST\n", "I AM BESIDE A LAKE\n" "EXITS ARE EAST AND NORTH.THERE IS A RAVINE TO THE WEST\n", "I AM IN A STRANGE HOUSE\n" "THE DOOR IS TO THE NORTH\n", "I AM IN AN OLD SHED\n" "THE EXIT IS TO THE EAST\n", "I AM IN A MAZE.THERE ARE PASSAGES EVERYWHERE\n", "I AM IN A MAZE.THERE ARE PASSAGES EVERYWHERE\n", "I AM IN A MAZE.THERE ARE PASSAGES EVERYWHERE\n", "I AM IN A MAZE.THERE ARE PASSAGES EVERYWHERE\n", "I AM IN AN ICE CAVERN\n" "THERE IS AN EXIT TO THE EAST\n", "I AM IN A QUIET CAVERN\n" "THERE ARE EXITS WEST,EAST AND SOUTH\n", "I AM IN A WIND TUNNEL\n" "THERE IS A CLOSED DOOR AT THE END\n" "THERE IS ALSO AN EXIT TO THE WEST\n", "I AM IN A ROOM WITH A COMPUTER IN\n" "THE COMPUTER IS WORKING AND HAS A KEYBOARD\n" "THE EXIT IS WEST\n", "I AM IN A PASSAGE\n" "THERE IS A FORCE FIELD TO THE SOUTH : BEWARE OF SECURITY\n" "THERE ARE EXITS TO NORTH,EAST AND WEST\n", "I AM IN A LARGE HANGER\n" "THERE IS A LOCKED DOOR TO THE WEST\n" "THERE ARE ALSO EXITS EAST,NORTH AND SOUTH\n", "I AM IN A TALL LIFT.THE BUTTONS ARE VERY HIGH\n" "THE EXIT IS WEST\n", "I AM IN THE LIFT CONTROL ROOM\n" "THERE ARE THREE SWITCHES ON THE WALL.THEY ARE ALL OFF\n" "A SIGN SAYS : 5,4 NO DUSTY BIN RULES\n" "THE EXIT IS EAST\n", "I AM IN A PRISON CELL\n", "I AM IN A SPACE SHIP.THERE IS NO VISIBLE EXIT\n" "THERE IS A SMALL OPEN WINDOW IN THE SIDE\n" "THERE ARE ALSO TWO BUTTONS,ONE MARKED MAIN AND THE OTHER AUX.\n" }; // ====================================================================== // item descriptions // ====================================================================== #define MAX_ITEM 28 char* straItem[MAX_ITEM] = { "A PAIR OF BOOTS", "A STARTER MOTOR", "A KEY", "A LASER GUN", "AN OUT OF ORDER SIGN", "A METAL BAR", "A GOLD COIN", "A MIRROR", "BROKEN GLASS", "A PAIR OF SLIMY GLOVES", "A ROPE", "A FLOOR BOARD", "A BROKEN FLOOR BOARD", "STALACTITES", "A BLOCK OF ICE", "A POOL OF WATER", "A SMALL GREEN MAN SLEEPING ON THE MIRROR", "A SLEEPING GREEN MAN", "A LOCKED DOOR", "AN OPEN DOOR", "A BARRED WINDOW", "A HOLE IN THE WALL", "A SMALL BUT POWERFULL SPACE SHIP", "A SLEEPING SECURITY MAN", "A PIECE OF SHARP FLINT", "SOME STONES", "A DRAWING ON THE WALL", "A LOUDSPEAKER WITH DANCE MUSIC COMING OUT" }; // ====================================================================== // initial positions of items - 1 int per item, holds room number // NOTX indicates item doesn't exist yet // ====================================================================== int naItemStart[MAX_ITEM] = { 0x05, 0x11, 0x0e, 0x06, 0x11, NOTX, NOTX, 0x0c, NOTX, 0x0d, NOTX, 0x05, NOTX, NOTX, 0x0b, NOTX, 0x0c, NOTX, 0x13, NOTX, 0x13, NOTX, 0x10, 0x10, 0x00, 0x01, 0x02, 0x0f }; // ====================================================================== // current positions of items - 1 int per item, holds room number // initialized from naItemStart at start, updated during the game // NOTX indicates item doesn't exist yet // ====================================================================== int naItemLoc[MAX_ITEM]; // the commands and their synonyms // each token is 4 characters, followed by a 1 byte token code // first define the token codes #define TOK_DOWN 0x01 #define TOK_NORT 0x02 #define TOK_SOUT 0x03 #define TOK_EAST 0x04 #define TOK_WEST 0x05 #define TOK_GET 0x0d #define TOK_DROP 0x0e #define TOK_FIRE 0x0f #define TOK_BOOT 0x10 #define TOK_STAR 0x11 #define TOK_KEY 0x12 #define TOK_GUN 0x13 #define TOK_USED 0x14 #define TOK_BAR 0x15 #define TOK_COIN 0x16 #define TOK_MIRR 0x17 #define TOK_BROK 0x18 #define TOK_GLOV 0x19 #define TOK_ROPE 0x1a #define TOK_BOAR 0x1b #define TOK_STAL 0x1c #define TOK_ICE 0x1d #define TOK_WATE 0x1e #define TOK_MAN 0x1f #define TOK_DOOR 0x20 #define TOK_OPEN 0x21 #define TOK_WIND 0x22 #define TOK_SHIP 0x23 #define TOK_SECU 0x24 #define TOK_FLIN 0x25 #define TOK_STON 0x26 #define TOK_DRAW 0x27 #define TOK_HELP 0x28 #define TOK_INVE 0x29 #define TOK_QUIT 0x2a #define TOK_YES 0x2b #define TOK_NO 0x2c #define TOK_COMP 0x2d #define TOK_TYPE 0x2e #define TOK_TURN 0x2f #define TOK_HAND 0x30 #define TOK_KILL 0x31 #define TOK_DANC 0x32 #define TOK_REMO 0x33 #define TOK_BREA 0x34 #define TOK_BRIB 0x35 #define TOK_USE 0x36 #define TOK_PUSH 0x37 #define TOK_THRE 0x38 #define TOK_TWO 0x39 #define TOK_ONE 0x3a #define TOK_MEND 0x3b #define TOK_FOUR 0x3c #define TOK_LOOK 0x3d #define TOK_STAN 0x3e #define TOK_TREE 0x3f #define TOK_CUT 0x40 #define TOK_WEAR 0x41 #define TOK_CROS 0x42 #define TOK_JUMP 0x43 #define TOK_RAVI 0x44 #define TOK_UP 0x45 #define TOK_FUSE 0x46 #define TOK_REDE 0x47 #define TOK_MAIN 0x48 #define TOK_AUX 0x49 #define TOK_FIEL 0x4a // now map the codes to their character representations typedef struct { char strWord[5]; int nCode; } TOKEN; #define MAX_TOK 110 TOKEN taToken[MAX_TOK] = { { "DOWN", TOK_DOWN }, { "D ", TOK_DOWN }, { "NORT", TOK_NORT }, { "N ", TOK_NORT }, { "SOUT", TOK_SOUT }, { "S ", TOK_SOUT }, { "EAST", TOK_EAST }, { "E ", TOK_EAST }, { "WEST", TOK_WEST }, { "W ", TOK_WEST }, { "GET ", TOK_GET }, { "PICK", TOK_GET }, { "DROP", TOK_DROP }, { "PUT ", TOK_DROP }, { "FIRE", TOK_FIRE }, { "SHOO", TOK_FIRE }, { "BOOT", TOK_BOOT }, { "STAR", TOK_STAR }, { "MOTO", TOK_STAR }, { "KEY ", TOK_KEY }, { "LASE", TOK_GUN }, { "GUN ", TOK_GUN }, { "USED", TOK_USED }, { "BAR ", TOK_BAR }, { "BARS", TOK_BAR }, { "GOLD", TOK_COIN }, { "COIN", TOK_COIN }, { "MIRR", TOK_MIRR }, { "BROK", TOK_BROK }, { "GLOV", TOK_GLOV }, { "ROPE", TOK_ROPE }, { "FLOO", TOK_BOAR }, { "BOAR", TOK_BOAR }, { "PLAN", TOK_BOAR }, { "STAL", TOK_STAL }, { "BLOC", TOK_ICE }, { "ICE ", TOK_ICE }, { "POOL", TOK_WATE }, { "WATE", TOK_WATE }, { "LAKE", TOK_WATE }, { "SLEE", TOK_MAN }, { "GREE", TOK_MAN }, { "MAN ", TOK_MAN }, { "DOOR", TOK_DOOR }, { "OPEN", TOK_OPEN }, { "UNLO", TOK_OPEN }, { "WIND", TOK_WIND }, { "SMAL", TOK_SHIP }, { "SPAC", TOK_SHIP }, { "SHIP", TOK_SHIP }, { "SECU", TOK_SECU }, { "FLIN", TOK_FLIN }, { "STON", TOK_STON }, { "DRAW", TOK_DRAW }, { "HELP", TOK_HELP }, { "INVE", TOK_INVE }, { "I ", TOK_INVE }, { "QUIT", TOK_QUIT }, { "STOP", TOK_QUIT }, { "ABOR", TOK_QUIT }, { "YES ", TOK_YES }, { "Y ", TOK_YES }, { "NO ", TOK_NO }, { "COMP", TOK_COMP }, { "KEYB", TOK_COMP }, { "TYPE", TOK_TYPE }, { "TURN", TOK_TURN }, { "HAND", TOK_HAND }, { "KILL", TOK_KILL }, { "DANC", TOK_DANC }, { "WALT", TOK_DANC }, { "REMO", TOK_REMO }, { "KICK", TOK_BREA }, { "BREA", TOK_BREA }, { "HIT ", TOK_BREA }, { "BANG", TOK_BREA }, { "BRIB", TOK_BRIB }, { "USE ", TOK_USE }, { "WITH", TOK_USE }, { "PUSH", TOK_PUSH }, { "THRE", TOK_THRE }, { "3 ", TOK_THRE }, { "TWO ", TOK_TWO }, { "2 ", TOK_TWO }, { "ONE ", TOK_ONE }, { "1 ", TOK_ONE }, { "MEND", TOK_MEND }, { "FIX ", TOK_MEND }, { "REPA", TOK_MEND }, { "FOUR", TOK_FOUR }, { "4 ", TOK_FOUR }, { "LOOK", TOK_LOOK }, { "STAN", TOK_STAN }, { "TREE", TOK_TREE }, { "CUT ", TOK_CUT }, { "SAW ", TOK_CUT }, { "WEAR", TOK_WEAR }, { "CROS", TOK_CROS }, { "JUMP", TOK_JUMP }, { "RAVI", TOK_RAVI }, { "UP ", TOK_UP }, { "U ", TOK_UP }, { "CLIM", TOK_UP }, { "FUSE", TOK_FUSE }, { "REDE", TOK_REDE }, { "R ", TOK_REDE }, { "MAIN", TOK_MAIN }, { "AUX ", TOK_AUX }, { "FIEL", TOK_FIEL }, { "SHIE", TOK_FIEL } }; // the directional information, one list for each room // each list entry is of the form , // each list is terminated with $ff BYTE DIR_00[] = { TOK_DOWN,0x03, TOK_EAST,0x02, TOK_WEST,0x01, 0xff }; BYTE DIR_01[] = { TOK_EAST,0x00, 0xff }; BYTE DIR_02[] = { TOK_NORT,0x07, TOK_WEST,0x00, 0xff }; BYTE DIR_03[] = { TOK_SOUT,0x04, TOK_WEST,0x00, 0xff }; BYTE DIR_04[] = { TOK_NORT,0x03, TOK_EAST,0x05, 0xff }; BYTE DIR_05[] = { TOK_NORT,0x04, 0xff }; BYTE DIR_06[] = { 0xff }; BYTE DIR_07[] = { TOK_DOWN,0x07, TOK_NORT,0x08, TOK_SOUT,0x07, TOK_EAST,0x07, TOK_WEST,0x07, 0xff }; BYTE DIR_08[] = { TOK_DOWN,0x07, TOK_NORT,0x07, TOK_SOUT,0x09, TOK_EAST,0x07, TOK_WEST,0x07, 0xff }; BYTE DIR_09[] = { TOK_DOWN,0x07, TOK_NORT,0x07, TOK_SOUT,0x07, TOK_EAST,0x0a, TOK_WEST,0x07, 0xff }; BYTE DIR_0A[] = { TOK_DOWN,0x07, TOK_NORT,0x02, TOK_SOUT,0x07, TOK_EAST,0x07, TOK_WEST,0x0b, 0xff }; BYTE DIR_0B[] = { TOK_EAST,0x07, 0xff }; BYTE DIR_0C[] = { TOK_SOUT,0x0f, TOK_EAST,0x0d, TOK_WEST,0x13, 0xff }; BYTE DIR_0D[] = { 0xff }; BYTE DIR_0E[] = { TOK_WEST,0x0d, 0xff }; BYTE DIR_0F[] = { TOK_EAST,0x13, TOK_WEST,0x13, 0xff }; BYTE DIR_10[] = { TOK_NORT,0x0f, TOK_SOUT,0x13, TOK_EAST,0x11, 0xff }; BYTE DIR_11[] = { TOK_WEST,0x10, 0xff }; BYTE DIR_12[] = { TOK_EAST,0x10, 0xff }; BYTE DIR_13[] = { 0xff }; // this vector array contains an address for every room BYTE* DIR_V[] = { DIR_00, DIR_01, DIR_02, DIR_03, DIR_04, DIR_05, DIR_06, DIR_07, DIR_08, DIR_09, DIR_0A, DIR_0B, DIR_0C, DIR_0D, DIR_0E, DIR_0F, DIR_10, DIR_11, DIR_12, DIR_13, DIR_13 // room 0x14 shares room 0x13's data - it's just an 0xff anyway }; // index codes of predicates #define COM_CHKROOM 0x00 #define COM_CHKHERE 0x01 #define COM_CHKRAND 0x02 #define COM_CHKAWAY 0x03 #define COM_CHKWORN 0x04 #define COM_CHKSETF 0x05 #define COM_TSTGVAR 0x06 #define COM_CHKCLRF 0x07 #define COM_CHKHELD 0x08 // a table of predicates BOOL CHKROOM(); BOOL CHKHERE(); BOOL CHKRAND(); BOOL CHKAWAY(); BOOL CHKWORN(); BOOL CHKSETF(); BOOL TSTGVAR(); BOOL CHKCLRF(); BOOL CHKHELD(); void* PRED_V[] = { (void*) CHKROOM, // $00 (void*) CHKHERE, // $01 (void*) CHKRAND, // $02 (void*) CHKAWAY, // $03 (void*) CHKWORN, // $04 (void*) CHKSETF, // $05 (void*) TSTGVAR, // $06 (void*) CHKCLRF, // $07 (void*) CHKHELD // $08 }; // list of predicate entries // first byte is the index of the predicate, see PRED_V // second byte is stored in PARAM1 // subsequent bytes of entry are terminated with a 0xff BYTE A_GD_BOOT[] = { COM_CHKHERE,0x00, 0xff }; BYTE A_GD_STAR[] = { COM_CHKHERE,0x01, 0xff }; BYTE A_GD_KEY[] = { COM_CHKHERE,0x02, 0xff }; BYTE A_GD_GUN[] = { COM_CHKHERE,0x03, 0xff }; BYTE A_GD_BAR[] = { COM_CHKHERE,0x05, 0xff }; BYTE A_GD_COIN[] = { COM_CHKHERE,0x06, 0xff }; BYTE A_G_MIRR_1[] = { COM_CHKHERE,0x07, COM_CHKAWAY,0x10, 0xff }; BYTE A_GD_MIRR_2[] = { COM_CHKHERE,0x08, 0xff }; BYTE A_GD_GLOV[] = { COM_CHKHERE,0x09, 0xff }; BYTE A_GD_ROPE[] = { COM_CHKHERE,0x0a, 0xff }; BYTE A_GD_BOAR_1[] = { COM_CHKHERE,0x0b, 0xff }; BYTE A_GD_BOAR_2[] = { COM_CHKHERE,0x0c, 0xff }; BYTE A_GD_STAL[] = { COM_CHKHERE,0x0d, 0xff }; BYTE A_GD_ICE[] = { COM_CHKHERE,0x0e, 0xff }; BYTE A_GD_FLIN[] = { COM_CHKHERE,0x18, 0xff }; BYTE A_GD_STON[] = { COM_CHKHERE,0x19, 0xff }; BYTE A_D_MIRR[] = { COM_CHKHERE,0x07, 0xff }; BYTE A_DRAW_STAL[] = { COM_CHKROOM,0x02, 0xff }; BYTE A_U_ICE_1[] = { COM_CHKROOM,0x02, COM_CHKHERE,0x0e, 0xff }; BYTE A_CUT_ROPE[] = { COM_CHKROOM,0x03, 0xff }; BYTE A_USE_FLIN[] = { COM_CHKROOM,0x03, COM_CHKHERE,0x18, 0xff }; BYTE A_C_RAVI_1[] = { COM_CHKROOM,0x04, 0xff }; BYTE A_C_RAVI_2[] = { COM_CHKROOM,0x06, 0xff }; BYTE A_C_RAVI_3[] = { COM_CHKROOM,0x04, COM_CHKHERE,0x0b, 0xff }; BYTE A_USE_BOAR[] = { COM_CHKROOM,0x06, COM_CHKHERE,0x0b, 0xff }; BYTE A_DOWN[] = { COM_CHKROOM,0x0b, 0xff }; BYTE A_U_ICE_2[] = { COM_CHKROOM,0x0b, COM_CHKHELD,0x0e, 0xff }; BYTE A_G_MAN_1[] = { COM_CHKHERE,0x10, COM_CHKHERE,0x09, COM_CHKWORN,0x09, 0xff }; BYTE A_G_MAN_2[] = { COM_CHKHERE,0x10, COM_CHKHERE,0x09, 0xff }; BYTE A_G_MAN_3[] = { COM_CHKHERE,0x10, 0xff }; BYTE A_KD_MAN_1[] = { COM_CHKHERE,0x11, 0xff }; BYTE A_G_MIRR_3[] = { COM_CHKHERE,0x07, COM_CHKAWAY,0x10, 0xff }; BYTE A_K_MAN_2[] = { COM_CHKHERE,0x10, 0xff }; BYTE A_U_GUN_1[] = { COM_CHKHERE,0x10, COM_CHKHERE,0x03, 0xff }; BYTE A_U_GUN_2[] = { COM_CHKHERE,0x11, COM_CHKHERE,0x03, COM_CHKHELD,0x11, 0xff }; BYTE A_U_GUN_3[] = { COM_CHKHERE,0x11, COM_CHKHERE,0x03, 0xff }; BYTE A_TYPE_HELP[] = { COM_CHKROOM,0x0e, 0xff }; BYTE A_FIRE_GUN[] = { COM_CHKROOM,0x0f, 0xff }; BYTE A_FIEL_1[] = { COM_CHKROOM,0x0f, COM_CHKCLRF,GVAR_07, COM_CHKHERE,0x03, 0xff }; BYTE A_FIEL_2[] = { COM_CHKSETF,GVAR_07, COM_CHKCLRF,GVAR_08, COM_CHKROOM,0x0f, COM_CHKHERE,0x03, 0xff }; BYTE A_FIEL_3[] = { COM_CHKSETF,GVAR_08, COM_CHKROOM,0x0f, COM_CHKHERE,0x03, 0xff }; BYTE A_DANC_1[] = { COM_CHKROOM,0x0f, COM_CHKHELD,0x07, COM_CHKSETF,GVAR_08, 0xff }; BYTE A_DANC_2[] = { COM_CHKROOM,0x0f, 0xff }; BYTE A_O_DOOR_1[] = { COM_CHKROOM,0x10, 0xff }; BYTE A_USE_KEY[] = { COM_CHKROOM,0x10, COM_CHKHERE,0x02, 0xff }; BYTE A_K_SECU[] = { COM_CHKROOM,0x10, COM_CHKHERE,0x03, 0xff }; BYTE A_LUP_BREA[] = { COM_CHKROOM,0x13, 0xff }; BYTE A_UP[] = { COM_CHKROOM,0x13, COM_CHKHERE,0x15, 0xff }; BYTE A_BRSEC[] = { COM_CHKROOM,0x13, 0xff }; BYTE A_U_COIN[] = { COM_CHKROOM,0x13, COM_CHKHERE,0x06, 0xff }; BYTE A_B_DOOR[] = { COM_CHKROOM,0x13, COM_CHKHERE,0x13, 0xff }; BYTE A_G_COIN[] = { COM_CHKROOM,0x04, COM_CHKAWAY,0x06, 0xff }; #define A_L_WATE A_G_COIN BYTE A_WATE_1[] = { COM_CHKROOM,0x04, COM_CHKAWAY,0x06, COM_CHKWORN,0x00, COM_CHKHERE,0x00, 0xff }; BYTE A_WATE_2[] = { COM_CHKROOM,0x04, COM_CHKAWAY,0x06, COM_CHKHERE,0x00, 0xff }; BYTE A_O_DOOR_2[] = { COM_CHKROOM,0x0d, 0xff }; BYTE A_PUSH_THRE[] = { COM_CHKROOM,0x12, COM_CHKCLRF,GVAR_09, COM_CHKCLRF,GVAR_0a, 0xff }; BYTE A_PUSH_DIG[] = { COM_CHKROOM,0x12, COM_CHKCLRF,GVAR_0a, 0xff }; BYTE A_PUSH_TWO[] = { COM_CHKROOM,0x12, COM_TSTGVAR,GVAR_09,0x01, COM_CHKCLRF,GVAR_0a, 0xff }; BYTE A_PUSH_ONE[] = { COM_CHKROOM,0x12, COM_TSTGVAR,GVAR_09,0x02, COM_CHKCLRF,GVAR_0a, 0xff }; BYTE A_MEND_FUSE[] = { COM_CHKROOM,0x12, COM_CHKSETF,GVAR_0a, 0xff }; BYTE A_USE_BAR[] = { COM_CHKROOM,0x12, COM_CHKHERE,0x05, COM_CHKSETF,GVAR_0a, 0xff }; BYTE A_LOOK[] = { COM_CHKROOM,0x0b, 0xff }; BYTE A_HELP_1[] = { COM_CHKROOM,0x11, 0xff }; BYTE A_HELP_2[] = { COM_CHKROOM,0x0f, 0xff }; BYTE A_HELP_3[] = { COM_CHKROOM,0x0e, 0xff }; BYTE A_HELP_4[] = { COM_CHKROOM,0x07, 0xff }; BYTE A_HELP_5[] = { COM_CHKROOM,0x08, 0xff }; BYTE A_HELP_6[] = { COM_CHKROOM,0x09, 0xff }; BYTE A_HELP_7[] = { COM_CHKROOM,0x0a, 0xff }; BYTE A_HELP_8[] = { COM_CHKROOM,0x14, COM_CHKSETF,GVAR_0c, 0xff }; BYTE A_LUP[] = { COM_CHKSETF,GVAR_0b, COM_CHKROOM,0x0c, 0xff }; BYTE A_WEST[] = { COM_CHKROOM,0x0d, 0xff }; BYTE A_JUMP[] = { COM_CHKROOM,0x01, 0xff }; BYTE A_USEROP[] = { COM_CHKROOM,0x01, COM_CHKHELD,0x0a, 0xff }; BYTE A_UPROPE[] = { COM_CHKROOM,0x0c, COM_CHKSETF,GVAR_0b, 0xff }; BYTE A_SHIP[] = { COM_CHKHERE,0x16, 0xff }; BYTE A_P_MAUX[] = { COM_CHKROOM,0x14, COM_CHKHERE,0x01, 0xff }; BYTE A_P_32[] = { COM_CHKROOM,0x14, COM_CHKSETF,GVAR_0c, 0xff }; BYTE A_P_41[] = { COM_CHKROOM,0x14, COM_CHKSETF,GVAR_0c, COM_TSTGVAR,GVAR_09,0x03, 0xff }; BYTE A_PSH_ONE_2[] = { COM_CHKROOM,0x14, COM_CHKSETF,GVAR_0c, COM_CHKWORN,0x00, COM_TSTGVAR,GVAR_09,0x03, 0xff }; // list of predicate entries for Auto Commands // first byte is the index of the predicate, see PRED_V // second byte is stored in PARAM1 // subsequent bytes of entry are terminated with a $ff // check if we have turned green and died BYTE A_CHGRN[] = { COM_TSTGVAR,GVAR_05,0x01, // if game variable 0x05 = 1 COM_CHKSETF,GVAR_06, // and game variable 0x06 is set 0xff }; // check if the small green man is to throttle us (version 1) BYTE A_CHTHR[] = { COM_TSTGVAR,GVAR_02,0x01, // if game variable 0x02 = 1 COM_CHKHERE,0x10, // and is-present the small green man sleeping on the mirror 0xff }; // check if the small green man is to throttle us (version 2) BYTE A_C2THR[] = { COM_TSTGVAR,GVAR_02,0x01, // if game variable 0x02 = 1 COM_CHKHERE,0x11, // and is-present the sleeping green man (moved off mirror) 0xff }; // check if we're to be shot by the security guard BYTE A_SHOT[] = { COM_TSTGVAR,GVAR_02,0x01, // if game variable 0x02 = 1 COM_CHKHERE,0x17, // and is-present the sleeping security man 0xff }; // check if ice has melted BYTE A_MELTD[] = { COM_TSTGVAR,GVAR_02,0x01, // if game variable 0x02 = 1 COM_CHKHERE,0x0e, // and is-present the block of ice 0xff }; // an empty action entry BYTE A_NULL[] = { 0Xff }; BYTE A_MISC[] = { 0xff }; // used for auto commands - no predicates required #define I_SH_INVE 0x00 // terminates bytecode processing #define I_SH_REMO 0x01 #define I_SH_GET 0x02 #define I_SH_DROP 0x03 #define I_SH_WEAR 0x04 #define I_SH_MSG 0x05 #define I_SH_REDE 0x06 // terminates bytecode processing #define I_SH_AUTO 0x07 // terminates bytecode processing #define I_SH_GOTO 0x08 #define I_SH_SETF 0x09 #define I_SH_CLRF 0x0a #define I_SH_SWAP 0x0b #define I_SH_DEAD 0x0c // terminates bytecode processing #define I_SH_OK 0x0d // terminates bytecode processing #define I_SH_QUIT 0x0e // terminates bytecode processing #define I_SH_SETV 0x0f #define I_SH_CREA 0x10 #define I_SH_DEST 0x11 #define I_SH_ADSC 0x12 #define I_SH_SCOR 0x13 #define I_SH_FAIL1 0x14 #define I_SH_TELL 0x15 #define I_SH_FAIL2 0x16 #define I_SH_FAIL3 0x17 #define I_SH_FAIL4 0x18 // bytecodes for the various commands a user can enter BYTE SGET_00[] = { I_SH_GET,0x00,I_SH_OK }; BYTE SGET_01[] = { I_SH_GET,0x01,I_SH_OK }; BYTE SGET_02[] = { I_SH_GET,0x02,I_SH_OK }; BYTE SGET_03[] = { I_SH_GET,0x03,I_SH_OK }; BYTE SGET_05[] = { I_SH_GET,0x05,I_SH_OK }; BYTE SGET_06[] = { I_SH_GET,0x06,I_SH_OK }; BYTE SGET_07[] = { I_SH_GET,0x07,I_SH_OK }; BYTE SGET_08[] = { I_SH_GET,0x08,I_SH_OK }; BYTE SGET_09[] = { I_SH_GET,0x09,I_SH_OK }; BYTE SGET_0A[] = { I_SH_GET,0x0a,I_SH_OK }; BYTE SGET_0B[] = { I_SH_GET,0x0b,I_SH_OK }; BYTE SGET_0C[] = { I_SH_GET,0x0c,I_SH_OK }; BYTE SGET_0D[] = { I_SH_GET,0x0d,I_SH_OK }; BYTE SGET_0E[] = { I_SH_GET,0x0e,I_SH_SETV,GVAR_02,0x09,I_SH_OK }; BYTE SGET_18[] = { I_SH_GET,0x18,I_SH_OK }; BYTE SGET_19[] = { I_SH_GET,0x19,I_SH_OK }; BYTE SINVENT[] = { I_SH_INVE,0x07 }; // the 0x07 is ignored BYTE SQUIT[] = { I_SH_QUIT }; BYTE SPUT_00[] = { I_SH_DROP,0x00,I_SH_OK }; BYTE SPUT_01[] = { I_SH_DROP,0x01,I_SH_OK }; BYTE SPUT_02[] = { I_SH_DROP,0x02,I_SH_OK }; BYTE SPUT_03[] = { I_SH_DROP,0x03,I_SH_OK }; BYTE SPUT_05[] = { I_SH_DROP,0x05,I_SH_OK }; BYTE SPUT_06[] = { I_SH_DROP,0x06,I_SH_OK }; BYTE SPUT_07[] = { I_SH_DROP,0x07,I_SH_OK }; BYTE SPUT_08[] = { I_SH_DROP,0x08,I_SH_OK }; BYTE SPUT_09[] = { I_SH_DROP,0x09,I_SH_OK }; BYTE SPUT_0A[] = { I_SH_DROP,0x0a,I_SH_OK }; BYTE SPUT_0B[] = { I_SH_DROP,0x0b,I_SH_OK }; BYTE SPUT_0C[] = { I_SH_DROP,0x0c,I_SH_OK }; BYTE SPUT_0D[] = { I_SH_DROP,0x0d,I_SH_OK }; BYTE SPUT_0E[] = { I_SH_DROP,0x0e,I_SH_OK }; BYTE SPUT_18[] = { I_SH_DROP,0x18,I_SH_OK }; BYTE SPUT_19[] = { I_SH_DROP,0x19,I_SH_OK }; BYTE SLK_DRW[] = { I_SH_MSG,0x00,I_SH_AUTO }; BYTE SBRK_ST[] = { I_SH_MSG,0x01,I_SH_AUTO }; BYTE SUSE_IC[] = { I_SH_CREA,0x0d,I_SH_MSG,0x02,I_SH_AUTO }; BYTE SCUT_RP[] = { I_SH_MSG,0x03,I_SH_AUTO }; BYTE SUSE_FL[] = { I_SH_CREA,0x0a,I_SH_MSG,0x02,I_SH_AUTO }; BYTE SWR_00[] = { I_SH_WEAR,0x00,I_SH_OK }; BYTE SRM_00[] = { I_SH_REMO,0x00,I_SH_OK }; BYTE SCR_RV[] = { I_SH_MSG,0x03,I_SH_AUTO }; BYTE SUSE_BO[] = { I_SH_GOTO,0x06,I_SH_REDE }; BYTE SUS2_BO[] = { I_SH_GOTO,0x04,I_SH_DEST,0x0b,I_SH_CREA,0x0c,I_SH_REDE }; BYTE SJMP_RV[] = { I_SH_MSG,0x04,I_SH_DEAD }; BYTE SUSE_I2[] = { I_SH_GOTO,0x0c,I_SH_DROP,0x0e,I_SH_SWAP,0x0e,I_SH_SETV,GVAR_02,0x07,I_SH_REDE }; 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 }; BYTE SGET_M2[] = { I_SH_GET,0x10,I_SH_SWAP,0x10,I_SH_OK }; BYTE SPUT_11[] = { I_SH_DROP,0x11,I_SH_OK }; BYTE SGE2_07[] = { I_SH_GET,0x07,I_SH_OK }; BYTE SGE2_08[] = { I_SH_GET,0x08,I_SH_OK }; BYTE SPU2_07[] = { I_SH_DROP,0x07,I_SH_OK }; BYTE SPU2_08[] = { I_SH_DROP,0x08,I_SH_OK }; BYTE SDO_HOW[] = { I_SH_MSG,0x03,I_SH_AUTO }; BYTE SUSE_GN[] = { I_SH_DEST,0x10,I_SH_SWAP,0x07,I_SH_MSG,0x06,I_SH_MSG,0x07,I_SH_AUTO }; BYTE SFIR_GN[] = { I_SH_MSG,0x26,I_SH_AUTO }; BYTE SUS2_GN[] = { I_SH_DEST,0x11,I_SH_MSG,0x06,I_SH_AUTO }; BYTE SHLP_CM[] = { I_SH_MSG,0x08,I_SH_AUTO }; BYTE SFLD_1[] = { I_SH_SETF,GVAR_07,I_SH_MSG,0x09,I_SH_AUTO }; BYTE SFLD_2[] = { I_SH_SETF,GVAR_08,I_SH_MSG,0x09,I_SH_AUTO }; BYTE SFLD_3[] = { I_SH_MSG,0x0a,I_SH_AUTO }; BYTE SDANCE[] = { I_SH_GOTO,0x10,I_SH_SETV,GVAR_02,0x09,I_SH_REDE }; BYTE SDANCE2[] = { I_SH_MSG,0x0b,I_SH_GOTO,0x13,I_SH_REDE }; BYTE SUSE_KY[] = { I_SH_GOTO,0x12,I_SH_REDE }; BYTE SKIL_SG[] = { I_SH_DEST,0x17,I_SH_OK }; BYTE SLK_UP[] = { I_SH_MSG,0x0c,I_SH_AUTO }; BYTE SBRK_BA[] = { I_SH_SWAP,0x14,I_SH_CREA,0x05,I_SH_REDE }; BYTE SGO_UP[] = { I_SH_GOTO,0x0c,I_SH_SWAP,0x14,I_SH_REDE }; BYTE SBRBSEC[] = { I_SH_MSG,0x0d,I_SH_AUTO }; BYTE SUSE_CN[] = { I_SH_SWAP,0x12,I_SH_DEST,0x06,I_SH_REDE }; BYTE SBDOOR[] = { I_SH_GOTO,0x0c,I_SH_SWAP,0x12,I_SH_REDE }; BYTE SLK_WAT[] = { I_SH_MSG,0x0e,I_SH_AUTO }; BYTE SGET_CN[] = { I_SH_MSG,0x01,I_SH_AUTO }; BYTE SWATER2[] = { I_SH_MSG,0x0f,I_SH_AUTO }; BYTE SWATER1[] = { I_SH_CREA,0x06,I_SH_GET,0x06,I_SH_OK }; BYTE SL2_WAT[] = { I_SH_MSG,0x0f,I_SH_AUTO }; BYTE SODOOR2[] = { I_SH_GOTO,0x0e,I_SH_REDE }; BYTE SPSH3A[] = { I_SH_SETV,GVAR_09,0x01,I_SH_OK }; BYTE SPSHDG[] = { I_SH_MSG,0x10,I_SH_CLRF,GVAR_09,I_SH_SETF,GVAR_0a,I_SH_AUTO }; BYTE SPSH2A[] = { I_SH_SETV,GVAR_09,0x02,I_SH_OK }; BYTE SPSH1A[] = { I_SH_MSG,0x11,I_SH_SETV,GVAR_09,0x03,I_SH_AUTO }; BYTE SMNDFUS[] = { I_SH_MSG,0x0d,I_SH_AUTO }; BYTE SUSE_BA[] = { I_SH_CLRF,GVAR_0a,I_SH_DEST,0x05,I_SH_OK }; BYTE SLOOK1[] = { I_SH_MSG,0x18,I_SH_AUTO }; BYTE SHELP1[] = { I_SH_MSG,0x13,I_SH_AUTO }; BYTE SHELP2[] = { I_SH_MSG,0x14,I_SH_AUTO }; BYTE SHELP3[] = { I_SH_MSG,0x15,I_SH_AUTO }; BYTE SHELP4[] = { I_SH_MSG,0x16,I_SH_AUTO }; BYTE SLK_UP2[] = { I_SH_MSG,0x1a,I_SH_AUTO }; BYTE SQUIET[] = { I_SH_GOTO,0x0c,I_SH_SETV,GVAR_02,0x07,I_SH_REDE }; BYTE SWR_09[] = { I_SH_WEAR,0x09,I_SH_OK }; BYTE SRM_09[] = { I_SH_REMO,0x09,I_SH_OK }; BYTE SREDE[] = { I_SH_REDE }; BYTE SJUMP_D[] = { I_SH_MSG,0x03,I_SH_AUTO }; BYTE SUSE_RP[] = { I_SH_SETF,GVAR_0b,I_SH_DROP,0x0a,I_SH_GOTO,0x0c,I_SH_REDE }; BYTE SJUMP[] = { I_SH_MSG,0x1b,I_SH_AUTO }; BYTE SUP_ROP[] = { I_SH_GOTO,0x01,I_SH_REDE }; BYTE SSHIP[] = { I_SH_GOTO,0x14,I_SH_REDE }; BYTE SPSH_MN[] = { I_SH_MSG,0x1c,I_SH_DEAD }; BYTE SPSH_AU[] = { I_SH_SETF,GVAR_0c,I_SH_MSG,0x1d,I_SH_AUTO }; BYTE SPSH_32[] = { I_SH_MSG,0x19,I_SH_DEAD }; BYTE SPSH_4[] = { I_SH_MSG,0x1e,I_SH_QUIT }; BYTE SPSH_1B[] = { I_SH_MSG,0x1f,I_SH_MSG,0x20,I_SH_DEAD }; BYTE SPSH_1C[] = { I_SH_MSG,0x1f,I_SH_MSG,0x21,I_SH_MSG,0x1e,I_SH_QUIT }; BYTE SHELP5[] = { I_SH_MSG,0x17,I_SH_AUTO }; BYTE SLOOK2[] = { I_SH_MSG,0x12,I_SH_AUTO }; // list of available verb/noun combinations // along with their defining predicates and // command lists // terminated with a zero byte // for each entry: // 1st = verb token code // 2nd = noun token code // 3rd = address of predicate list entry // 4th = address of system command list entry VNDef vndDefinitions[] = { { TOK_GET, TOK_BOOT, (void*) A_GD_BOOT, (void*) SGET_00 }, { TOK_GET, TOK_STAR, (void*) A_GD_STAR, (void*) SGET_01 }, { TOK_GET, TOK_KEY, (void*) A_GD_KEY, (void*) SGET_02 }, { TOK_GET, TOK_GUN, (void*) A_GD_GUN, (void*) SGET_03 }, { TOK_GET, TOK_BAR, (void*) A_GD_BAR, (void*) SGET_05 }, { TOK_GET, TOK_COIN, (void*) A_GD_COIN, (void*) SGET_06 }, { TOK_GET, TOK_MIRR, (void*) A_G_MIRR_1, (void*) SGET_07 }, { TOK_GET, TOK_MIRR, (void*) A_GD_MIRR_2, (void*) SGET_08 }, { TOK_GET, TOK_BROK, (void*) A_GD_MIRR_2, (void*) SGET_08 }, { TOK_GET, TOK_GLOV, (void*) A_GD_GLOV, (void*) SGET_09 }, { TOK_GET, TOK_ROPE, (void*) A_GD_ROPE, (void*) SGET_0A }, { TOK_GET, TOK_BOAR, (void*) A_GD_BOAR_1, (void*) SGET_0B }, { TOK_GET, TOK_BOAR, (void*) A_GD_BOAR_2, (void*) SGET_0C }, { TOK_GET, TOK_BROK, (void*) A_GD_BOAR_2, (void*) SGET_0C }, { TOK_GET, TOK_STAL, (void*) A_GD_STAL, (void*) SGET_0D }, { TOK_GET, TOK_ICE, (void*) A_GD_ICE, (void*) SGET_0E }, { TOK_GET, TOK_FLIN, (void*) A_GD_FLIN, (void*) SGET_18 }, { TOK_GET, TOK_STON, (void*) A_GD_STON, (void*) SGET_19 }, { TOK_INVE, 0xff, (void*) A_MISC, (void*) SINVENT }, { TOK_QUIT, 0xff, (void*) A_MISC, (void*) SQUIT }, { TOK_DROP, TOK_BOOT, (void*) A_GD_BOOT, (void*) SPUT_00 }, { TOK_DROP, TOK_STAR, (void*) A_GD_STAR, (void*) SPUT_01 }, { TOK_DROP, TOK_KEY, (void*) A_GD_KEY, (void*) SPUT_02 }, { TOK_DROP, TOK_GUN, (void*) A_GD_GUN, (void*) SPUT_03 }, { TOK_DROP, TOK_BAR, (void*) A_GD_BAR, (void*) SPUT_05 }, { TOK_DROP, TOK_COIN, (void*) A_GD_COIN, (void*) SPUT_06 }, { TOK_DROP, TOK_MIRR, (void*) A_D_MIRR, (void*) SPUT_07 }, { TOK_DROP, TOK_MIRR, (void*) A_GD_MIRR_2, (void*) SPUT_08 }, { TOK_DROP, TOK_BROK, (void*) A_GD_MIRR_2, (void*) SPUT_08 }, { TOK_DROP, TOK_GLOV, (void*) A_GD_GLOV, (void*) SPUT_09 }, { TOK_DROP, TOK_ROPE, (void*) A_GD_ROPE, (void*) SPUT_0A }, { TOK_DROP, TOK_BOAR, (void*) A_GD_BOAR_1, (void*) SPUT_0B }, { TOK_DROP, TOK_BOAR, (void*) A_GD_BOAR_2, (void*) SPUT_0C }, { TOK_FIRE, TOK_BROK, (void*) A_GD_BOAR_2, (void*) SPUT_0C }, { TOK_DROP, TOK_STAL, (void*) A_GD_STAL, (void*) SPUT_0D }, { TOK_DROP, TOK_ICE, (void*) A_GD_ICE, (void*) SPUT_0E }, { TOK_DROP, TOK_FLIN, (void*) A_GD_FLIN, (void*) SPUT_18 }, { TOK_DROP, TOK_STON, (void*) A_GD_STON, (void*) SPUT_19 }, { TOK_LOOK, TOK_DRAW, (void*) A_DRAW_STAL, (void*) SLK_DRW }, { TOK_BREA, TOK_STAL, (void*) A_DRAW_STAL, (void*) SBRK_ST }, { TOK_USE, TOK_ICE, (void*) A_U_ICE_1, (void*) SUSE_IC }, { TOK_CUT, TOK_ROPE, (void*) A_CUT_ROPE, (void*) SCUT_RP }, { TOK_USE, TOK_FLIN, (void*) A_USE_FLIN, (void*) SUSE_FL }, { TOK_WEAR, TOK_BOOT, (void*) A_MISC, (void*) SWR_00 }, { TOK_REMO, TOK_BOOT, (void*) A_MISC, (void*) SRM_00 }, { TOK_CROS, TOK_RAVI, (void*) A_C_RAVI_1, (void*) SCR_RV }, { TOK_CROS, TOK_RAVI, (void*) A_C_RAVI_2, (void*) SCR_RV }, { TOK_USE, TOK_BOAR, (void*) A_C_RAVI_3, (void*) SUSE_BO }, { TOK_USE, TOK_BOAR, (void*) A_USE_BOAR, (void*) SUS2_BO }, { TOK_JUMP, TOK_RAVI, (void*) A_C_RAVI_3, (void*) SJMP_RV }, { TOK_JUMP, TOK_RAVI, (void*) A_C_RAVI_2, (void*) SJMP_RV }, { TOK_DOWN, 0xff, (void*) A_DOWN, (void*) SCR_RV }, { TOK_USE, TOK_ICE, (void*) A_U_ICE_2, (void*) SUSE_I2 }, { TOK_GET, TOK_MAN, (void*) A_G_MAN_1, (void*) SGET_MN }, { TOK_GET, TOK_MAN, (void*) A_G_MAN_2, (void*) SGET_M2 }, { TOK_GET, TOK_MAN, (void*) A_G_MAN_3, (void*) SGET_MN }, { TOK_DROP, TOK_MAN, (void*) A_KD_MAN_1, (void*) SPUT_11 }, { TOK_GET, TOK_MIRR, (void*) A_G_MIRR_3, (void*) SGE2_07 }, { TOK_GET, TOK_BROK, (void*) A_GD_MIRR_2, (void*) SGE2_08 }, { TOK_DROP, TOK_MIRR, (void*) A_D_MIRR, (void*) SPU2_07 }, { TOK_DROP, TOK_BROK, (void*) A_GD_MIRR_2, (void*) SPU2_08 }, { TOK_KILL, TOK_MAN, (void*) A_K_MAN_2, (void*) SDO_HOW }, { TOK_KILL, TOK_MAN, (void*) A_KD_MAN_1, (void*) SDO_HOW }, { TOK_USE, TOK_GUN, (void*) A_U_GUN_1, (void*) SUSE_GN }, { TOK_USE, TOK_GUN, (void*) A_U_GUN_2, (void*) SFIR_GN }, { TOK_USE, TOK_GUN, (void*) A_U_GUN_3, (void*) SUS2_GN }, { TOK_TYPE, TOK_HELP, (void*) A_TYPE_HELP, (void*) SHLP_CM }, { TOK_FIRE, TOK_GUN, (void*) A_FIRE_GUN, (void*) SFIR_GN }, { TOK_FIEL, 0xff, (void*) A_FIEL_1, (void*) SFLD_1 }, { TOK_FIEL, 0xff, (void*) A_FIEL_2, (void*) SFLD_2 }, { TOK_FIEL, 0xff, (void*) A_FIEL_3, (void*) SFLD_3 }, { TOK_DANC, 0xff, (void*) A_DANC_1, (void*) SDANCE }, { TOK_DANC, 0xff, (void*) A_DANC_2, (void*) SDANCE2 }, { TOK_OPEN, TOK_DOOR, (void*) A_O_DOOR_1, (void*) SDO_HOW }, { TOK_USE, TOK_KEY, (void*) A_USE_KEY, (void*) SUSE_KY }, { TOK_KILL, TOK_SECU, (void*) A_K_SECU, (void*) SKIL_SG }, { TOK_LOOK, TOK_UP, (void*) A_LUP_BREA, (void*) SLK_UP }, { TOK_BREA, TOK_BAR, (void*) A_LUP_BREA, (void*) SBRK_BA }, { TOK_UP, 0xff, (void*) A_UP, (void*) SGO_UP }, { TOK_BRIB, TOK_SECU, (void*) A_BRSEC, (void*) SBRBSEC }, { TOK_USE, TOK_COIN, (void*) A_U_COIN, (void*) SUSE_CN }, { TOK_DOOR, 0xff, (void*) A_B_DOOR, (void*) SBDOOR }, { TOK_LOOK, TOK_WATE, (void*) A_L_WATE, (void*) SLK_WAT }, { TOK_GET, TOK_COIN, (void*) A_G_COIN, (void*) SGET_CN }, { TOK_WATE, 0xff, (void*) A_WATE_1, (void*) SWATER1 }, { TOK_WATE, 0xff, (void*) A_WATE_2, (void*) SWATER2 }, { TOK_WATE, 0xff, (void*) A_L_WATE, (void*) SL2_WAT }, { TOK_OPEN, TOK_DOOR, (void*) A_O_DOOR_2, (void*) SODOOR2 }, { TOK_PUSH, TOK_THRE, (void*) A_PUSH_THRE, (void*) SPSH3A }, { TOK_PUSH, TOK_THRE, (void*) A_PUSH_DIG, (void*) SPSHDG }, { TOK_PUSH, TOK_TWO, (void*) A_PUSH_TWO, (void*) SPSH2A }, { TOK_PUSH, TOK_TWO, (void*) A_PUSH_DIG, (void*) SPSHDG }, { TOK_PUSH, TOK_ONE, (void*) A_PUSH_ONE, (void*) SPSH1A }, { TOK_PUSH, TOK_ONE, (void*) A_PUSH_DIG, (void*) SPSHDG }, { TOK_MEND, TOK_FUSE, (void*) A_MEND_FUSE, (void*) SMNDFUS }, { TOK_USE, TOK_BAR, (void*) A_USE_BAR, (void*) SUSE_BA }, { TOK_LOOK, 0xff, (void*) A_LOOK, (void*) SLOOK1 }, { TOK_HELP, 0xff, (void*) A_HELP_1, (void*) SHELP1 }, { TOK_HELP, 0xff, (void*) A_HELP_2, (void*) SHELP2 }, { TOK_HELP, 0xff, (void*) A_HELP_3, (void*) SHELP3 }, { TOK_HELP, 0xff, (void*) A_HELP_4, (void*) SHELP4 }, { TOK_HELP, 0xff, (void*) A_HELP_5, (void*) SHELP4 }, { TOK_HELP, 0xff, (void*) A_HELP_6, (void*) SHELP4 }, { TOK_HELP, 0xff, (void*) A_HELP_7, (void*) SHELP4 }, { TOK_HELP, 0xff, (void*) A_HELP_8, (void*) SHELP1 }, { TOK_LOOK, TOK_UP, (void*) A_LUP, (void*) SLK_UP2 }, { TOK_WEST, 0xff, (void*) A_WEST, (void*) SQUIET }, { TOK_NORT, 0xff, (void*) A_HELP_2, (void*) SQUIET }, { TOK_WEAR, TOK_GLOV, (void*) A_MISC, (void*) SWR_09 }, { TOK_REMO, TOK_GLOV, (void*) A_MISC, (void*) SRM_09 }, { TOK_REDE, 0xff, (void*) A_MISC, (void*) SREDE }, { TOK_DOWN, 0xff, (void*) A_JUMP, (void*) SJUMP_D }, { TOK_USE, TOK_ROPE, (void*) A_USEROP, (void*) SUSE_RP }, { TOK_JUMP, 0xff, (void*) A_JUMP, (void*) SJUMP }, { TOK_UP, TOK_ROPE, (void*) A_UPROPE, (void*) SUP_ROP }, { TOK_SHIP, 0xff, (void*) A_SHIP, (void*) SSHIP }, { TOK_PUSH, TOK_MAIN, (void*) A_P_MAUX, (void*) SPSH_MN }, { TOK_PUSH, TOK_AUX, (void*) A_P_MAUX, (void*) SPSH_AU }, { TOK_PUSH, TOK_THRE, (void*) A_P_32, (void*) SPSH_32 }, { TOK_PUSH, TOK_TWO, (void*) A_P_32, (void*) SPSH_32 }, { TOK_PUSH, TOK_FOUR, (void*) A_P_41, (void*) SPSH_4 }, { TOK_PUSH, TOK_ONE, (void*) A_PSH_ONE_2, (void*) SPSH_1C }, { TOK_PUSH, TOK_ONE, (void*) A_P_41, (void*) SPSH_1B }, { TOK_HELP, 0xff, (void*) A_MISC, (void*) SHELP5 }, { TOK_LOOK, 0xff, (void*) A_MISC, (void*) SLOOK2 }, { 0x00, 0x00, (void*) 0, (void*) 0 } }; // bytecodes for the auto commands BYTE STURNGR[] = { I_SH_MSG,0x23,I_SH_DEAD }; BYTE STHROTL[] = { I_SH_MSG,0x24,I_SH_DEAD }; BYTE SSHOT[] = { I_SH_MSG,0x25,I_SH_DEAD }; BYTE SMELT_I[] = { I_SH_SWAP,0x0e,I_SH_TELL }; BYTE STELLME[] = { I_SH_TELL }; // list of auto command combinations // terminated with a zero byte // these processed at the end of each parse cycle // for each entry: // 1st = verb token code (wildcard, matches any verb) // 2nd = noun token code (wildcard, matches any noun) // 3rd = address of predicate list entry // 4th = unknown address VNDef AUT_LST[] = { { 0xff, 0xff, (void*) A_CHGRN, (void*) STURNGR }, { 0xff, 0xff, (void*) A_CHTHR, (void*) STHROTL }, { 0xff, 0xff, (void*) A_C2THR, (void*) STHROTL }, { 0xff, 0xff, (void*) A_SHOT, (void*) SSHOT }, { 0xff, 0xff, (void*) A_MELTD, (void*) SMELT_I }, { 0xff, 0xff, (void*) A_NULL, (void*) STELLME } }; // ====================================================================== // output a character to the display // ====================================================================== void i_PutCh(char ch) { putch(ch); if (ch == '\n') nRemColumns = MAX_COL; } // ====================================================================== // throw a new line on the display // ====================================================================== void PrintCR() { i_PutCh('\n'); } // ====================================================================== // clear the screen // ====================================================================== void ClearScr() { //putchar(12); int n; for (n = 0; n < 50; ++n) printf("\n"); nRemColumns = MAX_COL; } // ====================================================================== // print the zero-terminated string pointed to by HL // performing word-wrap and scrolling if necessary // ====================================================================== void PrintStr(char* hl) { char ch; char *temphl; int b; for (;;) { ch = *hl++; if (ch == 0) return; switch (ch) { case '\n': PrintCR(); break; case ' ': break; default: --hl; temphl = hl; b = 0; for (;;) { ch = *hl; if ((ch == ' ') || (ch == '\0') || (ch == '\n')) break; ++b; ++hl; } if (b > nRemColumns) PrintCR(); hl = temphl; for (;;) { ch = *hl; if ((ch == ' ') || (ch == '\0') || (ch == '\n')) break; i_PutCh(ch); ++hl; } if ((nRemColumns - b) != 0) { i_PutCh(' '); nRemColumns = nRemColumns - b - 1; } else nRemColumns = nRemColumns - b; break; } } } /**** ; main program starts here START ld hl,GVARS ; zero all game variables ld b,$1e INITLP ld (hl),$00 inc hl djnz INITLP ld hl,$0000 ld (SCORE),hl call PrintInstr ; display instructions // copied to main - initialize naItemLoc ld ix,GVARS ; initialize ix to point at the game variables ld (CUR_RM),$00 ; set current room to 0 (starting room) push hl ; save hl (points at naItemLoc) jr RESTG ; skip message data... RESTG_M .text "WANT TO RESTORE A GAME?" .byte $0d,$00 RESTG ld hl,RESTG_M ; prompt - restore game? call PrintStr ; print it pop hl ; restore hl (points at naItemLoc) call i_GetCh cp 'Y' call z,LCASS ; user typed 'Y', go and restore game ; main execution loop MAIN call ClearScr xor a cp (ix+$00) ; if (ix+$00) is zero, jr z,ROOM ; go and display the room description cp (ix+$03) ; if (ix+$03) is zero, jr z,DARK_CH ; go straight to the dark check dec (ix+$03) ; otherwise, decrement (ix+$03) DARK_CH ld a,(naItemLoc) ; get location of item $00 cp (CUR_RM) ; check whether it's in the current room jr z,ROOM ; if it is, it's not dark push hl jr DARK ; skip message data... DARK_M .text "EVERYTHING IS DARK.I CANT SEE." .byte $0d,$00 DARK ld hl,DARK_M ; say it's dark and we can't see call PrintStr pop hl xor a cp (ix+$04) ; if (ix+$04) is zero, jr z,DARK_ND ; go straight to ???????? dec (ix+$04) ; otherwise, decrement (ix+$04) DARK_ND jr DO_AUTO ; (96) ****/ // display description for current room void ShowRoom() { int nItem; PrintStr(straRoom[CUR_RM]); FLAG = FALSE; for (nItem = 0; nItem < MAX_ITEM; ++nItem) { if (naItemLoc[nItem] == CUR_RM) { if (!FLAG) { PrintStr("I CAN ALSO SEE :\n"); FLAG = TRUE; } PrintStr(straItem[nItem]); PrintCR(); } } nNextParseAction = NA_DO_AUTO; } /***** // ====================================================================== // perform regular automatic functions, e.g. the little green man // ====================================================================== void DO_AUTO() { ld hl,AUT_LST ; select the auto command list (wildcards, every command matches) jp PARS_LP ; and restart parser ***/ // ====================================================================== // system command - TELL command // generates the "tell me what to do" prompt // ====================================================================== void SH_TELL() { void GetLine(); int GET_TOK(); BYTE* pDirections; if (GVARS[GVAR_02] > 0) --GVARS[GVAR_02]; if (GVARS[GVAR_05] > 0) --GVARS[GVAR_05]; /*** { char sz[256]; sprintf(sz, "02 = %u\n", GVARS[0x02]); PrintStr(sz); } ***/ PrintStr("TELL ME WHAT TO DO \n"); GetLine(); F_NTYET = FALSE; // ====================================================================== // fetch verb token from the input buffer // ====================================================================== pchEditLine = chaEditLine; for (;;) { VERB_TK = GET_TOK(); if (VERB_TK == 0xff) { BOOL bDont = FALSE; if ((*pchEditLine == '\n') || (*pchEditLine == '\0')) bDont = TRUE; else { for (;;) { if (*pchEditLine == ' ') { ++pchEditLine; goto verb_outer_continue; } else if ((*pchEditLine == '\n') || (*pchEditLine == '\0')) { bDont = TRUE; break; } ++pchEditLine; } } if (bDont) { PrintStr("I DONT UNDERSTAND\n"); nNextParseAction = NA_DO_AUTO; return; } } else break; // verb ok verb_outer_continue: continue; } // verb recognized NOUN_TK = 0xff; // assume noun unrecognized before reading on // trim off excess characters from the verb for (;;) { char ch = *pchEditLine; if (ch == ' ') break; if (ch == '\0') goto P_DIR; if (ch == '\n') goto P_DIR; ++pchEditLine; } // ====================================================================== // fetch noun token from the input buffer // ====================================================================== for (;;) { ++pchEditLine; NOUN_TK = GET_TOK(); if (NOUN_TK != 0xff) break; for (;;) { char ch = *pchEditLine; if (ch == ' ') break; if (ch == '\0') goto P_DIR; if (ch == '\n') goto P_DIR; ++pchEditLine; } } // ====================================================================== // attempt to parse a direction verb // ====================================================================== P_DIR: pDirections = DIR_V[CUR_RM]; for (;;) { int nDir = *pDirections; if (nDir == 0xff) break; if (nDir == VERB_TK) { CUR_RM = pDirections[1]; nNextParseAction = NA_MAIN; return; } pDirections += 2; } pvndCurrent = vndDefinitions; CMDFLG = FALSE; nNextParseAction = NA_BEGIN; } void* SYS_V[]; void PARSE_LP() { int nVerbTok = pvndCurrent->nVerbTok; if (nVerbTok == 0) { if (!CMDFLG) { if (VERB_TK < TOK_GET) // direction? PrintStr("I CANT GO IN THAT DIRECTION\n"); else if (F_NTYET) PrintStr("I CANT DO THAT YET\n"); else PrintStr("I CANT\n"); } nNextParseAction = NA_DO_AUTO; return; } if ((nVerbTok == 0xff) || (nVerbTok == VERB_TK)) { int nNounTok = pvndCurrent->nNounTok; if ((nNounTok == 0xff) || (nNounTok == NOUN_TK)) { int nPred; pPredicateCurrent = (BYTE*) pvndCurrent->pPredicates; while ((nPred = *pPredicateCurrent++) != 0xff) { BOOL (*pfn)() = PRED_V[nPred]; PARAM1 = *pPredicateCurrent; if (!pfn()) { F_NTYET = TRUE; nNextParseAction = NA_CONTINUE; return; } ++pPredicateCurrent; } // execute command pActionCurrent = (BYTE*) pvndCurrent->pActions; CMDFLG = TRUE; nNextParseAction = NA_CONTINUE; for (;;) { if (*pActionCurrent == 0xff) return; else { void (*pfn)() = (void*) (SYS_V[*pActionCurrent++]); PARAM1 = *pActionCurrent; pfn(); if (nNextParseAction != NA_CONTINUE) return; ++pActionCurrent; } } PrintStr("Executed!\n"); } } nNextParseAction = NA_CONTINUE; return; } // predicates // predicate CHKROOM - this tests the current room number to make sure it's the specified room number. // if it is, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the room number BOOL CHKROOM() { return PARAM1 == CUR_RM; } // predicate for GET and DROP commands // this handler interprets PARAM1 as the item number BOOL CHKHERE() { int nLoc = naItemLoc[PARAM1]; return (nLoc == CUR_RM) || (nLoc >= ITEM_WORN); } // predicate CHKRAND - randomly allows or disallows the user's command. // if allowed, we move on to the next command, otherwise we trigger a "i can't do that yet" response. BOOL CHKRAND() { return (rand() % 256) < PARAM1; } // predicate CHKAWAY - checks that the specified item is not carried, held or in the current room. // if it is NOT, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the item number BOOL CHKAWAY() { return !CHKHERE(); } // predicate CHKWORN - checks that the specified item is being worn. // if it is, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the item number BOOL CHKWORN() { return naItemLoc[PARAM1] == ITEM_WORN; } // predicate CHKSETF - checks the game variable specified by PARAM1. // if it is non-zero, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the game variable number // used by "field" and "look up" BOOL CHKSETF() { return !!GVARS[PARAM1]; } // predicate TSTGVAR - compares the game variable specified by PARAM1 with the value specified as // the next byte after the command. // if it is equal, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the game variable number BOOL TSTGVAR() { int nParam2 = *++pPredicateCurrent; return GVARS[PARAM1] == nParam2; } // predicate CHKCLRF - checks the game variable specified by PARAM1. // if it is zero, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the game variable number BOOL CHKCLRF() { return !CHKSETF(); } // predicate CHKHELD - checks that the specified item is being carried (or worn!). // if it is, we move on to the next command, otherwise we trigger a "i can't do that yet" response. // this handler interprets PARAM1 as the item number BOOL CHKHELD() { return (naItemLoc[PARAM1] == ITEM_HELD) || (naItemLoc[PARAM1] == ITEM_WORN); } /*** ; fetch location for an item ; item number is in PARAM1 ; location is returned in A ; address of location entry is returned in HL GET_LOC ld hl,naItemLoc ld b,$00 ld c,(PARAM1) add hl,bc ld a,(hl) ret ***/ void SH_INVE() { int bNothing = TRUE; int nItem; int nLoc; PrintStr("I HAVE WITH ME THE FOLLOWING:\n"); for (nItem = 0; nItem < MAX_ITEM; ++nItem) { nLoc = naItemLoc[nItem]; if (nLoc >= ITEM_WORN) { bNothing = FALSE; PrintStr(straItem[nItem]); if (nLoc == ITEM_WORN) PrintStr(" WHICH I AM WEARING"); PrintCR(); } } if (bNothing) PrintStr("NOTHING AT ALL\n"); nNextParseAction = NA_DO_AUTO; } // ====================================================================== // system command - REMOVE command // item to be removed is specified in PARAM1 // ====================================================================== void SH_REMO() { if (naItemLoc[PARAM1] == ITEM_WORN) { if (GVARS[GVAR_NO_ITEMS] == 6) { PrintStr("I CANT. MY HANDS ARE FULL\n"); nNextParseAction = NA_DO_AUTO; } else { naItemLoc[PARAM1] = ITEM_HELD; ++GVARS[GVAR_NO_ITEMS]; } } else { PrintStr("I AM NOT WEARING IT\n"); nNextParseAction = NA_DO_AUTO; } } // ====================================================================== // system command - GET command // item to be got is specified in PARAM1 // ====================================================================== void SH_GET() { if (GVARS[GVAR_NO_ITEMS] == 6) { PrintStr("I CANT CARRY ANY MORE\n"); nNextParseAction = NA_DO_AUTO; } else if (naItemLoc[PARAM1] == CUR_RM) { naItemLoc[PARAM1] = ITEM_HELD; ++GVARS[GVAR_NO_ITEMS]; } else if ((naItemLoc[PARAM1] == ITEM_WORN) || (naItemLoc[PARAM1] == ITEM_HELD)) { PrintStr("I ALREADY HAVE IT\n"); nNextParseAction = NA_DO_AUTO; } else { PrintStr("I DON'T SEE IT HERE\n"); nNextParseAction = NA_DO_AUTO; } } // ====================================================================== // system command - DROP command // item to be dropped is specified in PARAM1 // ====================================================================== void SH_DROP() { if (naItemLoc[PARAM1] == CUR_RM) { PrintStr("I DONT HAVE IT\n"); nNextParseAction = NA_DO_AUTO; } else if (naItemLoc[PARAM1] == ITEM_WORN) { naItemLoc[PARAM1] = CUR_RM; } else if (naItemLoc[PARAM1] == ITEM_HELD) { --GVARS[GVAR_NO_ITEMS]; naItemLoc[PARAM1] = CUR_RM; } else { PrintStr("I DONT HAVE IT\n"); nNextParseAction = NA_DO_AUTO; } } // ====================================================================== // system command - WEAR command // item to be worn is specified in PARAM1 // ====================================================================== void SH_WEAR() { if (naItemLoc[PARAM1] == ITEM_HELD) { naItemLoc[PARAM1] = ITEM_WORN; --GVARS[GVAR_NO_ITEMS]; } else if (naItemLoc[PARAM1] == ITEM_WORN) { PrintStr("I AM ALREADY WEARING IT\n"); nNextParseAction = NA_DO_AUTO; } else { PrintStr("I DONT HAVE IT\n"); nNextParseAction = NA_DO_AUTO; } } // ====================================================================== // system command - display a response // index of response to be displayed is specified in PARAM1 // ====================================================================== BOOL SH_MSG() { PrintStr(straMsg[PARAM1]); return TRUE; } // ====================================================================== // system command - REDE // redescribe current room, terminating execution of system commands // ====================================================================== void SH_REDE() { nNextParseAction = NA_MAIN; } // ====================================================================== // exactly the same effect as SH_FAIL - it halts further system command // processing, // and proceeds to execute the auto commands. // ====================================================================== void SH_AUTO() { nNextParseAction = NA_DO_AUTO; } // ====================================================================== // system command - go directly to specific room (do not pass go) // index of room is specified in PARAM1 // NB: room description not automatically displayed // ====================================================================== void SH_GOTO() { CUR_RM = PARAM1; } // ====================================================================== // system command SETF - set game variable to $ff // index of variable to set is specified in PARAM1 // ====================================================================== void SH_SETF() { GVARS[PARAM1] = 0xff; } // ====================================================================== // system command CLRF - clear game variable to $00 // index of variable to clear is specified in PARAM1 // ====================================================================== void SH_CLRF() { GVARS[PARAM1] = 0x00; } // ====================================================================== // system command - SWAP // swap an item's location with the location of the following item // item to be swapped is specified in PARAM1 // ====================================================================== void SH_SWAP() { int nTemp = naItemLoc[PARAM1]; naItemLoc[PARAM1] = naItemLoc[PARAM1 + 1]; naItemLoc[PARAM1 + 1] = nTemp; } // ====================================================================== // system command - DEAD // immediately terminate game, stop executing system commands // ====================================================================== void SH_DEAD() { char i_GetCh(); PrintStr("DO YOU WISH TO TRY AGAIN?\n"); for (;;) { char ch; PrintStr("ANSWER YES OR NO\n"); ch = i_GetCh(); if (ch == 'Y') { nNextParseAction = NA_RESTART; return; } if (ch == 'N') { exit(0); } } } // display "OK.." prompt and cease processing system commands void SH_OK() { PrintStr("OK..\n"); nNextParseAction = NA_DO_AUTO; } void SH_QUIT() { char i_GetCh(); PrintStr("DO YOU WANT TO SAVE THE GAME?\n"); if (i_GetCh() == 'Y') { // save PrintStr("SAVE NOT SUPPORTED\n"); PrintStr("DO YOU WISH TO CONTINUE?\n"); if (i_GetCh() == 'Y') { nNextParseAction = NA_DO_AUTO; return; } } SH_DEAD(); } // ====================================================================== // system command SETV - set game variable to a specific value // index of variable to set is specified in PARAM1 // the new value is specified as the byte after this command // ====================================================================== void SH_SETV() { int nParam2 = *++pActionCurrent; GVARS[PARAM1] = nParam2; } // ====================================================================== // system command CREA - create item in current room // index of item to be created is specified in PARAM1 // ====================================================================== void SH_CREA() { naItemLoc[PARAM1] = CUR_RM; } // ====================================================================== // system command DEST - destroy item in current room // index of item to be destoyed is specified in PARAM1 // ====================================================================== void SH_DEST() { naItemLoc[PARAM1] = NOTX; } // clean-up and abort execution of system commands, continuing with auto commands void SH_FAIL() { nNextParseAction = NA_DO_AUTO; } // ====================================================================== // system command ADSC - add value to the current score. // value to be added is specified in PARAM1 // ====================================================================== void SH_ADSC() { nScore += PARAM1; } void SH_SCOR() { char szScore[32]; PrintStr("YOU HAVE A SCORE OF "); sprintf(szScore, "%04x", nScore); // hex! (really) PrintStr(szScore); PrintCR(); } // addresses of various system function handlers void* SYS_V[] = { SH_INVE, SH_REMO, SH_GET, SH_DROP, SH_WEAR, SH_MSG, SH_REDE, SH_AUTO, SH_GOTO, SH_SETF, SH_CLRF, SH_SWAP, SH_DEAD, SH_OK, SH_QUIT, SH_SETV, SH_CREA, SH_DEST, SH_ADSC, SH_SCOR, SH_FAIL, SH_TELL, SH_FAIL, SH_FAIL, SH_FAIL }; // ====================================================================== // fetch command token from the input buffer, starting at position HL // on return, A contains the token code (or $ff if not recognized) // and HL points to the character after the token // ====================================================================== int GET_TOK() { char *pchTokenBuffer = strTokenBuf; int nResult = 0xff; int n; strncpy(strTokenBuf, " ", 4); // clear the token buffer to spaces for (n = 0; n < 4; ++n) { char ch = *pchEditLine; if (ch == ' ') break; if (ch == '\0') break; if (ch == '\n') break; *pchTokenBuffer++ = ch; ++pchEditLine; } for (n = 0; n < MAX_TOK; ++n) { if (strncmp(strTokenBuf, taToken[n].strWord, 4) == 0) { nResult = taToken[n].nCode; break; } } return nResult; } /*** ; ====================================================================== LCASS push hl jr LCASS_1 ; (16) LCASS_M .text "READY CASSETTE" .byte $0d,$00 LCASS_1 ld hl,LCASS_M call PrintStr pop hl call i_GetCh push ix ld ix,FLAG ld de,$0029 ld a,$ff scf call ROM_LD ld ix,naItemLoc ld de,$001d ld a,$ff scf call ROM_LD pop ix ret ****/ // ====================================================================== // fetch key from buffer // waits for keypress, returns ascii code in A // ====================================================================== char i_GetCh() { int ch; do { ch = _getch(); } while ((ch != '\n') && (ch != '\r') && (ch != '\b') && !(ch >= ' ' && ch <= '~')); if (ch == '\r') ch = '\n'; if (ch >= 'a' && ch <= 'z') ch ^= 0x20; return (char) ch; } /*** ; unused keyboard-reading code (left over from ZX81 version?) push de ld d,a ld a,$7f in a,($fe) rra jr c,ZX_END2 ld a,$fe in a,($fe) rra jr c,ZX_END2 ld a,$01 or a ZX_END ld a,d pop de ret ZX_END2 xor a jr ZX_END ; (-6) ***/ // ====================================================================== // get a line of input from the user // store the data in the buffer pointed to by HL // ====================================================================== void GetLine() { int nPos = 0; char ch = 0; while (ch != '\n') { chaEditLine[nPos] = 0; ch = i_GetCh(); if (ch == '\b') // delete { if (nPos != 0) { --nPos; i_PutCh(8); i_PutCh(' '); i_PutCh(8); } } else if (ch != '\n') { if (nPos == MAX_COL) { i_PutCh(' '); i_PutCh(8); } else { i_PutCh(ch); chaEditLine[nPos++] = ch; } } } i_PutCh('\n'); } // ====================================================================== // clear screen, display instructions and wait for keypress // ====================================================================== void PrintInstr() { ClearScr(); PrintStr(strInstructions); i_GetCh(); } /**** ****/ /**** ; spurious data found in the original game GARBAGE .word $5200,$4c4f,$5220,$004f .end ****/ int main() { int n; for (;;) // restart game loop { // initialize the game variables for (n = 0; n <= 0x1e; ++n) GVARS[n] = 0; nScore = 0; PrintInstr(); // copy data from naItemStart to naItemLoc at start of game for (n = 0; n < MAX_ITEM; ++n) naItemLoc[n] = naItemStart[n]; CUR_RM = 0; PrintStr("WANT TO RESTORE A GAME?\n"); if (i_GetCh() == 'Y') { // restore PrintStr("RESTORE NOT SUPPORTED\n"); PrintStr("PRESS A KEY"); i_GetCh(); } for (;;) // main loop { ClearScr(); if (GVARS[0] == 0) { ShowRoom(); } else { if (GVARS[3] > 0) --GVARS[3]; if (naItemLoc[0] == CUR_RM) { ShowRoom(); } else { PrintStr("EVERYTHING IS DARK.I CANT SEE.\n"); if (GVARS[4] > 0) --GVARS[4]; nNextParseAction = NA_DO_AUTO; } } for (;;) // parse loop { switch (nNextParseAction) { case NA_DO_AUTO: pvndCurrent = AUT_LST; break; case NA_CONTINUE: ++pvndCurrent; break; case NA_MAIN: case NA_RESTART: goto outer_cont; break; case NA_BEGIN: break; default: PrintStr("ERROR\n"); ++pvndCurrent; break; } PARSE_LP(); } outer_cont: if (nNextParseAction == NA_RESTART) break; } } return 0; }