From 5c91ea37393dcad690ed03dc3afc56b593a1be1c Mon Sep 17 00:00:00 2001 From: "Jason S. Ninneman" Date: Wed, 2 Aug 2017 20:11:40 -0700 Subject: [PATCH] Encapsulate command words into their own struct. --- actions.c | 50 +++++++++++++++++------------------ advent.h | 7 ++--- main.c | 78 +++++++++++++++++++++++++++---------------------------- misc.c | 16 ++++++------ 4 files changed, 74 insertions(+), 77 deletions(-) diff --git a/actions.c b/actions.c index 1b9e999..dca01f5 100644 --- a/actions.c +++ b/actions.c @@ -1092,7 +1092,7 @@ static int read(struct command_t command) } if (DARK(game.loc)) { - sspeak(NO_SEE, command.raw1); + sspeak(NO_SEE, command.word[0].raw); } else if (command.obj == OYSTER && !game.clshnt && game.closed) { game.clshnt = yes(arbitrary_messages[CLUE_QUERY], arbitrary_messages[WAYOUT_CLUE], arbitrary_messages[OK_MAN]); } else if (objects[command.obj].texts[0] == NULL || @@ -1144,25 +1144,25 @@ static int rub(verb_t verb, obj_t obj) static int say(struct command_t command) /* Say. Echo WD2. Magic words override. */ { - if (command.type2 == MOTION && - (command.id2 == XYZZY || - command.id2 == PLUGH || - command.id2 == PLOVER)) { + if (command.word[1].type == MOTION && + (command.word[1].id == XYZZY || + command.word[1].id == PLUGH || + command.word[1].id == PLOVER)) { return GO_WORD2; } - if (command.type2 == ACTION && command.id2 == PART) + if (command.word[1].type == ACTION && command.word[1].id == PART) return reservoir(); - if (command.type2 == ACTION && - (command.id2 == FEE || - command.id2 == FIE || - command.id2 == FOE || - command.id2 == FOO || - command.id2 == FUM || - command.id2 == PART)) { - return bigwords(command.id2); - } - sspeak(OKEY_DOKEY, command.raw2); + if (command.word[1].type == ACTION && + (command.word[1].id == FEE || + command.word[1].id == FIE || + command.word[1].id == FOE || + command.word[1].id == FOO || + command.word[1].id == FUM || + command.word[1].id == PART)) { + return bigwords(command.word[1].id); + } + sspeak(OKEY_DOKEY, command.word[1].raw); return GO_CLEAROBJ; } @@ -1353,14 +1353,14 @@ int action(struct command_t command) command.obj = ROD2; /* FALL THROUGH */; } else if ((command.verb == FIND || - command.verb == INVENTORY) && (command.id2 == WORD_EMPTY || command.id2 == WORD_NOT_FOUND)) + command.verb == INVENTORY) && (command.word[1].id == WORD_EMPTY || command.word[1].id == WORD_NOT_FOUND)) /* FALL THROUGH */; else { - sspeak(NO_SEE, command.raw1); + sspeak(NO_SEE, command.word[0].raw); return GO_CLEAROBJ; } - if (command.id2 != WORD_EMPTY && command.id2 != WORD_NOT_FOUND) + if (command.word[1].id != WORD_EMPTY && command.word[1].id != WORD_NOT_FOUND) return GO_WORD2; if (command.verb != 0) command.part = transitive; @@ -1368,13 +1368,13 @@ int action(struct command_t command) switch (command.part) { case intransitive: - if (command.raw2[0] != '\0' && command.verb != SAY) + if (command.word[1].raw[0] != '\0' && command.verb != SAY) return GO_WORD2; if (command.verb == SAY) /* KEYS is not special, anything not NO_OBJECT or INTRANSITIVE * will do here. We're preventing interpretation as an intransitive * verb when the word is unknown. */ - command.obj = command.raw2[0] != '\0' ? KEYS : NO_OBJECT; + command.obj = command.word[1].raw[0] != '\0' ? KEYS : NO_OBJECT; if (command.obj == NO_OBJECT || command.obj == INTRANSITIVE) { /* Analyse an intransitive verb (ie, no object given yet). */ @@ -1439,7 +1439,7 @@ int action(struct command_t command) case FOE: case FOO: case FUM: - return bigwords(command.id1); + return bigwords(command.word[0].id); case BRIEF: return brief(); case READ: @@ -1568,15 +1568,15 @@ int action(struct command_t command) return reservoir(); // LCOV_EXCL_STOP case SEED: - return seed(command.verb, command.raw2); + return seed(command.verb, command.word[1].raw); case WASTE: - return waste(command.verb, (turn_t)atol(command.raw2)); + return waste(command.verb, (turn_t)atol(command.word[1].raw)); default: // LCOV_EXCL_LINE BUG(TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST); // LCOV_EXCL_LINE } case unknown: /* Unknown verb, couldn't deduce object - might need hint */ - sspeak(WHAT_DO, command.raw1); + sspeak(WHAT_DO, command.word[0].raw); return GO_CHECKHINT; default: // LCOV_EXCL_LINE BUG(SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN); // LCOV_EXCL_LINE diff --git a/advent.h b/advent.h index d235707..b011e96 100644 --- a/advent.h +++ b/advent.h @@ -184,17 +184,14 @@ struct settings_t { }; typedef struct { + char raw[LINESIZE]; vocab_t id; word_type_t type; } command_word_t; struct command_t { - char raw1[LINESIZE], raw2[LINESIZE]; enum speechpart part; - vocab_t id1; - vocab_t id2; - word_type_t type1; - word_type_t type2; + command_word_t word[2]; verb_t verb; obj_t obj; }; diff --git a/main.c b/main.c index 2b0d292..ba2f7d7 100644 --- a/main.c +++ b/main.c @@ -1059,14 +1059,14 @@ Lclearobj: return false; #ifdef GDEBUG - printf("Preserve: type1 = %u, id1 = %ld, type2 = %u id2 = %ld\n", - preserve.type1, preserve.id1, preserve.type2, preserve.id2); - printf("Command: type1 = %u, id1 = %ld, type2 = %u id2 = %ld\n", - command.type1, command.id1, command.type2, command.id2); + printf("Preserve: type1 = %u, id1 = %ld, type2 = %u, id2 = %ld\n", + preserve.word[0].type, preserve.word[0].id, preserve.word[1].type, preserve.word[1].id); + printf("Command: type1 = %u, id1 = %ld, type2 = %u, id2 = %ld\n", + command.word[0].type, command.word[0].id, command.word[1].type, command.word[1].id); #endif - /* Handling of objectless action followed by actionless object */ - if (preserve.type1 == ACTION && preserve.type2 == NO_WORD_TYPE && command.id2 == 0) + /* Handle of objectless action followed by actionless object */ + if (preserve.word[0].type == ACTION && preserve.word[1].type == NO_WORD_TYPE && command.word[1].id == 0) command.verb = preserve.verb; #ifdef BROKEN @@ -1083,8 +1083,8 @@ Lclearobj: } else lampcheck(); - if (command.type1 == MOTION && command.id1 == ENTER - && (command.id2 == STREAM || command.id2 == WATER)) { + if (command.word[0].type == MOTION && command.word[0].id == ENTER + && (command.word[1].id == STREAM || command.word[1].id == WATER)) { if (LIQLOC(game.loc) == WATER) rspeak(FEET_WET); else @@ -1093,65 +1093,65 @@ Lclearobj: goto Lclearobj; } - if (command.type1 == OBJECT) { - if (command.id1 == GRATE) { - command.type1 = MOTION; + if (command.word[0].type == OBJECT) { + if (command.word[0].id == GRATE) { + command.word[0].type = MOTION; if (game.loc == LOC_START || game.loc == LOC_VALLEY || game.loc == LOC_SLIT) { - command.id1 = DEPRESSION; + command.word[0].id = DEPRESSION; } if (game.loc == LOC_COBBLE || game.loc == LOC_DEBRIS || game.loc == LOC_AWKWARD || game.loc == LOC_BIRD || game.loc == LOC_PITTOP) { - command.id1 = ENTRANCE; + command.word[0].id = ENTRANCE; } } - if (!((command.id1 != WATER && command.id1 != OIL) || (command.id2 != PLANT && command.id2 != DOOR))) { - if (AT(command.id2)) { - command.id2 = POUR; - command.type2 = ACTION; - strncpy(command.raw2, "POUR", LINESIZE - 1); + if (!((command.word[0].id != WATER && command.word[0].id != OIL) || (command.word[1].id != PLANT && command.word[1].id != DOOR))) { + if (AT(command.word[1].id)) { + command.word[1].id = POUR; + command.word[1].type = ACTION; + strncpy(command.word[1].raw, "POUR", LINESIZE - 1); } } - if (command.id1 == CAGE && command.id2 == BIRD && HERE(CAGE) && HERE(BIRD)) { - command.id1 = CARRY; - command.type1 = ACTION; - strncpy(command.raw2, "CATCH", LINESIZE - 1); + if (command.word[0].id == CAGE && command.word[1].id == BIRD && HERE(CAGE) && HERE(BIRD)) { + command.word[0].id = CARRY; + command.word[0].type = ACTION; + strncpy(command.word[1].raw, "CATCH", LINESIZE - 1); } } Lookup: - if (strncasecmp(command.raw1, "west", sizeof("west")) == 0) { + if (strncasecmp(command.word[0].raw, "west", sizeof("west")) == 0) { if (++game.iwest == 10) rspeak(W_IS_WEST); } - if (strncasecmp(command.raw1, "go", sizeof("go")) == 0 && command.id2 != WORD_EMPTY) { + if (strncasecmp(command.word[0].raw, "go", sizeof("go")) == 0 && command.word[1].id != WORD_EMPTY) { if (++game.igo == 10) rspeak(GO_UNNEEDED); } - if (command.id1 == WORD_NOT_FOUND) { + if (command.word[0].id == WORD_NOT_FOUND) { /* Gee, I don't understand. */ - sspeak(DONT_KNOW, command.raw1); + sspeak(DONT_KNOW, command.word[0].raw); goto Lclearobj; } - switch (command.type1) { + switch (command.word[0].type) { case NO_WORD_TYPE: // FIXME: treating NO_WORD_TYPE as a motion word is confusing case MOTION: - playermove(command.id1); + playermove(command.word[0].id); return true; case OBJECT: command.part = unknown; - command.obj = command.id1; + command.obj = command.word[0].id; break; case ACTION: - if(command.type2 == NUMERIC) + if(command.word[1].type == NUMERIC) command.part = transitive; else command.part = intransitive; - command.verb = command.id1; + command.verb = command.word[0].id; break; case NUMERIC: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE @@ -1168,18 +1168,18 @@ Lookup: continue; /* back to top of main interpreter loop */ case GO_WORD2: /* Get second word for analysis. */ - command.id1 = command.id2; - command.type1 = command.type2; - strncpy(command.raw1, command.raw2, LINESIZE - 1); - command.id2 = WORD_EMPTY; - command.type2 = NO_WORD_TYPE; - command.raw2[0] = '\0'; + command.word[0].id = command.word[1].id; + command.word[0].type = command.word[1].type; + strncpy(command.word[0].raw, command.word[1].raw, LINESIZE - 1); + command.word[1].id = WORD_EMPTY; + command.word[1].type = NO_WORD_TYPE; + command.word[1].raw[0] = '\0'; goto Lookup; case GO_UNKNOWN: /* Random intransitive verbs come here. Clear obj just in case * (see attack()). */ - command.raw1[0] = toupper(command.raw1[0]); - sspeak(DO_WHAT, command.raw1); + command.word[0].raw[0] = toupper(command.word[0].raw[0]); + sspeak(DO_WHAT, command.word[0].raw); command.obj = 0; // Fallthrough case GO_CHECKHINT: // Fallthrough diff --git a/misc.c b/misc.c index 23c053f..481b521 100644 --- a/misc.c +++ b/misc.c @@ -471,7 +471,7 @@ static void tokenize(char* raw, struct command_t *cmd) /* Bound prefix on the %s would be needed to prevent buffer * overflow. but we shortstop this more simply by making each * raw-input buffer as long as the entire input buffer. */ - sscanf(raw, "%s%s", cmd->raw1, cmd->raw2); + sscanf(raw, "%s%s", cmd->word[0].raw, cmd->word[1].raw); /* (ESR) In oldstyle mode, simulate the uppercasing and truncating * effect on raw tokens of packing them into sixbit characters, 5 @@ -488,16 +488,16 @@ static void tokenize(char* raw, struct command_t *cmd) * possible an emulation of the original UI. */ if (settings.oldstyle) { - cmd->raw1[TOKLEN + TOKLEN] = cmd->raw2[TOKLEN + TOKLEN] = '\0'; - for (size_t i = 0; i < strlen(cmd->raw1); i++) - cmd->raw1[i] = toupper(cmd->raw1[i]); - for (size_t i = 0; i < strlen(cmd->raw2); i++) - cmd->raw2[i] = toupper(cmd->raw2[i]); + cmd->word[0].raw[TOKLEN + TOKLEN] = cmd->word[1].raw[TOKLEN + TOKLEN] = '\0'; + for (size_t i = 0; i < strlen(cmd->word[0].raw); i++) + cmd->word[0].raw[i] = toupper(cmd->word[0].raw[i]); + for (size_t i = 0; i < strlen(cmd->word[1].raw); i++) + cmd->word[1].raw[i] = toupper(cmd->word[1].raw[i]); } /* populate command with parsed vocabulary metadata */ - get_vocab_metadata(cmd->raw1, &(cmd->id1), &(cmd->type1)); - get_vocab_metadata(cmd->raw2, &(cmd->id2), &(cmd->type2)); + get_vocab_metadata(cmd->word[0].raw, &(cmd->word[0].id), &(cmd->word[0].type)); + get_vocab_metadata(cmd->word[1].raw, &(cmd->word[1].id), &(cmd->word[1].type)); } bool get_command_input(struct command_t *command) -- 2.31.1