From 3a93b2b5f08351c3e87d4f41c5c61273c42e9420 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sat, 24 Jun 2017 08:45:22 -0400 Subject: [PATCH] Elimination of OBJSND. --- actions.c | 32 +++++++++++++++++--------------- advent.h | 4 +++- adventure.yaml | 27 ++++++++++++++++++++++----- dungeon.c | 4 ---- init.c | 2 +- main.c | 6 +++--- misc.c | 26 +++++++++++++++++++------- newdungeon.py | 24 +++++++++++++++++++++++- 8 files changed, 88 insertions(+), 37 deletions(-) diff --git a/actions.c b/actions.c index 2b30de9..16ed7ca 100644 --- a/actions.c +++ b/actions.c @@ -44,8 +44,9 @@ static int attack(FILE *input, struct command_t *command) DESTROY(BIRD); spk = BIRD_DEAD; } else if (obj == VEND) { - pspeak(VEND, game.prop[VEND] + 2); - game.prop[VEND] = 3 - game.prop[VEND]; + bool blocking = (game.prop[VEND] == VEND_BLOCKS); + game.prop[VEND] = blocking ? VEND_UNBLOCKS : VEND_BLOCKS; + rspeak(blocking ? MACHINE_SWINGOUT : MACHINE_SWINGBACK); return GO_CLEAROBJ; } @@ -82,7 +83,7 @@ static int attack(FILE *input, struct command_t *command) GETIN(input, &command->wd1, &command->wd1x, &command->wd2, &command->wd2x); if (command->wd1 != MAKEWD(WORD_YINIT) && command->wd1 != MAKEWD(WORD_YES)) return GO_CHECKFOO; - pspeak(DRAGON, 3); + pspeak(DRAGON, look, 3); game.prop[DRAGON] = 1; game.prop[RUG] = 0; int k = (PLAC[DRAGON] + FIXD[DRAGON]) / 2; @@ -133,7 +134,7 @@ static int bigwords(token_t foo) if (HERE(EGGS))k = 1; if (game.loc == PLAC[EGGS])k = 0; MOVE(EGGS, PLAC[EGGS]); - pspeak(EGGS, k); + pspeak(EGGS, look, k); return GO_CLEAROBJ; } } @@ -356,7 +357,7 @@ static int discard(token_t verb, token_t obj, bool just_do_it) } else if (obj == COINS && HERE(VEND)) { DESTROY(COINS); DROP(BATTERY, game.loc); - pspeak(BATTERY, FRESH_BATTERIES); + pspeak(BATTERY, look, FRESH_BATTERIES); return GO_CLEAROBJ; } else if (obj == BIRD && AT(DRAGON) && game.prop[DRAGON] == 0) { rspeak(BIRD_BURNT); @@ -375,7 +376,7 @@ static int discard(token_t verb, token_t obj, bool just_do_it) } else { game.prop[VASE] = 2; if (AT(PILLOW))game.prop[VASE] = 0; - pspeak(VASE, game.prop[VASE] + 1); + pspeak(VASE, look, game.prop[VASE] + 1); if (game.prop[VASE] != 0)game.fixed[VASE] = -1; } } @@ -623,7 +624,7 @@ static int inven(void) if (spk == NO_CARRY) rspeak(NOW_HOLDING); game.blklin = false; - pspeak(i, -1); + pspeak(i, touch, -1); game.blklin = true; spk = NO_MESSAGE; } @@ -685,14 +686,15 @@ static int listen(void) spk = NO_MESSAGE; } for (int i = 1; i <= NOBJECTS; i++) { - if (!HERE(i) || OBJSND[i] == 0 || game.prop[i] < 0) + if (!HERE(i) || object_descriptions[i].sounds[0] == NULL || game.prop[i] < 0) continue; - int mi = OBJSND[i] + game.prop[i]; + int mi = game.prop[i]; if (i == BIRD) mi += 3 * game.blooded; - pspeak(i, mi, game.zzword); + pspeak(i, hear, mi, game.zzword); spk = NO_MESSAGE; - if (i == BIRD && OBJSND[i] + game.prop[i] == 8) + /* FIXME: Magic number, sensitive to bird state logic */ + if (i == BIRD && game.prop[i] == 5) DESTROY(BIRD); } rspeak(spk); @@ -775,7 +777,7 @@ static int pour(token_t verb, token_t obj) rspeak(spk); return GO_CLEAROBJ; } - pspeak(PLANT, game.prop[PLANT] + 3); + pspeak(PLANT, look, game.prop[PLANT] + 3); game.prop[PLANT] = MOD(game.prop[PLANT] + 1, 3); game.prop[PLANT2] = game.prop[PLANT]; return GO_MOVE; @@ -816,7 +818,7 @@ static int read(struct command_t command) } else if (OBJTXT[command.obj] == 0 || game.prop[command.obj] < 0) { rspeak(ACTSPK[command.verb]); } else - pspeak(command.obj, OBJTXT[command.obj] + game.prop[command.obj]); + pspeak(command.obj, study, game.prop[command.obj]); return GO_CLEAROBJ; } @@ -827,7 +829,7 @@ static int reservoir(void) rspeak(NOTHING_HAPPENS); return GO_CLEAROBJ; } else { - pspeak(RESER, game.prop[RESER] + 1); + pspeak(RESER, look, game.prop[RESER] + 1); game.prop[RESER] = 1 - game.prop[RESER]; if (AT(RESER)) return GO_CLEAROBJ; @@ -993,7 +995,7 @@ static int wave(token_t verb, token_t obj) } if (HERE(BIRD))rspeak(spk); game.prop[FISSURE] = 1 - game.prop[FISSURE]; - pspeak(FISSURE, 2 - game.prop[FISSURE]); + pspeak(FISSURE, look, 2 - game.prop[FISSURE]); return GO_CLEAROBJ; } } diff --git a/advent.h b/advent.h index ce39df1..c1fc79b 100644 --- a/advent.h +++ b/advent.h @@ -86,6 +86,8 @@ extern const char advent_to_ascii[]; extern FILE *logfp; extern bool oldstyle, editline, prompt; +enum speaktype {touch, look, hear, study}; + /* b is not needed for POSIX but harmless */ #define READ_MODE "rb" #define WRITE_MODE "wb" @@ -97,7 +99,7 @@ extern bool wordeq(token_t, token_t); extern bool wordempty(token_t); extern void wordclear(token_t *); extern void speak(const char*, ...); -extern void pspeak(vocab_t, int, ...); +extern void pspeak(vocab_t, enum speaktype, int, ...); extern void rspeak(vocab_t, ...); extern bool GETIN(FILE *, token_t*, token_t*, token_t*, token_t*); extern void echo_input(FILE*, char*, char*); diff --git a/adventure.yaml b/adventure.yaml index 0d44671..6ba2797 100644 --- a/adventure.yaml +++ b/adventure.yaml @@ -1357,6 +1357,7 @@ arbitrary_messages: !!omap - BREAK_VASE: 'You have taken the vase and hurled it delicately to the ground.' - PROD_DWARF: 'You prod the nearest dwarf, who wakes up grumpily, takes one look at\nyou, curses, and grabs for his axe.' - THIS_ACCEPTABLE: 'Is this acceptable?' +# This message is not currently used - ALREADY_OVER: 'This adventure is already over. To start a new adventure, or to\nresume an earlier adventure, please run a fresh copy of the program.' - OGRE_FULL: 'The ogre doesn''t appear to be hungry.' - OGRE_DODGE: 'The ogre, who despite his bulk is quite agile, easily dodges your\nattack. He seems almost amused by your puny effort.' @@ -1426,7 +1427,8 @@ arbitrary_messages: !!omap - TABLE_SPACE: 'Table space used:\n%d of %d words of messages %d of %d travel options\n%d of %d vocabulary words %d of %d locations\n%d of %d objects %d of %d action verbs\n%d of %d "random" messages %d of %d "class" messages\n%d of %d hints %d of %d turn threshholds' - RESUME_ABANDON: 'To resume an earlier Adventure, you must abandon the current one.' - VERSION_SKEW: 'I''m sorry, but that Adventure was begun using Version%d.%d of the\nprogram, and this is Version%d.%d. You must find the other version\nin order to resume that Adventure.' -- DAVE_TAMPERING: 'A dark fog creeps in to surround you. From somewhere in the fog you\nhear a stern voice. "This Adventure has been tampered with! You have\nbeen dabbling in magic, knowing not the havoc you might cause thereby.\nLeave at once, before you do irrevocable harm!" The fog thickens,\nuntil at last you can see nothing at all. Your vision then clears,\nand you find yourself back in The Real World.' +# This message is not currently used +- SAVE_TAMPERING: 'A dark fog creeps in to surround you. From somewhere in the fog you\nhear a stern voice. "This Adventure has been tampered with! You have\nbeen dabbling in magic, knowing not the havoc you might cause thereby.\nLeave at once, before you do irrevocable harm!" The fog thickens,\nuntil at last you can see nothing at all. Your vision then clears,\nand you find yourself back in The Real World.' - GUESS_AGAIN: 'Guess again.' - MISSING_ONE: 'You''re missing only one other treasure. Do you need help finding it?' - NO_LOCATE: 'Once you''ve found all the other treasures, it is no longer possible to\nlocate the one you''re now missing.' @@ -1434,6 +1436,8 @@ arbitrary_messages: !!omap - ADVENTURE_NEWS: 'Open Adventure is an author-approved open-source release of\nVersion 2.5 with, as yet, no gameplay changes.\nVersion 2.5 was essentially the same as Version II; the cave and the\nhazards therein are unchanged, and top score is still 430 points.\nThere are a few more hints, especially for some of the more obscure\npuzzles. There are a few minor bugfixes and cosmetic changes. You\ncan now save a game and resume it at once (formerly you had to wait a\nwhile first), but it now costs you a few points each time you save the\ngame. Saved games are now stored in much smaller files than before.' - GO_UNNEEDED: 'You don''t have to say "go" every time; just specify a direction or, if\nit''s nearby, name the place to which you wish to move.' - CANNOT_CARRY7: !!null +- MACHINE_SWINGOUT: 'As you strike the vending machine, it pivots backward along with a\nsection of wall, revealing a dark passage leading south.' +- MACHINE_SWINGBACK: 'The vending machine swings back to block the passage.' classes: - threshold: 0 @@ -1514,6 +1518,7 @@ object_descriptions: !!omap - [BIRD_UNCAGED, 'A cheerful little bird is sitting here singing.'] - [BIRD_CAGED, 'There is a little bird in the cage.'] - [BIRD_FOREST_UNCAGED, 'A cheerful little bird is sitting here singing.'] + sounds: - 'The bird''s singing is quite melodious.' - 'The bird does not seem inclined to sing while in the cage.' - 'It almost seems as though the bird is trying to tell you something.' @@ -1534,6 +1539,7 @@ object_descriptions: !!omap longs: - 'A huge green fierce snake bars the way!' - '' # chased away + sounds: - 'The snake is hissing venomously.' - OBJ_12: inventory: '*fissure' @@ -1545,23 +1551,27 @@ object_descriptions: !!omap inventory: '*stone tablet' longs: - 'A massive stone tablet imbedded in the wall reads:\n"Congratulations on bringing light into the dark-room!"' + texts: - '"Congratulations on bringing light into the dark-room!"' - OBJ_14: inventory: 'Giant clam >GRUNT!<' longs: - 'There is an enormous clam here with its shell tightly closed.' + sounds: - 'The clam is as tight-mouthed as a, er, clam.' - OBJ_15: inventory: 'Giant oyster >GROAN!<' longs: - 'There is an enormous oyster here with its shell tightly closed.' - 'Interesting. There seems to be something written on the underside of\nthe oyster.' + sounds: - 'Even though it''s an oyster, the critter''s as tight-mouthed as a clam.' - 'It says the same thing it did before. Hm, maybe it''s a pun?' - OBJ_16: inventory: '"Spelunker Today"' longs: - 'There are a few recent issues of "Spelunker Today" magazine here.' + texts: - 'I''m afraid the magazine is written in dwarvish. But pencilled on one\ncover you see, "Please leave the magazines at the construction site."' - OBJ_17: inventory: !!null @@ -1597,6 +1607,7 @@ object_descriptions: !!omap - 'The plant spurts into furious growth for a few seconds.' - 'The plant grows explosively, almost filling the bottom of the pit.' - 'You''ve over-watered the plant! It''s shriveling up! And now . . .' + sounds: - 'The plant continues to ask plaintively for water.' - 'The plant continues to demand water.' - 'The plant now maintains a contented silence.' @@ -1632,6 +1643,7 @@ object_descriptions: !!omap - 'The blood-specked body of a huge green dead dragon lies to one side.' - 'The body of a huge green dead dragon is lying off to one side.' - 'Congratulations! You have just vanquished a dragon with your bare\nhands! (Unbelievable, isn''t it?)' + sounds: - 'The dragon''s ominous hissing does not bode well for you.' - 'The dragon is, not surprisingly, silent.' - 'The dragon is, not surprisingly, silent.' @@ -1646,6 +1658,7 @@ object_descriptions: !!omap - 'A burly troll stands by the bridge and insists you throw him a\ntreasure before you may cross.' - 'The troll steps out from beneath the bridge and blocks your way.' - '' # chased away + sounds: - 'The troll sounds quite adamant in his demand for a treasure.' - OBJ_34: inventory: '*phony troll' @@ -1662,6 +1675,7 @@ object_descriptions: !!omap inventory: '*message in second maze' longs: - 'There is a message scrawled in the dust in a flowery script, reading:\n"This is not the maze where the pirate leaves his treasure chest."' + texts: - '"This is not the maze where the pirate leaves his treasure chest."' - OBJ_37: inventory: '*volcano and/or geyser' @@ -1669,12 +1683,11 @@ object_descriptions: !!omap - OBJ_38: inventory: '*vending machine' longs: - - 'There is a massive and somewhat battered vending machine here. The\ninstructions on it read: "Drop coins here to receive fresh batteries."' + - [VEND_BLOCKS, 'There is a massive and somewhat battered vending machine here. The\ninstructions on it read: "Drop coins here to receive fresh batteries."'] + - [VEND_UNBLOCKS, 'There is a massive vending machine here, swung back to reveal a\nsouthward passage.'] + texts: - '"Drop coins here to receive fresh batteries."' - - 'As you strike the vending machine, it pivots backward along with a\nsection of wall, revealing a dark passage leading south.' - - 'There is a massive vending machine here, swung back to reveal a\nsouthward passage.' - '"Drop coins here to receive fresh batteries."' - - 'The vending machine swings back to block the passage.' - OBJ_39: inventory: 'Batteries' longs: @@ -1687,6 +1700,7 @@ object_descriptions: !!omap inventory: '*ogre' longs: - 'A formidable ogre bars the northern exit.' + sounds: - 'The ogre is apparently the strong, silent type.' - OBJ_42: inventory: '*urn' @@ -1717,16 +1731,19 @@ object_descriptions: !!omap inventory: '*mud' longs: - '' + texts: - '"MAGIC WORD XYZZY"' - OBJ_48: inventory: '*note' longs: - '' + texts: - '"You won''t get it up the steps"' - OBJ_49: inventory: '*sign' longs: - '' + texts: - 'Cave under construction beyond this point.\n Proceed at own risk.\n [Witt Construction Company]' - '"Treasure Vault. Keys in main office."' - OBJ_50: diff --git a/dungeon.c b/dungeon.c index 88f632d..08f11b1 100644 --- a/dungeon.c +++ b/dungeon.c @@ -30,7 +30,6 @@ long LINUSE; long TRVS; long TRNVLS; long TABNDX; -long OBJSND[NOBJECTS + 1]; long OBJTXT[NOBJECTS + 1]; long KEY[LOCSIZ + 1]; long LINES[LINSIZ + 1]; @@ -308,7 +307,6 @@ static void read_sound_text(FILE* database) long KK = GETNUM(NULL); long I = GETNUM(NULL); if (I != 0) { - OBJSND[K] = (KK > 0 ? KK : 0); OBJTXT[K] = (I > 0 ? I : 0); continue; } @@ -327,7 +325,6 @@ static int read_database(FILE* database) * message for game.prop(N)=0. Successive prop messages are * found by chasing pointers. */ for (int I = 1; I <= NOBJECTS; I++) { - OBJSND[I] = 0; OBJTXT[I] = 0; } for (int I = 1; I <= LOCSIZ; I++) { @@ -440,7 +437,6 @@ static void write_file(FILE* header_file) fprintf(header_file, "\n"); // content variables - write_1d(header_file, OBJSND, NOBJECTS + 1, "OBJSND"); write_1d(header_file, OBJTXT, NOBJECTS + 1, "OBJTXT"); write_1d(header_file, KEY, LOCSIZ + 1, "KEY"); write_1d(header_file, TRAVEL, TRVSIZ + 1, "TRAVEL"); diff --git a/init.c b/init.c index 4511aca..46e825b 100644 --- a/init.c +++ b/init.c @@ -16,7 +16,7 @@ * 330 vocabulary words (KTAB, ATAB, TABSIZ). * 185 locations (KEY, COND, game.abbrev, game.atloc, LOCSIZ). * 100 objects (PLAC, game.place, FIXD, game.fixed, game.link (twice), - * ogame.prop, OBJSND, OBJTXT). + * ogame.prop). * 35 "action" verbs (ACTSPK, VRBSIZ). * 12 different player classifications (CTEXT, CVAL, CLSMAX). * 20 hints (game.hintlc, game.hinted, HINTS, HNTSIZ). diff --git a/main.c b/main.c index 11d967d..c2e28b5 100644 --- a/main.c +++ b/main.c @@ -687,7 +687,7 @@ static bool playermove(token_t verb, int motion) * and block him. (standard travel entries check for * game.prop(TROLL)=0.) Special stuff for bear. */ if (game.prop[TROLL] == 1) { - pspeak(TROLL, 1); + pspeak(TROLL,look, 1); game.prop[TROLL] = 0; MOVE(TROLL2, 0); MOVE(TROLL2 + NOBJECTS, 0); @@ -912,7 +912,7 @@ static void listobjects(void) int kk = game.prop[obj]; if (obj == STEPS && game.loc == game.fixed[STEPS]) kk = 1; - pspeak(obj, kk); + pspeak(obj, look, kk); } } } @@ -999,7 +999,7 @@ L2600: * tick game.clock1 unless well into cave (and not at Y2). */ if (game.closed) { if (game.prop[OYSTER] < 0 && TOTING(OYSTER)) - pspeak(OYSTER, 1); + pspeak(OYSTER, look, 1); for (size_t i = 1; i <= NOBJECTS; i++) { if (TOTING(i) && game.prop[i] < 0) game.prop[i] = -1 - game.prop[i]; diff --git a/misc.c b/misc.c index e42cbc9..d4c9955 100644 --- a/misc.c +++ b/misc.c @@ -161,17 +161,29 @@ void speak(const char* msg, ...) va_end(ap); } -void pspeak(vocab_t msg, int skip, ...) -/* Find the skip+1st message from msg and print it. msg should be - * the index of the inventory message for object. (INVEN+N+1 message - * is game.prop=N message). */ +void pspeak(vocab_t msg, enum speaktype mode, int skip, ...) +/* Find the skip+1st message from msg and print it. Modes are: + * feel = for inventory, what you can touch + * look = the long description for the state the object is in + * listen = the sound for the state the object is in + * study = text on the object. */ { va_list ap; va_start(ap, skip); - if (skip >= 0) - vspeak(object_descriptions[msg].longs[skip], ap); - else + switch (mode) { + case touch: vspeak(object_descriptions[msg].inventory, ap); + break; + case look: + vspeak(object_descriptions[msg].longs[skip], ap); + break; + case hear: + vspeak(object_descriptions[msg].sounds[skip], ap); + break; + case study: + vspeak(object_descriptions[msg].texts[skip], ap); + break; + } va_end(ap); } diff --git a/newdungeon.py b/newdungeon.py index a981a1d..89d8db6 100755 --- a/newdungeon.py +++ b/newdungeon.py @@ -22,6 +22,8 @@ h_template = """/* Generated from adventure.yaml - do not hand-hack! */ typedef struct {{ const char* inventory; const char** longs; + const char** sounds; + const char** texts; }} object_description_t; typedef struct {{ @@ -216,6 +218,12 @@ def get_object_descriptions(obj): template = """ {{ .inventory = {}, .longs = (const char* []) {{ +{} + }}, + .sounds = (const char* []) {{ +{} + }}, + .texts = (const char* []) {{ {} }}, }}, @@ -242,7 +250,21 @@ def get_object_descriptions(obj): message = message[:45] + "..." statedefines += "#define %s\t%d /* %s */\n" % (label, i, message) statedefines += "\n" - obj_str += template.format(i_msg, longs_str) + sounds_str = "" + if item[1].get("sounds") == None: + sounds_str = " " * 12 + "NULL," + else: + for l_msg in item[1]["sounds"]: + sounds_str += " " * 12 + make_c_string(l_msg) + ",\n" + sounds_str = sounds_str[:-1] # trim trailing newline + texts_str = "" + if item[1].get("texts") == None: + texts_str = " " * 12 + "NULL," + else: + for l_msg in item[1]["texts"]: + texts_str += " " * 12 + make_c_string(l_msg) + ",\n" + texts_str = texts_str[:-1] # trim trailing newline + obj_str += template.format(i_msg, longs_str, sounds_str, texts_str) obj_str = obj_str[:-1] # trim trailing newline return obj_str -- 2.31.1