From 06960d33e15bc80f9912fa92f11dd82388199bd6 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 17 Aug 2010 09:28:20 +0000 Subject: HUGO: Adding engine to the main tree svn-id: r52137 --- engines/hugo/parser.cpp | 676 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 676 insertions(+) create mode 100755 engines/hugo/parser.cpp (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp new file mode 100755 index 0000000000..f9800af2cc --- /dev/null +++ b/engines/hugo/parser.cpp @@ -0,0 +1,676 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// parser.c - handles all keyboard/command input + +#include "common/system.h" +#include "common/keyboard.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/parser.h" +#include "hugo/global.h" +#include "hugo/file.h" +#include "hugo/schedule.h" +#include "hugo/display.h" +#include "hugo/route.h" +#include "hugo/util.h" +#include "hugo/sound.h" + +namespace Hugo { + +#define BLINKS 2 // Cursor blinks per second +#define CX(X) LOWORD(X) +#define CY(Y) HIWORD(Y) + +Parser::Parser(HugoEngine &vm) : + _vm(vm), _putIndex(0), _getIndex(0) { +} + +void Parser::keyHandler(uint16 nChar, uint16 nFlags) { + status_t &gameStatus = _vm.getGameStatus(); + bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat + + debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags); + +// Process key down event - called from OnKeyDown() + switch (nChar) { // Set various toggle states + case Common::KEYCODE_ESCAPE: // Escape key, may want to QUIT + if (gameStatus.inventoryState == I_ACTIVE) // Remove inventory, if displayed + gameStatus.inventoryState = I_UP; + gameStatus.inventoryObjId = -1; // Deselect any dragged icon + break; + case Common::KEYCODE_END: + case Common::KEYCODE_HOME: + case Common::KEYCODE_LEFT: + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_UP: + case Common::KEYCODE_DOWN: + if (!repeatedFl) { + gameStatus.routeIndex = -1; // Stop any automatic route + _vm.route().setWalk(nChar); // Direction of hero travel + } + break; + case Common::KEYCODE_F1: // User Help (DOS) + if (repeatedFl) { + _vm.file().instructions(); + nChar = '\0'; + } else + _vm.screen().userHelp(); + break; + case Common::KEYCODE_F2: // Toggle sound + case Common::KEYCODE_F3: // Repeat last line + case Common::KEYCODE_F4: // Save game + case Common::KEYCODE_F5: // Restore game + case Common::KEYCODE_F6: // Inventory + case Common::KEYCODE_F8: // Turbo mode + case Common::KEYCODE_F9: // Boss button + warning("STUB: KeyHandler() - F2-F9 (DOS)"); + break; + default: // Any other key + if (!gameStatus.storyModeFl) { // Keyboard disabled + // Add printable keys to ring buffer + + uint16 bnext = _putIndex + 1; + if (bnext >= sizeof(_ringBuffer)) + bnext = 0; + if (bnext != _getIndex) { + _ringBuffer[_putIndex] = nChar; + _putIndex = bnext; + } + } + break; + } +} + +// Add any new chars to line buffer and display them. +// If CR pressed, pass line to Line_handler() +void Parser::charHandler() { + static int16 lineIndex = 0; // Index into line + static uint32 tick = 0; // For flashing cursor + static char cursor = '_'; + char c; + static command_t cmdLine; // Build command line + status_t &gameStatus = _vm.getGameStatus(); +// Strangerke : Useless ? +// bool updateFl = (_getIndex != _putIndex); // TRUE if any chars processed +// command_t status_line; // Includes prompt, cursor + +//Strangerke : Useless ? +// bool updateFl = (_getIndex != _putIndex); // TRUE if any chars processed + //command_t status_line; // Includes prompt, cursor + + debugC(4, kDebugParser, "charHandler"); + + // Check for one or more characters in ring buffer + while (_getIndex != _putIndex) { + c = _ringBuffer[_getIndex++]; + if (_getIndex >= sizeof(_ringBuffer)) + _getIndex = 0; + + switch (c) { + case Common::KEYCODE_BACKSPACE: // Rubout key + if (lineIndex) + cmdLine[--lineIndex] = '\0'; + break; + case Common::KEYCODE_RETURN: // EOL, pass line to line handler + if (lineIndex && (_vm._hero->pathType != QUIET)) { + // Remove inventory bar if active + if (gameStatus.inventoryState == I_ACTIVE) + gameStatus.inventoryState = I_UP; + // Call Line handler and reset line + command(cmdLine); + cmdLine[lineIndex = 0] = '\0'; + } + break; + default: // Normal text key, add to line + if (lineIndex >= MAX_CHARS) { + //MessageBeep(MB_ICONASTERISK); + warning("STUB: MessageBeep(MB_ICONASTERISK);"); + } else if (isprint(c)) { + cmdLine[lineIndex++] = c; + cmdLine[lineIndex] = '\0'; + } + break; + } + } + + // See if time to blink cursor, set cursor character + if ((tick++ % (TPS / BLINKS)) == 0) { +// Strangerke : Useless ? +// updateFl = true; // Force an update + cursor = cursor == '_' ? ' ' : '_'; + } + + // See if recall button pressed + if (gameStatus.recallFl) { + // Copy previous line to current cmdline + gameStatus.recallFl = false; + strcpy(cmdLine, _line); + lineIndex = strlen(cmdLine); + } + + sprintf(_statusLine, ">%s%c", cmdLine, cursor); + sprintf(_scoreLine, "Score: %d of %d", _vm.getScore(), _vm.getMaxScore()); + + // See if "look" button pressed + if (gameStatus.lookFl) { + command("look around"); + gameStatus.lookFl = false; + } +} + +void Parser::drawStatusText() { + debugC(4, kDebugParser, "drawStatusText"); + + if (_vm.getPlatform() == Common::kPlatformWindows) + _vm.screen().loadFont(U_FONT8); + uint16 sdx = _vm.screen().stringLength(_statusLine); + uint16 sdy = _vm.screen().fontHeight() + 1; // + 1 for shadow + uint16 posX = 0; + uint16 posY = YPIX - sdy; + // Display the string and add rect to display list + _vm.screen().writeStr(posX, posY, _statusLine, _TLIGHTYELLOW); + _vm.screen().displayList(D_ADD, posX, posY, sdx, sdy); + + sdx = _vm.screen().stringLength(_scoreLine); + posY = 0; + _vm.screen().writeStr(posX, posY, _scoreLine, _TCYAN); + _vm.screen().displayList(D_ADD, posX, posY, sdx, sdy); +} + +// Perform an immediate command. Takes parameters a la sprintf +// Assumes final string will not overrun line[] length +void Parser::command(const char *format, ...) { + va_list marker; + + debugC(1, kDebugParser, "Command(%s, ...)", format); + + va_start(marker, format); + vsprintf(_line, format, marker); + va_end(marker); + + lineHandler(); +} + +char *Parser::strlwr(char *buffer) { + char *result = buffer; + + debugC(1, kDebugParser, "strlwr(%s)", buffer); + + while (*buffer != '\0') { + if (isupper(*buffer)) + *buffer = tolower(*buffer); + buffer++; + } + + return result; +} + +// Parse the user's line of text input. Generate events as necessary +void Parser::lineHandler() { + char *noun, *verb; // ptrs to noun and verb strings +// int i; + object_t *obj; + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + char contextComment[XBYTES * 5] = ""; // Unused comment for context objects + status_t &gameStatus = _vm.getGameStatus(); + + + debugC(1, kDebugParser, "lineHandler"); + + // Toggle God Mode + if (!strncmp(_line, "PPG", 3)) { + _vm.sound().playSound(!_vm._soundTest, BOTH_CHANNELS, HIGH_PRI); + gameStatus.godModeFl ^= 1; + return; + } + + strlwr(_line); // Convert to lower case + + // God Mode cheat commands: + // goto Takes hero to named screen + // fetch Hero carries named object + // fetch all Hero carries all possible objects + // find Takes hero to screen containing named object + if (DEBUG || gameStatus.godModeFl) { + // Special code to allow me to go straight to any screen + if (strstr(_line, "goto")) + for (int i = 0; i < _vm._numScreens; i++) + if (!strcmp(&_line[strlen("goto") + 1], _vm._screenNames[i])) { + _vm.scheduler().newScreen(i); + return; + } + + // Special code to allow me to get objects from anywhere + if (strstr(_line, "fetch all")) { + for (int i = 0; i < _vm._numObj; i++) + if (_vm._objects[i].genericCmd & TAKE) + takeObject(&_vm._objects[i]); + return; + } + + if (strstr(_line, "fetch")) { + for (int i = 0; i < _vm._numObj; i++) + if (!strcmp(&_line[strlen("fetch") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { + takeObject(&_vm._objects[i]); + return; + } + } + + // Special code to allow me to goto objects + if (strstr(_line, "find")) + for (int i = 0; i < _vm._numObj; i++) + if (!strcmp(&_line[strlen("find") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { + _vm.scheduler().newScreen(_vm._objects[i].screenIndex); + return; + } + } + + // Special meta commands + // EXIT/QUIT + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + Utils::Box(BOX_ANY, _vm._textParser[kTBExit]); + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line) && gameStatus.viewState == V_PLAY) { + _vm.file().saveGame(gameStatus.saveSlot, "Current game"); + return; + } + + if (!strcmp("restore", _line) && gameStatus.viewState == V_PLAY || gameStatus.viewState == V_IDLE) { + _vm.file().restoreGame(gameStatus.saveSlot); + _vm.scheduler().restoreScreen(*_vm._screen_p); + gameStatus.viewState = V_PLAY; + return; + } + + // Empty line + if (*_line == '\0') // Empty line + return; + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { + // No commands allowed! + Utils::gameOverMsg(); + return; + } + + // Test for nearby objects referenced explicitly + for (int i = 0; i < _vm._numObj; i++) { + obj = &_vm._objects[i]; + if (isWordPresent(_vm._arrayNouns[obj->nounIndex])) + if (isObjectVerb(obj, _line, farComment) || isGenericVerb(obj, _line, farComment)) + return; + } + + // Test for nearby objects that only require a verb + // Note comment is unused if not near. + for (int i = 0; i < _vm._numObj; i++) { + obj = &_vm._objects[i]; + if (obj->verbOnlyFl) + if (isObjectVerb(obj, _line, contextComment) || isGenericVerb(obj, _line, contextComment)) + return; + } + + // No objects match command line, try background and catchall commands + if (isBackgroundWord(_vm._backgroundObjects[*_vm._screen_p], _line)) + return; + if (isCatchallVerb(_vm._backgroundObjects[*_vm._screen_p], _line)) + return; + if (isBackgroundWord(_vm._catchallList, _line)) + return; + if (isCatchallVerb(_vm._catchallList, _line)) + return; + + // If a not-near comment was generated, print it + if (*farComment != '\0') { + Utils::Box(BOX_ANY, farComment); + return; + } + + // Nothing matches. Report recognition success to user. + verb = findVerb(_line); + noun = findNoun(_line); + if (verb == _vm._arrayVerbs[_vm._look][0] && _maze.enabledFl) { + Utils::Box(BOX_ANY, _vm._textParser[kTBMaze]); + showTakeables(); + } else if (verb && noun) // A combination I didn't think of + Utils::Box(BOX_ANY, _vm._textParser[kTBNoPoint]); + else if (noun) + Utils::Box(BOX_ANY, _vm._textParser[kTBNoun]); + else if (verb) + Utils::Box(BOX_ANY, _vm._textParser[kTBVerb]); + else + Utils::Box(BOX_ANY, _vm._textParser[kTBEh]); +} + +// Search for matching verb/noun pairs in background command list +// Print text for possible background object. Return TRUE if match found +bool Parser::isBackgroundWord(objectList_t obj, char *line) { + debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj, %s)", line); + + for (int i = 0; obj[i].verbIndex != 0; i++) + if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && + isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { + Utils::Box(BOX_ANY, _vm.file().fetchString(obj[i].commentIndex)); + _vm.scheduler().processBonus(obj[i].bonusIndex); + return true; + } + return false; +} + +// Search for matching verbs in background command list. +// Noun is not required. Return TRUE if match found +// Note that if the background command list has match set TRUE then do not +// print text if there are any recognizable nouns in the command line +bool Parser::isCatchallVerb(objectList_t obj, char *line) { + debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj, %s)", line); + + for (int i = 0; obj[i].verbIndex != 0; i++) + if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && + (!obj[i].matchFl || !findNoun(line)) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { + Utils::Box(BOX_ANY, _vm.file().fetchString(obj[i].commentIndex)); + _vm.scheduler().processBonus(obj[i].bonusIndex); + + // If this is LOOK (without a noun), show any takeable objects + if (*(_vm._arrayVerbs[obj[i].verbIndex]) == _vm._arrayVerbs[_vm._look][0]) + showTakeables(); + + return(true); + } + return false; +} + +// Test whether hero is close to object. Return TRUE or FALSE +// If object not near, return suitable comment; may be another object close +// If radius is -1, treat radius as infinity +// Verb is included to determine correct comment if not near +bool Parser::isNear(object_t *obj, char *verb, char *comment) { + debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); + + if (obj->carriedFl) // Object is being carried + return(true); + + if (obj->screenIndex != *_vm._screen_p) { + // Not in same screen + if (obj->objValue) + strcpy(comment, _vm._textParser[kCmtAny1]); + else + strcpy(comment, _vm._textParser[kCmtAny2]); + return(false); + } + + if (obj->cycling == INVISIBLE) + if (obj->seqNumb) { + // There is an image + strcpy(comment, _vm._textParser[kCmtAny3]); + return(false); + } else + // No image, assume visible + if ((obj->radius < 0) || + ((abs(obj->x - _vm._hero->x) <= obj->radius) && + (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) + return(true); + else { + // User is not close enough + if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) + strcpy(comment, _vm._textParser[kCmtAny1]); + else + strcpy(comment, _vm._textParser[kCmtClose]); + return(false); + } + + if ((obj->radius < 0) || + ((abs(obj->x - _vm._hero->x) <= obj->radius) && + (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) + return(true); + else { + // User is not close enough + if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) + strcpy(comment, _vm._textParser[kCmtAny1]); + else + strcpy(comment, _vm._textParser[kCmtClose]); + return(false); + } + return true; +} + +// Locate any member of object name list appearing in command line +bool Parser::isWordPresent(char **wordArr) { + debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]); + + if (wordArr != NULL) { + for (int i = 0; strlen(wordArr[i]); i++) + if (strstr(_line, wordArr[i])) + return(true); + } + + return false; +} + +// Locate word in list of nouns and return ptr to first string in noun list +char *Parser::findNoun(char *line) { + debugC(1, kDebugParser, "findNoun(%s)", line); + + for (int i = 0; _vm._arrayNouns[i]; i++) + for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) + if (strstr(line, _vm._arrayNouns[i][j])) + return(_vm._arrayNouns[i][0]); + return NULL; +} + +// Locate word in list of verbs and return ptr to first string in verb list +char *Parser::findVerb(char *line) { + debugC(1, kDebugParser, "findVerb(%s)", line); + + for (int i = 0; _vm._arrayVerbs[i]; i++) + for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) + if (strstr(line, _vm._arrayVerbs[i][j])) + return(_vm._arrayVerbs[i][0]); + return NULL; +} + +// Describe any takeable objects visible in this screen +void Parser::showTakeables() { + object_t *obj; + + debugC(1, kDebugParser, "showTakeables"); + + for (int j = 0; j < _vm._numObj; j++) { + obj = &_vm._objects[j]; + if ((obj->cycling != INVISIBLE) && + (obj->screenIndex == *_vm._screen_p) && + (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { + sprintf(_textBoxBuffer, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); + Utils::Box(BOX_ANY, _textBoxBuffer); + } + } +} + +// Do all things necessary to carry an object +void Parser::takeObject(object_t *obj) { + debugC(1, kDebugParser, "takeObject(object_t *obj)"); + + obj->carriedFl = true; + if (obj->seqNumb) { // Don't change if no image to display + obj->cycling = INVISIBLE; + if (_vm.getPlatform() != Common::kPlatformWindows) + warning("takeObject : DOS version should use ALMOST_INVISIBLE"); + } + _vm.adjustScore(obj->objValue); + + if (obj->seqNumb > 0) // If object has an image, force walk to dropped + obj->viewx = -1; // (possibly moved) object next time taken! + Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); +} + +// Do all necessary things to drop an object +void Parser::dropObject(object_t *obj) { + debugC(1, kDebugParser, "dropObject(object_t *obj)"); + + obj->carriedFl = false; + obj->screenIndex = *_vm._screen_p; + if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) + obj->cycling = CYCLE_FORWARD; + else + obj->cycling = NOT_CYCLING; + obj->x = _vm._hero->x - 1; + obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; + obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; + _vm.adjustScore(-obj->objValue); + Utils::Box(BOX_ANY, _vm._textParser[kTBOk]); +} + +// Test whether command line contains one of the generic actions +bool Parser::isGenericVerb(object_t *obj, char *line, char *comment) { + debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s, %s)", line, comment); + + if (!obj->genericCmd) + return false; + + // Following is equivalent to switch, but couldn't do one + if (isWordPresent(_vm._arrayVerbs[_vm._look]) && isNear(obj, _vm._arrayVerbs[_vm._look][0], comment)) { + // Test state-dependent look before general look + if ((obj->genericCmd & LOOK_S) == LOOK_S) { + Utils::Box(BOX_ANY, _vm._textData[obj->stateDataIndex[obj->state]]); + warning("isGenericVerb: use of state dependant look - To be validated"); + } else { + if ((LOOK & obj->genericCmd) == LOOK) + if (_vm._textData[obj->dataIndex]) + Utils::Box(BOX_ANY, _vm._textData[obj->dataIndex]); + else + return(false); + else + Utils::Box(BOX_ANY, _vm._textParser[kTBUnusual]); + } + } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { + if (obj->carriedFl) + Utils::Box(BOX_ANY, _vm._textParser[kTBHave]); + else if ((TAKE & obj->genericCmd) == TAKE) + takeObject(obj); + else if (obj->cmdIndex != 0) // No comment if possible commands + return false; + else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! + Utils::Box(BOX_ANY, _vm._textParser[kTBNoUse]); + else + return false; + } else if (isWordPresent(_vm._arrayVerbs[_vm._drop])) { + if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + Utils::Box(BOX_ANY, _vm._textParser[kTBDontHave]); + else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + dropObject(obj); + else if (obj->cmdIndex == 0) + Utils::Box(BOX_ANY, _vm._textParser[kTBNeed]); + else + return false; + } else // It was not a generic cmd + return false; + + return true; +} + +// Return TRUE if object being carried by hero +bool Parser::isCarrying(uint16 wordIndex) { + debugC(1, kDebugParser, "isCarrying(%d)", wordIndex); + + for (int i = 0; i < _vm._numObj; i++) + if ((wordIndex == _vm._objects[i].nounIndex) && _vm._objects[i].carriedFl) + return true; + return false; +} + +// Test whether command line contains a verb allowed by this object. +// If it does, and the object is near and passes the tests in the command +// list then carry out the actions in the action list and return TRUE +bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { + int i; + cmd *cmnd; + char *verb; + uint16 *reqs; + uint16 cmdIndex; + + debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s, %s)", line, comment); + + // First, find matching verb in cmd list + cmdIndex = obj->cmdIndex; // ptr to list of commands + if (cmdIndex == 0) // No commands for this obj + return false; + + for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) // For each cmd + if (isWordPresent(_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex])) // Was this verb used? + break; + if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. + return false; + + // Verb match found. Check if object is Near + verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; + if (!isNear(obj, verb, comment)) + return(false); + + // Check all required objects are being carried + cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd + if (cmnd->reqIndex) { // At least 1 thing in list + reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + for (i = 0; reqs[i]; i++) // for each obj + if (!isCarrying(reqs[i])) { + Utils::Box(BOX_ANY, _vm._textData[cmnd->textDataNoCarryIndex]); + return true; + } + } + + // Required objects are present, now check state is correct + if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { + Utils::Box(BOX_ANY, _vm._textData[cmnd->textDataWrongIndex]); + return true; + } + + // Everything checked. Change the state and carry out any actions + if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care + obj->state = cmnd->newState; + Utils::Box(BOX_ANY, _vm._textData[cmnd->textDataDoneIndex]); + _vm.scheduler().insertActionList(cmnd->actIndex); + + // See if any additional generic actions + if ((verb == _vm._arrayVerbs[_vm._look][0]) || (verb == _vm._arrayVerbs[_vm._take][0]) || (verb == _vm._arrayVerbs[_vm._drop][0])) + isGenericVerb(obj, line, comment); + return true; +} + +} // end of namespace Hugo -- cgit v1.2.3 From 789219022ac353ec72086d96c45a958c856abef2 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 17 Aug 2010 11:00:00 +0000 Subject: HUGO: Fix game restoring svn-id: r52145 --- engines/hugo/parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index f9800af2cc..c184000602 100755 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -309,7 +309,7 @@ void Parser::lineHandler() { return; } - if (!strcmp("restore", _line) && gameStatus.viewState == V_PLAY || gameStatus.viewState == V_IDLE) { + if (!strcmp("restore", _line) && (gameStatus.viewState == V_PLAY || gameStatus.viewState == V_IDLE)) { _vm.file().restoreGame(gameStatus.saveSlot); _vm.scheduler().restoreScreen(*_vm._screen_p); gameStatus.viewState = V_PLAY; -- cgit v1.2.3 From 2c545ae1f38e479f2df1d270170bc9708b93a824 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 17 Aug 2010 11:00:29 +0000 Subject: HUGO: Fix warnings svn-id: r52146 --- engines/hugo/parser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index c184000602..c9c3b8dc4e 100755 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -437,7 +437,7 @@ bool Parser::isNear(object_t *obj, char *verb, char *comment) { return(false); } - if (obj->cycling == INVISIBLE) + if (obj->cycling == INVISIBLE) { if (obj->seqNumb) { // There is an image strcpy(comment, _vm._textParser[kCmtAny3]); @@ -456,6 +456,7 @@ bool Parser::isNear(object_t *obj, char *verb, char *comment) { strcpy(comment, _vm._textParser[kCmtClose]); return(false); } + } if ((obj->radius < 0) || ((abs(obj->x - _vm._hero->x) <= obj->radius) && -- cgit v1.2.3 From 54c1a1463f2eadb8bf48c234f2474d395b7d62a6 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Tue, 17 Aug 2010 23:55:31 +0000 Subject: HUGO: Fix file permissions 755->644 svn-id: r52177 --- engines/hugo/parser.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 engines/hugo/parser.cpp (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp old mode 100755 new mode 100644 -- cgit v1.2.3 From fa41f9ffd05a97c90a59fb629a7b6e61abf231fa Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Wed, 18 Aug 2010 16:14:38 +0000 Subject: Hugo - Check double F1, display properly the content of help.dat if present svn-id: r52189 --- engines/hugo/parser.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index c9c3b8dc4e..60a33425de 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -54,6 +54,7 @@ namespace Hugo { Parser::Parser(HugoEngine &vm) : _vm(vm), _putIndex(0), _getIndex(0) { + _checkDoubleF1Fl = false; } void Parser::keyHandler(uint16 nChar, uint16 nFlags) { @@ -81,11 +82,12 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { } break; case Common::KEYCODE_F1: // User Help (DOS) - if (repeatedFl) { + if (_checkDoubleF1Fl) { _vm.file().instructions(); - nChar = '\0'; + _checkDoubleF1Fl = false; } else _vm.screen().userHelp(); + _checkDoubleF1Fl = true; break; case Common::KEYCODE_F2: // Toggle sound case Common::KEYCODE_F3: // Repeat last line @@ -110,6 +112,8 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { } break; } + if ((_checkDoubleF1Fl) && (nChar != Common::KEYCODE_F1)) + _checkDoubleF1Fl = false; } // Add any new chars to line buffer and display them. @@ -125,10 +129,6 @@ void Parser::charHandler() { // bool updateFl = (_getIndex != _putIndex); // TRUE if any chars processed // command_t status_line; // Includes prompt, cursor -//Strangerke : Useless ? -// bool updateFl = (_getIndex != _putIndex); // TRUE if any chars processed - //command_t status_line; // Includes prompt, cursor - debugC(4, kDebugParser, "charHandler"); // Check for one or more characters in ring buffer -- cgit v1.2.3 From 844b4665738b7946b072c55ad257ed535f8399ca Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Wed, 18 Aug 2010 16:44:12 +0000 Subject: Hugo - Add F6 Inventory. This is a DOS only feature, but quite convenient as the iconic inventory is not available atm. svn-id: r52190 --- engines/hugo/parser.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 60a33425de..24ee1bf3c8 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -89,11 +89,13 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { _vm.screen().userHelp(); _checkDoubleF1Fl = true; break; + case Common::KEYCODE_F6: // Inventory + showDosInventory(); + break; case Common::KEYCODE_F2: // Toggle sound case Common::KEYCODE_F3: // Repeat last line case Common::KEYCODE_F4: // Save game case Common::KEYCODE_F5: // Restore game - case Common::KEYCODE_F6: // Inventory case Common::KEYCODE_F8: // Turbo mode case Common::KEYCODE_F9: // Boss button warning("STUB: KeyHandler() - F2-F9 (DOS)"); @@ -674,4 +676,42 @@ bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { return true; } +void Parser::showDosInventory() { +// Show user all objects being carried in a variable width 2 column format +static char *intro = "You are carrying:"; +static char *outro = "\nPress ESCAPE to continue"; +static char *blanks = " "; +uint16 index, len, len1 = 0, len2 = 0; +char buffer[XBYTES * NUM_ROWS] = "\0"; + + index = 0; + for (int i = 0; i < _vm._numObj; i++) /* Find widths of 2 columns */ + if (_vm._objects[i].carriedFl) { + len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); + if (index++ & 1) /* Right hand column */ + len2 = len > len2 ? len : len2; + else + len1 = len > len1 ? len : len1; + } + len1 += 1; /* For gap between columns */ + + if (len1 + len2 < (uint16)strlen(outro)) + len1 = strlen(outro); + + strncat (buffer, blanks, (len1 + len2 - strlen(intro)) / 2); + strcat (strcat (buffer, intro), "\n"); + index = 0; + for (int i = 0; i < _vm._numObj; i++) /* Assign strings */ + if (_vm._objects[i].carriedFl) + if (index++ & 1) + strcat (strcat (buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); + else + strncat (strcat (buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); + if (index & 1) strcat (buffer, "\n"); + strcat (buffer, outro); + + Utils::Box(BOX_ANY, buffer); +} + + } // end of namespace Hugo -- cgit v1.2.3 From 7f97d568298b51370fef3d25b847268416849694 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Wed, 18 Aug 2010 17:51:44 +0000 Subject: HUGO: Fix GCC warnings. svn-id: r52192 --- engines/hugo/parser.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 24ee1bf3c8..79b616adde 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -678,9 +678,9 @@ bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { void Parser::showDosInventory() { // Show user all objects being carried in a variable width 2 column format -static char *intro = "You are carrying:"; -static char *outro = "\nPress ESCAPE to continue"; -static char *blanks = " "; +static const char *intro = "You are carrying:"; +static const char *outro = "\nPress ESCAPE to continue"; +static const char *blanks = " "; uint16 index, len, len1 = 0, len2 = 0; char buffer[XBYTES * NUM_ROWS] = "\0"; @@ -701,12 +701,14 @@ char buffer[XBYTES * NUM_ROWS] = "\0"; strncat (buffer, blanks, (len1 + len2 - strlen(intro)) / 2); strcat (strcat (buffer, intro), "\n"); index = 0; - for (int i = 0; i < _vm._numObj; i++) /* Assign strings */ - if (_vm._objects[i].carriedFl) + for (int i = 0; i < _vm._numObj; i++) { /* Assign strings */ + if (_vm._objects[i].carriedFl) { if (index++ & 1) strcat (strcat (buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); else strncat (strcat (buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); + } + } if (index & 1) strcat (buffer, "\n"); strcat (buffer, outro); -- cgit v1.2.3 From 0b4fef3aa745a873deb99ca9ff95e33d12770f2c Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Fri, 20 Aug 2010 15:30:30 +0000 Subject: Hugo - Move DOS hardcoded inventory strings to Hugo.dat svn-id: r52226 --- engines/hugo/parser.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 79b616adde..41d9a5afb5 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -678,8 +678,6 @@ bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { void Parser::showDosInventory() { // Show user all objects being carried in a variable width 2 column format -static const char *intro = "You are carrying:"; -static const char *outro = "\nPress ESCAPE to continue"; static const char *blanks = " "; uint16 index, len, len1 = 0, len2 = 0; char buffer[XBYTES * NUM_ROWS] = "\0"; @@ -695,11 +693,11 @@ char buffer[XBYTES * NUM_ROWS] = "\0"; } len1 += 1; /* For gap between columns */ - if (len1 + len2 < (uint16)strlen(outro)) - len1 = strlen(outro); + if (len1 + len2 < (uint16)strlen(_vm._textParser[kTBOutro])) + len1 = strlen(_vm._textParser[kTBOutro]); - strncat (buffer, blanks, (len1 + len2 - strlen(intro)) / 2); - strcat (strcat (buffer, intro), "\n"); + strncat (buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); + strcat (strcat (buffer, _vm._textParser[kTBIntro]), "\n"); index = 0; for (int i = 0; i < _vm._numObj; i++) { /* Assign strings */ if (_vm._objects[i].carriedFl) { @@ -710,7 +708,7 @@ char buffer[XBYTES * NUM_ROWS] = "\0"; } } if (index & 1) strcat (buffer, "\n"); - strcat (buffer, outro); + strcat (buffer, _vm._textParser[kTBOutro]); Utils::Box(BOX_ANY, buffer); } -- cgit v1.2.3 From 30f1312386e8b6ae0156e48eaac2d54c53985b51 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Fri, 20 Aug 2010 15:55:56 +0000 Subject: Hugo - Add handling of "turbo" key (F8) - Modify the score line so it looks like the DOS one svn-id: r52227 --- engines/hugo/parser.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 41d9a5afb5..5fa0dac774 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -92,11 +92,13 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { case Common::KEYCODE_F6: // Inventory showDosInventory(); break; + case Common::KEYCODE_F8: // Turbo mode + _config.turboFl ^= 1; + break; case Common::KEYCODE_F2: // Toggle sound case Common::KEYCODE_F3: // Repeat last line case Common::KEYCODE_F4: // Save game case Common::KEYCODE_F5: // Restore game - case Common::KEYCODE_F8: // Turbo mode case Common::KEYCODE_F9: // Boss button warning("STUB: KeyHandler() - F2-F9 (DOS)"); break; @@ -182,7 +184,7 @@ void Parser::charHandler() { } sprintf(_statusLine, ">%s%c", cmdLine, cursor); - sprintf(_scoreLine, "Score: %d of %d", _vm.getScore(), _vm.getMaxScore()); + sprintf(_scoreLine, "F1-Help %s Score: %d of %d", (_config.turboFl) ? "T" : " ", _vm.getScore(), _vm.getMaxScore()); // See if "look" button pressed if (gameStatus.lookFl) { -- cgit v1.2.3 From 48c9b4855bd9481f88912333aae0bf4aa3b0978c Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Fri, 20 Aug 2010 16:02:00 +0000 Subject: Hugo - Fix a problem in the F1 behavior svn-id: r52228 --- engines/hugo/parser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 5fa0dac774..9a889698ef 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -85,9 +85,10 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { if (_checkDoubleF1Fl) { _vm.file().instructions(); _checkDoubleF1Fl = false; - } else + } else { _vm.screen().userHelp(); _checkDoubleF1Fl = true; + } break; case Common::KEYCODE_F6: // Inventory showDosInventory(); -- cgit v1.2.3 From 53bf93a8847c47f983a3ee25bffa8f6072ad82d4 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Fri, 20 Aug 2010 16:25:48 +0000 Subject: Hugo : Add toggle sound, plus little clean up svn-id: r52229 --- engines/hugo/parser.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 9a889698ef..dec98087e6 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -82,26 +82,27 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { } break; case Common::KEYCODE_F1: // User Help (DOS) - if (_checkDoubleF1Fl) { + if (_checkDoubleF1Fl) _vm.file().instructions(); - _checkDoubleF1Fl = false; - } else { + else _vm.screen().userHelp(); - _checkDoubleF1Fl = true; - } + _checkDoubleF1Fl = !_checkDoubleF1Fl; break; case Common::KEYCODE_F6: // Inventory showDosInventory(); break; case Common::KEYCODE_F8: // Turbo mode - _config.turboFl ^= 1; + _config.turboFl = !_config.turboFl; break; case Common::KEYCODE_F2: // Toggle sound + _vm.sound().toggleSound(); + _vm.sound().toggleMusic(); + break; case Common::KEYCODE_F3: // Repeat last line case Common::KEYCODE_F4: // Save game case Common::KEYCODE_F5: // Restore game case Common::KEYCODE_F9: // Boss button - warning("STUB: KeyHandler() - F2-F9 (DOS)"); + warning("STUB: KeyHandler() - F3-F9 (DOS)"); break; default: // Any other key if (!gameStatus.storyModeFl) { // Keyboard disabled @@ -173,7 +174,7 @@ void Parser::charHandler() { if ((tick++ % (TPS / BLINKS)) == 0) { // Strangerke : Useless ? // updateFl = true; // Force an update - cursor = cursor == '_' ? ' ' : '_'; + cursor = (cursor == '_') ? ' ' : '_'; } // See if recall button pressed @@ -185,7 +186,7 @@ void Parser::charHandler() { } sprintf(_statusLine, ">%s%c", cmdLine, cursor); - sprintf(_scoreLine, "F1-Help %s Score: %d of %d", (_config.turboFl) ? "T" : " ", _vm.getScore(), _vm.getMaxScore()); + sprintf(_scoreLine, "F1-Help %s Score: %d of %d Sound %s", (_config.turboFl) ? "T" : " ", _vm.getScore(), _vm.getMaxScore(), (_config.soundFl) ? "On" : "Off"); // See if "look" button pressed if (gameStatus.lookFl) { @@ -690,9 +691,9 @@ char buffer[XBYTES * NUM_ROWS] = "\0"; if (_vm._objects[i].carriedFl) { len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); if (index++ & 1) /* Right hand column */ - len2 = len > len2 ? len : len2; + len2 = (len > len2) ? len : len2; else - len1 = len > len1 ? len : len1; + len1 = (len > len1) ? len : len1; } len1 += 1; /* For gap between columns */ -- cgit v1.2.3 From 1a0d7c87d36a9bf1aa27186b1299b3a5348656b6 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 21 Aug 2010 17:27:48 +0000 Subject: Hugo: Some formatting fixes. svn-id: r52265 --- engines/hugo/parser.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index dec98087e6..ad2b107329 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -53,8 +53,7 @@ namespace Hugo { #define CY(Y) HIWORD(Y) Parser::Parser(HugoEngine &vm) : - _vm(vm), _putIndex(0), _getIndex(0) { - _checkDoubleF1Fl = false; + _vm(vm), _putIndex(0), _getIndex(0), _checkDoubleF1Fl(false) { } void Parser::keyHandler(uint16 nChar, uint16 nFlags) { @@ -118,7 +117,7 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { } break; } - if ((_checkDoubleF1Fl) && (nChar != Common::KEYCODE_F1)) + if (_checkDoubleF1Fl && (nChar != Common::KEYCODE_F1)) _checkDoubleF1Fl = false; } @@ -682,9 +681,9 @@ bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { void Parser::showDosInventory() { // Show user all objects being carried in a variable width 2 column format -static const char *blanks = " "; -uint16 index, len, len1 = 0, len2 = 0; -char buffer[XBYTES * NUM_ROWS] = "\0"; + static const char *blanks = " "; + uint16 index, len, len1 = 0, len2 = 0; + char buffer[XBYTES *NUM_ROWS] = "\0"; index = 0; for (int i = 0; i < _vm._numObj; i++) /* Find widths of 2 columns */ @@ -700,19 +699,20 @@ char buffer[XBYTES * NUM_ROWS] = "\0"; if (len1 + len2 < (uint16)strlen(_vm._textParser[kTBOutro])) len1 = strlen(_vm._textParser[kTBOutro]); - strncat (buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); - strcat (strcat (buffer, _vm._textParser[kTBIntro]), "\n"); + strncat(buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); + strcat(strcat(buffer, _vm._textParser[kTBIntro]), "\n"); index = 0; for (int i = 0; i < _vm._numObj; i++) { /* Assign strings */ if (_vm._objects[i].carriedFl) { if (index++ & 1) - strcat (strcat (buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); + strcat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); else - strncat (strcat (buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); + strncat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); } } - if (index & 1) strcat (buffer, "\n"); - strcat (buffer, _vm._textParser[kTBOutro]); + if (index & 1) + strcat(buffer, "\n"); + strcat(buffer, _vm._textParser[kTBOutro]); Utils::Box(BOX_ANY, buffer); } -- cgit v1.2.3 From ec9708694e886746af0d45d30bbf271c2061053f Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Fri, 27 Aug 2010 09:48:53 +0000 Subject: HUGO: Hopefully fix GCC_PRINTF issue in util * Add a mask in each call of Warn(), Error() and Box() not using one * cleanup: use the same wording for 'End of namespace Hugo' in all files svn-id: r52406 --- engines/hugo/parser.cpp | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index ad2b107329..33fd0ddfef 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -304,7 +304,7 @@ void Parser::lineHandler() { // Special meta commands // EXIT/QUIT if (!strcmp("exit", _line) || strstr(_line, "quit")) { - Utils::Box(BOX_ANY, _vm._textParser[kTBExit]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBExit]); return; } @@ -362,7 +362,7 @@ void Parser::lineHandler() { // If a not-near comment was generated, print it if (*farComment != '\0') { - Utils::Box(BOX_ANY, farComment); + Utils::Box(BOX_ANY, "%s", farComment); return; } @@ -370,16 +370,16 @@ void Parser::lineHandler() { verb = findVerb(_line); noun = findNoun(_line); if (verb == _vm._arrayVerbs[_vm._look][0] && _maze.enabledFl) { - Utils::Box(BOX_ANY, _vm._textParser[kTBMaze]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); showTakeables(); } else if (verb && noun) // A combination I didn't think of - Utils::Box(BOX_ANY, _vm._textParser[kTBNoPoint]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoPoint]); else if (noun) - Utils::Box(BOX_ANY, _vm._textParser[kTBNoun]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoun]); else if (verb) - Utils::Box(BOX_ANY, _vm._textParser[kTBVerb]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBVerb]); else - Utils::Box(BOX_ANY, _vm._textParser[kTBEh]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh]); } // Search for matching verb/noun pairs in background command list @@ -392,7 +392,7 @@ bool Parser::isBackgroundWord(objectList_t obj, char *line) { isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && ((obj[i].roomState == DONT_CARE) || (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, _vm.file().fetchString(obj[i].commentIndex)); + Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); _vm.scheduler().processBonus(obj[i].bonusIndex); return true; } @@ -411,7 +411,7 @@ bool Parser::isCatchallVerb(objectList_t obj, char *line) { (!obj[i].matchFl || !findNoun(line)) && ((obj[i].roomState == DONT_CARE) || (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, _vm.file().fetchString(obj[i].commentIndex)); + Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); _vm.scheduler().processBonus(obj[i].bonusIndex); // If this is LOOK (without a noun), show any takeable objects @@ -524,8 +524,8 @@ void Parser::showTakeables() { if ((obj->cycling != INVISIBLE) && (obj->screenIndex == *_vm._screen_p) && (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { - sprintf(_textBoxBuffer, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); - Utils::Box(BOX_ANY, _textBoxBuffer); +// sprintf(_textBoxBuffer, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); + Utils::Box(BOX_ANY, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); } } } @@ -561,7 +561,7 @@ void Parser::dropObject(object_t *obj) { obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; _vm.adjustScore(-obj->objValue); - Utils::Box(BOX_ANY, _vm._textParser[kTBOk]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); } // Test whether command line contains one of the generic actions @@ -575,35 +575,35 @@ bool Parser::isGenericVerb(object_t *obj, char *line, char *comment) { if (isWordPresent(_vm._arrayVerbs[_vm._look]) && isNear(obj, _vm._arrayVerbs[_vm._look][0], comment)) { // Test state-dependent look before general look if ((obj->genericCmd & LOOK_S) == LOOK_S) { - Utils::Box(BOX_ANY, _vm._textData[obj->stateDataIndex[obj->state]]); + Utils::Box(BOX_ANY, "%s", _vm._textData[obj->stateDataIndex[obj->state]]); warning("isGenericVerb: use of state dependant look - To be validated"); } else { if ((LOOK & obj->genericCmd) == LOOK) if (_vm._textData[obj->dataIndex]) - Utils::Box(BOX_ANY, _vm._textData[obj->dataIndex]); + Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); else return(false); else - Utils::Box(BOX_ANY, _vm._textParser[kTBUnusual]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual]); } } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { if (obj->carriedFl) - Utils::Box(BOX_ANY, _vm._textParser[kTBHave]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); else if ((TAKE & obj->genericCmd) == TAKE) takeObject(obj); else if (obj->cmdIndex != 0) // No comment if possible commands return false; else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! - Utils::Box(BOX_ANY, _vm._textParser[kTBNoUse]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); else return false; } else if (isWordPresent(_vm._arrayVerbs[_vm._drop])) { if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - Utils::Box(BOX_ANY, _vm._textParser[kTBDontHave]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) dropObject(obj); else if (obj->cmdIndex == 0) - Utils::Box(BOX_ANY, _vm._textParser[kTBNeed]); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); else return false; } else // It was not a generic cmd @@ -656,21 +656,21 @@ bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects for (i = 0; reqs[i]; i++) // for each obj if (!isCarrying(reqs[i])) { - Utils::Box(BOX_ANY, _vm._textData[cmnd->textDataNoCarryIndex]); + Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); return true; } } // Required objects are present, now check state is correct if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { - Utils::Box(BOX_ANY, _vm._textData[cmnd->textDataWrongIndex]); + Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataWrongIndex]); return true; } // Everything checked. Change the state and carry out any actions if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care obj->state = cmnd->newState; - Utils::Box(BOX_ANY, _vm._textData[cmnd->textDataDoneIndex]); + Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataDoneIndex]); _vm.scheduler().insertActionList(cmnd->actIndex); // See if any additional generic actions @@ -714,8 +714,7 @@ void Parser::showDosInventory() { strcat(buffer, "\n"); strcat(buffer, _vm._textParser[kTBOutro]); - Utils::Box(BOX_ANY, buffer); + Utils::Box(BOX_ANY, "%s", buffer); } - -} // end of namespace Hugo +} // End of namespace Hugo -- cgit v1.2.3 From 597eed026611eeaab6d992308677fa59b4f18908 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 12 Sep 2010 22:59:32 +0000 Subject: HUGO: Use fonts in HUGO.DAT for the DOS version This is only a temporary solution, to be replaced by a proper .FON handling. Hugo 2 and 3 (dos) now start. svn-id: r52697 --- engines/hugo/parser.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 33fd0ddfef..061e8e597d 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -197,8 +197,7 @@ void Parser::charHandler() { void Parser::drawStatusText() { debugC(4, kDebugParser, "drawStatusText"); - if (_vm.getPlatform() == Common::kPlatformWindows) - _vm.screen().loadFont(U_FONT8); + _vm.screen().loadFont(U_FONT8); uint16 sdx = _vm.screen().stringLength(_statusLine); uint16 sdy = _vm.screen().fontHeight() + 1; // + 1 for shadow uint16 posX = 0; -- cgit v1.2.3 From 1e9e8cd64a97ade7d8f9ff891e511d47b98da70d Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Fri, 17 Sep 2010 22:40:53 +0000 Subject: HUGO: Fix crash in the first screen of H1 Dos - Fix crash in the first screen of H1 Dos - Clean up svn-id: r52787 --- engines/hugo/parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 061e8e597d..e4d7364b61 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -266,7 +266,7 @@ void Parser::lineHandler() { // fetch Hero carries named object // fetch all Hero carries all possible objects // find Takes hero to screen containing named object - if (DEBUG || gameStatus.godModeFl) { + if (gameStatus.godModeFl) { // Special code to allow me to go straight to any screen if (strstr(_line, "goto")) for (int i = 0; i < _vm._numScreens; i++) -- cgit v1.2.3 From 3db60d9e441cbf48701d0a0565ac87f6c69b1d15 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Mon, 27 Sep 2010 20:24:36 +0000 Subject: HUGO: Add F3 behavior (recall), little cleanup - Add F3 behavior - Move drawStatusText() to Screen svn-id: r52920 --- engines/hugo/parser.cpp | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index e4d7364b61..c4833c295b 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -98,10 +98,12 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { _vm.sound().toggleMusic(); break; case Common::KEYCODE_F3: // Repeat last line + gameStatus.recallFl = true; + break; case Common::KEYCODE_F4: // Save game case Common::KEYCODE_F5: // Restore game case Common::KEYCODE_F9: // Boss button - warning("STUB: KeyHandler() - F3-F9 (DOS)"); + warning("STUB: KeyHandler() - F4-F5-F9 (DOS)"); break; default: // Any other key if (!gameStatus.storyModeFl) { // Keyboard disabled @@ -184,8 +186,8 @@ void Parser::charHandler() { lineIndex = strlen(cmdLine); } - sprintf(_statusLine, ">%s%c", cmdLine, cursor); - sprintf(_scoreLine, "F1-Help %s Score: %d of %d Sound %s", (_config.turboFl) ? "T" : " ", _vm.getScore(), _vm.getMaxScore(), (_config.soundFl) ? "On" : "Off"); + sprintf(_vm._statusLine, ">%s%c", cmdLine, cursor); + sprintf(_vm._scoreLine, "F1-Help %s Score: %d of %d Sound %s", (_config.turboFl) ? "T" : " ", _vm.getScore(), _vm.getMaxScore(), (_config.soundFl) ? "On" : "Off"); // See if "look" button pressed if (gameStatus.lookFl) { @@ -194,24 +196,6 @@ void Parser::charHandler() { } } -void Parser::drawStatusText() { - debugC(4, kDebugParser, "drawStatusText"); - - _vm.screen().loadFont(U_FONT8); - uint16 sdx = _vm.screen().stringLength(_statusLine); - uint16 sdy = _vm.screen().fontHeight() + 1; // + 1 for shadow - uint16 posX = 0; - uint16 posY = YPIX - sdy; - // Display the string and add rect to display list - _vm.screen().writeStr(posX, posY, _statusLine, _TLIGHTYELLOW); - _vm.screen().displayList(D_ADD, posX, posY, sdx, sdy); - - sdx = _vm.screen().stringLength(_scoreLine); - posY = 0; - _vm.screen().writeStr(posX, posY, _scoreLine, _TCYAN); - _vm.screen().displayList(D_ADD, posX, posY, sdx, sdy); -} - // Perform an immediate command. Takes parameters a la sprintf // Assumes final string will not overrun line[] length void Parser::command(const char *format, ...) { -- cgit v1.2.3 From d46f4a2fc0316e32a300752f5260e463118626e4 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Mon, 27 Sep 2010 21:50:11 +0000 Subject: HUGO: Move strlwr to Utils svn-id: r52921 --- engines/hugo/parser.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index c4833c295b..54f6a7f159 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -199,10 +199,9 @@ void Parser::charHandler() { // Perform an immediate command. Takes parameters a la sprintf // Assumes final string will not overrun line[] length void Parser::command(const char *format, ...) { - va_list marker; - debugC(1, kDebugParser, "Command(%s, ...)", format); + va_list marker; va_start(marker, format); vsprintf(_line, format, marker); va_end(marker); @@ -210,20 +209,6 @@ void Parser::command(const char *format, ...) { lineHandler(); } -char *Parser::strlwr(char *buffer) { - char *result = buffer; - - debugC(1, kDebugParser, "strlwr(%s)", buffer); - - while (*buffer != '\0') { - if (isupper(*buffer)) - *buffer = tolower(*buffer); - buffer++; - } - - return result; -} - // Parse the user's line of text input. Generate events as necessary void Parser::lineHandler() { char *noun, *verb; // ptrs to noun and verb strings @@ -243,7 +228,7 @@ void Parser::lineHandler() { return; } - strlwr(_line); // Convert to lower case + Utils::strlwr(_line); // Convert to lower case // God Mode cheat commands: // goto Takes hero to named screen -- cgit v1.2.3 From 07427bed7476fa050fffcedd100b97e0c0aecda2 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Tue, 28 Sep 2010 19:49:53 +0000 Subject: HUGO: Suppress useless parameter in several functions svn-id: r52933 --- engines/hugo/parser.cpp | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 54f6a7f159..aa7c1d68c3 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -212,7 +212,6 @@ void Parser::command(const char *format, ...) { // Parse the user's line of text input. Generate events as necessary void Parser::lineHandler() { char *noun, *verb; // ptrs to noun and verb strings -// int i; object_t *obj; char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby char contextComment[XBYTES * 5] = ""; // Unused comment for context objects @@ -305,7 +304,7 @@ void Parser::lineHandler() { for (int i = 0; i < _vm._numObj; i++) { obj = &_vm._objects[i]; if (isWordPresent(_vm._arrayNouns[obj->nounIndex])) - if (isObjectVerb(obj, _line, farComment) || isGenericVerb(obj, _line, farComment)) + if (isObjectVerb(obj, farComment) || isGenericVerb(obj, farComment)) return; } @@ -314,18 +313,18 @@ void Parser::lineHandler() { for (int i = 0; i < _vm._numObj; i++) { obj = &_vm._objects[i]; if (obj->verbOnlyFl) - if (isObjectVerb(obj, _line, contextComment) || isGenericVerb(obj, _line, contextComment)) + if (isObjectVerb(obj, contextComment) || isGenericVerb(obj, contextComment)) return; } // No objects match command line, try background and catchall commands - if (isBackgroundWord(_vm._backgroundObjects[*_vm._screen_p], _line)) + if (isBackgroundWord(_vm._backgroundObjects[*_vm._screen_p])) return; - if (isCatchallVerb(_vm._backgroundObjects[*_vm._screen_p], _line)) + if (isCatchallVerb(_vm._backgroundObjects[*_vm._screen_p])) return; - if (isBackgroundWord(_vm._catchallList, _line)) + if (isBackgroundWord(_vm._catchallList)) return; - if (isCatchallVerb(_vm._catchallList, _line)) + if (isCatchallVerb(_vm._catchallList)) return; // If a not-near comment was generated, print it @@ -335,8 +334,8 @@ void Parser::lineHandler() { } // Nothing matches. Report recognition success to user. - verb = findVerb(_line); - noun = findNoun(_line); + verb = findVerb(); + noun = findNoun(); if (verb == _vm._arrayVerbs[_vm._look][0] && _maze.enabledFl) { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); showTakeables(); @@ -352,8 +351,8 @@ void Parser::lineHandler() { // Search for matching verb/noun pairs in background command list // Print text for possible background object. Return TRUE if match found -bool Parser::isBackgroundWord(objectList_t obj, char *line) { - debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj, %s)", line); +bool Parser::isBackgroundWord(objectList_t obj) { + debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); for (int i = 0; obj[i].verbIndex != 0; i++) if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && @@ -371,12 +370,12 @@ bool Parser::isBackgroundWord(objectList_t obj, char *line) { // Noun is not required. Return TRUE if match found // Note that if the background command list has match set TRUE then do not // print text if there are any recognizable nouns in the command line -bool Parser::isCatchallVerb(objectList_t obj, char *line) { - debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj, %s)", line); +bool Parser::isCatchallVerb(objectList_t obj) { + debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); for (int i = 0; obj[i].verbIndex != 0; i++) if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && - (!obj[i].matchFl || !findNoun(line)) && + (!obj[i].matchFl || !findNoun()) && ((obj[i].roomState == DONT_CARE) || (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); @@ -460,23 +459,23 @@ bool Parser::isWordPresent(char **wordArr) { } // Locate word in list of nouns and return ptr to first string in noun list -char *Parser::findNoun(char *line) { - debugC(1, kDebugParser, "findNoun(%s)", line); +char *Parser::findNoun() { + debugC(1, kDebugParser, "findNoun()"); for (int i = 0; _vm._arrayNouns[i]; i++) for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) - if (strstr(line, _vm._arrayNouns[i][j])) + if (strstr(_line, _vm._arrayNouns[i][j])) return(_vm._arrayNouns[i][0]); return NULL; } // Locate word in list of verbs and return ptr to first string in verb list -char *Parser::findVerb(char *line) { - debugC(1, kDebugParser, "findVerb(%s)", line); +char *Parser::findVerb() { + debugC(1, kDebugParser, "findVerb()"); for (int i = 0; _vm._arrayVerbs[i]; i++) for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) - if (strstr(line, _vm._arrayVerbs[i][j])) + if (strstr(_line, _vm._arrayVerbs[i][j])) return(_vm._arrayVerbs[i][0]); return NULL; } @@ -533,8 +532,8 @@ void Parser::dropObject(object_t *obj) { } // Test whether command line contains one of the generic actions -bool Parser::isGenericVerb(object_t *obj, char *line, char *comment) { - debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s, %s)", line, comment); +bool Parser::isGenericVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); if (!obj->genericCmd) return false; @@ -593,14 +592,14 @@ bool Parser::isCarrying(uint16 wordIndex) { // Test whether command line contains a verb allowed by this object. // If it does, and the object is near and passes the tests in the command // list then carry out the actions in the action list and return TRUE -bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { +bool Parser::isObjectVerb(object_t *obj, char *comment) { int i; cmd *cmnd; char *verb; uint16 *reqs; uint16 cmdIndex; - debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s, %s)", line, comment); + debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); // First, find matching verb in cmd list cmdIndex = obj->cmdIndex; // ptr to list of commands @@ -643,7 +642,7 @@ bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { // See if any additional generic actions if ((verb == _vm._arrayVerbs[_vm._look][0]) || (verb == _vm._arrayVerbs[_vm._take][0]) || (verb == _vm._arrayVerbs[_vm._drop][0])) - isGenericVerb(obj, line, comment); + isGenericVerb(obj, comment); return true; } -- cgit v1.2.3 From 694758fd2a0e98513c436e02cdf13d690fe9565d Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 3 Oct 2010 08:08:42 +0000 Subject: HUGO: Clean-up svn-id: r52988 --- engines/hugo/parser.cpp | 197 +++++++++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 96 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index aa7c1d68c3..59fe023788 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -57,11 +57,11 @@ Parser::Parser(HugoEngine &vm) : } void Parser::keyHandler(uint16 nChar, uint16 nFlags) { + debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags); + status_t &gameStatus = _vm.getGameStatus(); bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat - debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags); - // Process key down event - called from OnKeyDown() switch (nChar) { // Set various toggle states case Common::KEYCODE_ESCAPE: // Escape key, may want to QUIT @@ -126,21 +126,17 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { // Add any new chars to line buffer and display them. // If CR pressed, pass line to Line_handler() void Parser::charHandler() { + debugC(4, kDebugParser, "charHandler"); + static int16 lineIndex = 0; // Index into line static uint32 tick = 0; // For flashing cursor static char cursor = '_'; - char c; static command_t cmdLine; // Build command line status_t &gameStatus = _vm.getGameStatus(); -// Strangerke : Useless ? -// bool updateFl = (_getIndex != _putIndex); // TRUE if any chars processed -// command_t status_line; // Includes prompt, cursor - - debugC(4, kDebugParser, "charHandler"); // Check for one or more characters in ring buffer while (_getIndex != _putIndex) { - c = _ringBuffer[_getIndex++]; + char c = _ringBuffer[_getIndex++]; if (_getIndex >= sizeof(_ringBuffer)) _getIndex = 0; @@ -172,11 +168,8 @@ void Parser::charHandler() { } // See if time to blink cursor, set cursor character - if ((tick++ % (TPS / BLINKS)) == 0) { -// Strangerke : Useless ? -// updateFl = true; // Force an update + if ((tick++ % (TPS / BLINKS)) == 0) cursor = (cursor == '_') ? ' ' : '_'; - } // See if recall button pressed if (gameStatus.recallFl) { @@ -211,15 +204,10 @@ void Parser::command(const char *format, ...) { // Parse the user's line of text input. Generate events as necessary void Parser::lineHandler() { - char *noun, *verb; // ptrs to noun and verb strings - object_t *obj; - char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby - char contextComment[XBYTES * 5] = ""; // Unused comment for context objects - status_t &gameStatus = _vm.getGameStatus(); - - debugC(1, kDebugParser, "lineHandler"); + status_t &gameStatus = _vm.getGameStatus(); + // Toggle God Mode if (!strncmp(_line, "PPG", 3)) { _vm.sound().playSound(!_vm._soundTest, BOTH_CHANNELS, HIGH_PRI); @@ -236,36 +224,42 @@ void Parser::lineHandler() { // find Takes hero to screen containing named object if (gameStatus.godModeFl) { // Special code to allow me to go straight to any screen - if (strstr(_line, "goto")) - for (int i = 0; i < _vm._numScreens; i++) + if (strstr(_line, "goto")) { + for (int i = 0; i < _vm._numScreens; i++) { if (!strcmp(&_line[strlen("goto") + 1], _vm._screenNames[i])) { _vm.scheduler().newScreen(i); return; } + } + } // Special code to allow me to get objects from anywhere if (strstr(_line, "fetch all")) { - for (int i = 0; i < _vm._numObj; i++) + for (int i = 0; i < _vm._numObj; i++) { if (_vm._objects[i].genericCmd & TAKE) takeObject(&_vm._objects[i]); + } return; } if (strstr(_line, "fetch")) { - for (int i = 0; i < _vm._numObj; i++) + for (int i = 0; i < _vm._numObj; i++) { if (!strcmp(&_line[strlen("fetch") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { takeObject(&_vm._objects[i]); return; } + } } // Special code to allow me to goto objects - if (strstr(_line, "find")) - for (int i = 0; i < _vm._numObj; i++) + if (strstr(_line, "find")) { + for (int i = 0; i < _vm._numObj; i++) { if (!strcmp(&_line[strlen("find") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { _vm.scheduler().newScreen(_vm._objects[i].screenIndex); return; } + } + } } // Special meta commands @@ -300,21 +294,26 @@ void Parser::lineHandler() { return; } + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + // Test for nearby objects referenced explicitly for (int i = 0; i < _vm._numObj; i++) { - obj = &_vm._objects[i]; - if (isWordPresent(_vm._arrayNouns[obj->nounIndex])) + object_t *obj = &_vm._objects[i]; + if (isWordPresent(_vm._arrayNouns[obj->nounIndex])) { if (isObjectVerb(obj, farComment) || isGenericVerb(obj, farComment)) return; + } } // Test for nearby objects that only require a verb // Note comment is unused if not near. for (int i = 0; i < _vm._numObj; i++) { - obj = &_vm._objects[i]; - if (obj->verbOnlyFl) + object_t *obj = &_vm._objects[i]; + if (obj->verbOnlyFl) { + char contextComment[XBYTES * 5] = ""; // Unused comment for context objects if (isObjectVerb(obj, contextComment) || isGenericVerb(obj, contextComment)) return; + } } // No objects match command line, try background and catchall commands @@ -334,19 +333,20 @@ void Parser::lineHandler() { } // Nothing matches. Report recognition success to user. - verb = findVerb(); - noun = findNoun(); + char *verb = findVerb(); + char *noun = findNoun(); if (verb == _vm._arrayVerbs[_vm._look][0] && _maze.enabledFl) { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); showTakeables(); - } else if (verb && noun) // A combination I didn't think of + } else if (verb && noun) { // A combination I didn't think of Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoPoint]); - else if (noun) + } else if (noun) { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoun]); - else if (verb) + } else if (verb) { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBVerb]); - else + } else { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh]); + } } // Search for matching verb/noun pairs in background command list @@ -354,15 +354,16 @@ void Parser::lineHandler() { bool Parser::isBackgroundWord(objectList_t obj) { debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); - for (int i = 0; obj[i].verbIndex != 0; i++) + for (int i = 0; obj[i].verbIndex != 0; i++) { if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && - isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { + isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); _vm.scheduler().processBonus(obj[i].bonusIndex); return true; } + } return false; } @@ -373,7 +374,7 @@ bool Parser::isBackgroundWord(objectList_t obj) { bool Parser::isCatchallVerb(objectList_t obj) { debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); - for (int i = 0; obj[i].verbIndex != 0; i++) + for (int i = 0; obj[i].verbIndex != 0; i++) { if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && (!obj[i].matchFl || !findNoun()) && ((obj[i].roomState == DONT_CARE) || @@ -385,8 +386,9 @@ bool Parser::isCatchallVerb(objectList_t obj) { if (*(_vm._arrayVerbs[obj[i].verbIndex]) == _vm._arrayVerbs[_vm._look][0]) showTakeables(); - return(true); + return true; } + } return false; } @@ -398,7 +400,7 @@ bool Parser::isNear(object_t *obj, char *verb, char *comment) { debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); if (obj->carriedFl) // Object is being carried - return(true); + return true; if (obj->screenIndex != *_vm._screen_p) { // Not in same screen @@ -406,41 +408,42 @@ bool Parser::isNear(object_t *obj, char *verb, char *comment) { strcpy(comment, _vm._textParser[kCmtAny1]); else strcpy(comment, _vm._textParser[kCmtAny2]); - return(false); + return false; } if (obj->cycling == INVISIBLE) { if (obj->seqNumb) { // There is an image strcpy(comment, _vm._textParser[kCmtAny3]); - return(false); - } else + return false; + } else { // No image, assume visible if ((obj->radius < 0) || ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) - return(true); - else { + (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { // User is not close enough if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) strcpy(comment, _vm._textParser[kCmtAny1]); else strcpy(comment, _vm._textParser[kCmtClose]); - return(false); + return false; } + } } if ((obj->radius < 0) || ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) - return(true); - else { + (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { // User is not close enough if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) strcpy(comment, _vm._textParser[kCmtAny1]); else strcpy(comment, _vm._textParser[kCmtClose]); - return(false); + return false; } return true; } @@ -449,12 +452,12 @@ bool Parser::isNear(object_t *obj, char *verb, char *comment) { bool Parser::isWordPresent(char **wordArr) { debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]); - if (wordArr != NULL) { - for (int i = 0; strlen(wordArr[i]); i++) + if (wordArr != 0) { + for (int i = 0; strlen(wordArr[i]); i++) { if (strstr(_line, wordArr[i])) - return(true); + return true; + } } - return false; } @@ -462,36 +465,37 @@ bool Parser::isWordPresent(char **wordArr) { char *Parser::findNoun() { debugC(1, kDebugParser, "findNoun()"); - for (int i = 0; _vm._arrayNouns[i]; i++) - for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) + for (int i = 0; _vm._arrayNouns[i]; i++) { + for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) { if (strstr(_line, _vm._arrayNouns[i][j])) - return(_vm._arrayNouns[i][0]); - return NULL; + return _vm._arrayNouns[i][0]; + } + } + return 0; } // Locate word in list of verbs and return ptr to first string in verb list char *Parser::findVerb() { debugC(1, kDebugParser, "findVerb()"); - for (int i = 0; _vm._arrayVerbs[i]; i++) - for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) + for (int i = 0; _vm._arrayVerbs[i]; i++) { + for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) { if (strstr(_line, _vm._arrayVerbs[i][j])) - return(_vm._arrayVerbs[i][0]); - return NULL; + return _vm._arrayVerbs[i][0]; + } + } + return 0; } // Describe any takeable objects visible in this screen void Parser::showTakeables() { - object_t *obj; - debugC(1, kDebugParser, "showTakeables"); for (int j = 0; j < _vm._numObj; j++) { - obj = &_vm._objects[j]; + object_t *obj = &_vm._objects[j]; if ((obj->cycling != INVISIBLE) && (obj->screenIndex == *_vm._screen_p) && (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { -// sprintf(_textBoxBuffer, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); Utils::Box(BOX_ANY, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); } } @@ -545,13 +549,14 @@ bool Parser::isGenericVerb(object_t *obj, char *comment) { Utils::Box(BOX_ANY, "%s", _vm._textData[obj->stateDataIndex[obj->state]]); warning("isGenericVerb: use of state dependant look - To be validated"); } else { - if ((LOOK & obj->genericCmd) == LOOK) + if ((LOOK & obj->genericCmd) == LOOK) { if (_vm._textData[obj->dataIndex]) Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); else - return(false); - else + return false; + } else { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual]); + } } } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { if (obj->carriedFl) @@ -573,8 +578,9 @@ bool Parser::isGenericVerb(object_t *obj, char *comment) { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); else return false; - } else // It was not a generic cmd + } else { // It was not a generic cmd return false; + } return true; } @@ -583,9 +589,10 @@ bool Parser::isGenericVerb(object_t *obj, char *comment) { bool Parser::isCarrying(uint16 wordIndex) { debugC(1, kDebugParser, "isCarrying(%d)", wordIndex); - for (int i = 0; i < _vm._numObj; i++) + for (int i = 0; i < _vm._numObj; i++) { if ((wordIndex == _vm._objects[i].nounIndex) && _vm._objects[i].carriedFl) return true; + } return false; } @@ -593,39 +600,37 @@ bool Parser::isCarrying(uint16 wordIndex) { // If it does, and the object is near and passes the tests in the command // list then carry out the actions in the action list and return TRUE bool Parser::isObjectVerb(object_t *obj, char *comment) { - int i; - cmd *cmnd; - char *verb; - uint16 *reqs; - uint16 cmdIndex; - debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); // First, find matching verb in cmd list - cmdIndex = obj->cmdIndex; // ptr to list of commands + uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands if (cmdIndex == 0) // No commands for this obj return false; - for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) // For each cmd + int i; + for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd if (isWordPresent(_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex])) // Was this verb used? break; + } + if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. return false; // Verb match found. Check if object is Near - verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; + char *verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; if (!isNear(obj, verb, comment)) - return(false); + return false; // Check all required objects are being carried - cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd + cmd *cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd if (cmnd->reqIndex) { // At least 1 thing in list - reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects - for (i = 0; reqs[i]; i++) // for each obj + uint16 *reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + for (i = 0; reqs[i]; i++) { // for each obj if (!isCarrying(reqs[i])) { Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); return true; } + } } // Required objects are present, now check state is correct @@ -649,27 +654,27 @@ bool Parser::isObjectVerb(object_t *obj, char *comment) { void Parser::showDosInventory() { // Show user all objects being carried in a variable width 2 column format static const char *blanks = " "; - uint16 index, len, len1 = 0, len2 = 0; - char buffer[XBYTES *NUM_ROWS] = "\0"; + uint16 index = 0, len1 = 0, len2 = 0; - index = 0; - for (int i = 0; i < _vm._numObj; i++) /* Find widths of 2 columns */ + for (int i = 0; i < _vm._numObj; i++) { // Find widths of 2 columns if (_vm._objects[i].carriedFl) { - len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); - if (index++ & 1) /* Right hand column */ + uint16 len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); + if (index++ & 1) // Right hand column len2 = (len > len2) ? len : len2; else len1 = (len > len1) ? len : len1; } - len1 += 1; /* For gap between columns */ + } + len1 += 1; // For gap between columns if (len1 + len2 < (uint16)strlen(_vm._textParser[kTBOutro])) len1 = strlen(_vm._textParser[kTBOutro]); + char buffer[XBYTES *NUM_ROWS] = "\0"; strncat(buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); strcat(strcat(buffer, _vm._textParser[kTBIntro]), "\n"); index = 0; - for (int i = 0; i < _vm._numObj; i++) { /* Assign strings */ + for (int i = 0; i < _vm._numObj; i++) { // Assign strings if (_vm._objects[i].carriedFl) { if (index++ & 1) strcat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); -- cgit v1.2.3 From ced1aba1eac0e8e7891ad44f09ff0877a4fbb3da Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 10 Oct 2010 07:43:42 +0000 Subject: HUGO: New parser for H1 Dos and H2 Dos. Add specific parser functions for H1 Dos and H2 Dos svn-id: r53106 --- engines/hugo/parser.cpp | 816 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 598 insertions(+), 218 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 59fe023788..a232e9df96 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -56,6 +56,9 @@ Parser::Parser(HugoEngine &vm) : _vm(vm), _putIndex(0), _getIndex(0), _checkDoubleF1Fl(false) { } +Parser::~Parser() { +} + void Parser::keyHandler(uint16 nChar, uint16 nFlags) { debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags); @@ -202,8 +205,218 @@ void Parser::command(const char *format, ...) { lineHandler(); } +Parser_v1w::Parser_v1w(HugoEngine &vm) : Parser(vm) { +} + +Parser_v1w::~Parser_v1w() { +} + +// Test whether command line contains a verb allowed by this object. +// If it does, and the object is near and passes the tests in the command +// list then carry out the actions in the action list and return TRUE +bool Parser_v1w::isObjectVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); + + // First, find matching verb in cmd list + uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands + if (cmdIndex == 0) // No commands for this obj + return false; + + int i; + for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (isWordPresent(_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex])) // Was this verb used? + break; + } + + if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. + return false; + + // Verb match found. Check if object is Near + char *verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; + if (!isNear(obj, verb, comment)) + return false; + + // Check all required objects are being carried + cmd *cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd + if (cmnd->reqIndex) { // At least 1 thing in list + uint16 *reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + for (i = 0; reqs[i]; i++) { // for each obj + if (!isCarrying(reqs[i])) { + Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); + return true; + } + } + } + + // Required objects are present, now check state is correct + if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { + Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataWrongIndex]); + return true; + } + + // Everything checked. Change the state and carry out any actions + if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care + obj->state = cmnd->newState; + Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataDoneIndex]); + _vm.scheduler().insertActionList(cmnd->actIndex); + + // See if any additional generic actions + if ((verb == _vm._arrayVerbs[_vm._look][0]) || (verb == _vm._arrayVerbs[_vm._take][0]) || (verb == _vm._arrayVerbs[_vm._drop][0])) + isGenericVerb(obj, comment); + return true; +} + +// Test whether command line contains one of the generic actions +bool Parser_v1w::isGenericVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); + + if (!obj->genericCmd) + return false; + + // Following is equivalent to switch, but couldn't do one + if (isWordPresent(_vm._arrayVerbs[_vm._look]) && isNear(obj, _vm._arrayVerbs[_vm._look][0], comment)) { + // Test state-dependent look before general look + if ((obj->genericCmd & LOOK_S) == LOOK_S) { + Utils::Box(BOX_ANY, "%s", _vm._textData[obj->stateDataIndex[obj->state]]); + warning("isGenericVerb: use of state dependant look - To be validated"); + } else { + if ((LOOK & obj->genericCmd) == LOOK) { + if (_vm._textData[obj->dataIndex]) + Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); + else + return false; + } else { + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual]); + } + } + } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { + if (obj->carriedFl) + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); + else if ((TAKE & obj->genericCmd) == TAKE) + takeObject(obj); + else if (obj->cmdIndex != 0) // No comment if possible commands + return false; + else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); + else + return false; + } else if (isWordPresent(_vm._arrayVerbs[_vm._drop])) { + if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); + else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + dropObject(obj); + else if (obj->cmdIndex == 0) + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); + else + return false; + } else { // It was not a generic cmd + return false; + } + + return true; +} + +// Test whether hero is close to object. Return TRUE or FALSE +// If object not near, return suitable comment; may be another object close +// If radius is -1, treat radius as infinity +// Verb is included to determine correct comment if not near +bool Parser_v1w::isNear(object_t *obj, char *verb, char *comment) { + debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); + + if (obj->carriedFl) // Object is being carried + return true; + + if (obj->screenIndex != *_vm._screen_p) { + // Not in same screen + if (obj->objValue) + strcpy(comment, _vm._textParser[kCmtAny1]); + else + strcpy(comment, _vm._textParser[kCmtAny2]); + return false; + } + + if (obj->cycling == INVISIBLE) { + if (obj->seqNumb) { + // There is an image + strcpy(comment, _vm._textParser[kCmtAny3]); + return false; + } else { + // No image, assume visible + if ((obj->radius < 0) || + ((abs(obj->x - _vm._hero->x) <= obj->radius) && + (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is not close enough + if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) + strcpy(comment, _vm._textParser[kCmtAny1]); + else + strcpy(comment, _vm._textParser[kCmtClose]); + return false; + } + } + } + + if ((obj->radius < 0) || + ((abs(obj->x - _vm._hero->x) <= obj->radius) && + (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is not close enough + if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) + strcpy(comment, _vm._textParser[kCmtAny1]); + else + strcpy(comment, _vm._textParser[kCmtClose]); + return false; + } + return true; +} + +// Search for matching verbs in background command list. +// Noun is not required. Return TRUE if match found +// Note that if the background command list has match set TRUE then do not +// print text if there are any recognizable nouns in the command line +bool Parser_v1w::isCatchallVerb(objectList_t obj) { + debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); + + for (int i = 0; obj[i].verbIndex != 0; i++) { + if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && + (!obj[i].matchFl || !findNoun()) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { + Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); + _vm.scheduler().processBonus(obj[i].bonusIndex); + + // If this is LOOK (without a noun), show any takeable objects + if (*(_vm._arrayVerbs[obj[i].verbIndex]) == _vm._arrayVerbs[_vm._look][0]) + showTakeables(); + + return true; + } + } + return false; +} + +// Search for matching verb/noun pairs in background command list +// Print text for possible background object. Return TRUE if match found +bool Parser_v1w::isBackgroundWord(objectList_t obj) { + debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); + + for (int i = 0; obj[i].verbIndex != 0; i++) { + if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && + isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { + Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); + _vm.scheduler().processBonus(obj[i].bonusIndex); + return true; + } + } + return false; +} + // Parse the user's line of text input. Generate events as necessary -void Parser::lineHandler() { +void Parser_v1w::lineHandler() { debugC(1, kDebugParser, "lineHandler"); status_t &gameStatus = _vm.getGameStatus(); @@ -349,142 +562,43 @@ void Parser::lineHandler() { } } -// Search for matching verb/noun pairs in background command list -// Print text for possible background object. Return TRUE if match found -bool Parser::isBackgroundWord(objectList_t obj) { - debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); +// Locate any member of object name list appearing in command line +bool Parser::isWordPresent(char **wordArr) { + debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]); - for (int i = 0; obj[i].verbIndex != 0; i++) { - if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && - isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - _vm.scheduler().processBonus(obj[i].bonusIndex); - return true; + if (wordArr != 0) { + for (int i = 0; strlen(wordArr[i]); i++) { + if (strstr(_line, wordArr[i])) + return true; } } return false; } -// Search for matching verbs in background command list. -// Noun is not required. Return TRUE if match found -// Note that if the background command list has match set TRUE then do not -// print text if there are any recognizable nouns in the command line -bool Parser::isCatchallVerb(objectList_t obj) { - debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); +// Locate word in list of nouns and return ptr to first string in noun list +char *Parser::findNoun() { + debugC(1, kDebugParser, "findNoun()"); - for (int i = 0; obj[i].verbIndex != 0; i++) { - if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && - (!obj[i].matchFl || !findNoun()) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - _vm.scheduler().processBonus(obj[i].bonusIndex); + for (int i = 0; _vm._arrayNouns[i]; i++) { + for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) { + if (strstr(_line, _vm._arrayNouns[i][j])) + return _vm._arrayNouns[i][0]; + } + } + return 0; +} - // If this is LOOK (without a noun), show any takeable objects - if (*(_vm._arrayVerbs[obj[i].verbIndex]) == _vm._arrayVerbs[_vm._look][0]) - showTakeables(); +// Locate word in list of verbs and return ptr to first string in verb list +char *Parser::findVerb() { + debugC(1, kDebugParser, "findVerb()"); - return true; + for (int i = 0; _vm._arrayVerbs[i]; i++) { + for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) { + if (strstr(_line, _vm._arrayVerbs[i][j])) + return _vm._arrayVerbs[i][0]; } } - return false; -} - -// Test whether hero is close to object. Return TRUE or FALSE -// If object not near, return suitable comment; may be another object close -// If radius is -1, treat radius as infinity -// Verb is included to determine correct comment if not near -bool Parser::isNear(object_t *obj, char *verb, char *comment) { - debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); - - if (obj->carriedFl) // Object is being carried - return true; - - if (obj->screenIndex != *_vm._screen_p) { - // Not in same screen - if (obj->objValue) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtAny2]); - return false; - } - - if (obj->cycling == INVISIBLE) { - if (obj->seqNumb) { - // There is an image - strcpy(comment, _vm._textParser[kCmtAny3]); - return false; - } else { - // No image, assume visible - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is not close enough - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - return false; - } - } - } - - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is not close enough - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - return false; - } - return true; -} - -// Locate any member of object name list appearing in command line -bool Parser::isWordPresent(char **wordArr) { - debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]); - - if (wordArr != 0) { - for (int i = 0; strlen(wordArr[i]); i++) { - if (strstr(_line, wordArr[i])) - return true; - } - } - return false; -} - -// Locate word in list of nouns and return ptr to first string in noun list -char *Parser::findNoun() { - debugC(1, kDebugParser, "findNoun()"); - - for (int i = 0; _vm._arrayNouns[i]; i++) { - for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) { - if (strstr(_line, _vm._arrayNouns[i][j])) - return _vm._arrayNouns[i][0]; - } - } - return 0; -} - -// Locate word in list of verbs and return ptr to first string in verb list -char *Parser::findVerb() { - debugC(1, kDebugParser, "findVerb()"); - - for (int i = 0; _vm._arrayVerbs[i]; i++) { - for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) { - if (strstr(_line, _vm._arrayVerbs[i][j])) - return _vm._arrayVerbs[i][0]; - } - } - return 0; + return 0; } // Describe any takeable objects visible in this screen @@ -494,8 +608,8 @@ void Parser::showTakeables() { for (int j = 0; j < _vm._numObj; j++) { object_t *obj = &_vm._objects[j]; if ((obj->cycling != INVISIBLE) && - (obj->screenIndex == *_vm._screen_p) && - (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { + (obj->screenIndex == *_vm._screen_p) && + (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { Utils::Box(BOX_ANY, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); } } @@ -535,49 +649,168 @@ void Parser::dropObject(object_t *obj) { Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); } -// Test whether command line contains one of the generic actions -bool Parser::isGenericVerb(object_t *obj, char *comment) { - debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); +// Return TRUE if object being carried by hero +bool Parser::isCarrying(uint16 wordIndex) { + debugC(1, kDebugParser, "isCarrying(%d)", wordIndex); - if (!obj->genericCmd) + for (int i = 0; i < _vm._numObj; i++) { + if ((wordIndex == _vm._objects[i].nounIndex) && _vm._objects[i].carriedFl) + return true; + } + return false; +} + +void Parser::showDosInventory() { +// Show user all objects being carried in a variable width 2 column format + static const char *blanks = " "; + uint16 index = 0, len1 = 0, len2 = 0; + + for (int i = 0; i < _vm._numObj; i++) { // Find widths of 2 columns + if (_vm._objects[i].carriedFl) { + uint16 len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); + if (index++ & 1) // Right hand column + len2 = (len > len2) ? len : len2; + else + len1 = (len > len1) ? len : len1; + } + } + len1 += 1; // For gap between columns + + if (len1 + len2 < (uint16)strlen(_vm._textParser[kTBOutro])) + len1 = strlen(_vm._textParser[kTBOutro]); + + char buffer[XBYTES *NUM_ROWS] = "\0"; + strncat(buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); + strcat(strcat(buffer, _vm._textParser[kTBIntro]), "\n"); + index = 0; + for (int i = 0; i < _vm._numObj; i++) { // Assign strings + if (_vm._objects[i].carriedFl) { + if (index++ & 1) + strcat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); + else + strncat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); + } + } + if (index & 1) + strcat(buffer, "\n"); + strcat(buffer, _vm._textParser[kTBOutro]); + + Utils::Box(BOX_ANY, "%s", buffer); +} + +Parser_v1d::Parser_v1d(HugoEngine &vm) : Parser(vm) { +} + +Parser_v1d::~Parser_v1d() { +} + +// Locate word in list of nouns and return ptr to string in noun list +// If n is NULL, start at beginning of list, else with n +char *Parser_v1d::findNextNoun(char *n) { + int k = -1; + if (n) { // If n not NULL, find index + for (k = 0; _vm._arrayNouns[k]; k++) { + if (n == _vm._arrayNouns[k][0]) + break; + } + } + for (int i = k + 1; _vm._arrayNouns[i]; i++) { + for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) { + if (strstr(_line, _vm._arrayNouns[i][j])) + return _vm._arrayNouns[i][0]; + } + } + return 0; +} + +// Test whether hero is close to object. Return TRUE or FALSE +// If no noun specified, check context flag in object before other tests. +// If object not near, return suitable string; may be similar object closer +// If radius is -1, treat radius as infinity +bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { + if (!noun && !obj->verbOnlyFl) { // No noun specified & object not context senesitive + return false; + } else if (noun && (noun != _vm._arrayNouns[obj->nounIndex][0])) { // Noun specified & not same as object + return false; + } else if (obj->carriedFl) { // Object is being carried + return true; + } else if (obj->screenIndex != *_vm._screen_p) { // Not in same screen + if (obj->objValue) + strcpy (comment, "You don't have it!"); return false; + } - // Following is equivalent to switch, but couldn't do one - if (isWordPresent(_vm._arrayVerbs[_vm._look]) && isNear(obj, _vm._arrayVerbs[_vm._look][0], comment)) { - // Test state-dependent look before general look - if ((obj->genericCmd & LOOK_S) == LOOK_S) { - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->stateDataIndex[obj->state]]); - warning("isGenericVerb: use of state dependant look - To be validated"); - } else { - if ((LOOK & obj->genericCmd) == LOOK) { - if (_vm._textData[obj->dataIndex]) - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); - else - return false; + if (obj->cycling == INVISIBLE) { + if (obj->seqNumb) { // There is an image + strcpy(comment, "I don't see it anywhere"); + return false; + } else { // No image, assume visible + if ((obj->radius < 0) || + ((abs(obj->x - _vm._hero->x) <= obj->radius) && + (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { + return true; } else { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual]); + // User is either not close enough (stationary, valueless objects) + // or is not carrying it (small, portable objects of value) + if (noun) { // Don't say unless object specified + if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) + strcpy(comment, "You don't have it!"); + else + strcpy(comment, "You're not close enough!"); + } + return false; } } - } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { + } + + if ((obj->radius < 0) || + ((abs(obj->x - _vm._hero->x) <= obj->radius) && + (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is either not close enough (stationary, valueless objects) + // or is not carrying it (small, portable objects of value) + if (noun) { // Don't say unless object specified + if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) + strcpy(comment, "You don't have it!"); + else + strcpy(comment, "You're not close enough!"); + } + return false; + } + + return true; +} + +// Test whether supplied verb is one of the common variety for this object +// say_ok needed for special case of take/drop which may be handled not only +// here but also in a cmd_list with a donestr string simultaneously +bool Parser_v1d::isGenericVerb(char *word, object_t *obj) { + if (!obj->genericCmd) + return false; + + // Following is equivalent to switch, but couldn't do one + if (word == _vm._arrayVerbs[_vm._look][0]) { + if ((LOOK & obj->genericCmd) == LOOK) + Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); + else + Utils::Box(BOX_ANY, "I see nothing special about it"); + } else if (word == _vm._arrayVerbs[_vm._take][0]) { if (obj->carriedFl) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); + Utils::Box(BOX_ANY, "You already have it"); else if ((TAKE & obj->genericCmd) == TAKE) takeObject(obj); - else if (obj->cmdIndex != 0) // No comment if possible commands - return false; - else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); + else if (!obj->verbOnlyFl) // Make sure not taking object in context! + Utils::Box(BOX_ANY, "It is of no use to you"); else return false; - } else if (isWordPresent(_vm._arrayVerbs[_vm._drop])) { - if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); - else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + } else if (word == _vm._arrayVerbs[_vm._drop][0]) { + if (!obj->carriedFl) + Utils::Box(BOX_ANY, "You don't have it"); + else if ((DROP & obj->genericCmd) == DROP) dropObject(obj); - else if (obj->cmdIndex == 0) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); else - return false; + Utils::Box(BOX_ANY, "No! You'll be needing it"); } else { // It was not a generic cmd return false; } @@ -585,46 +818,31 @@ bool Parser::isGenericVerb(object_t *obj, char *comment) { return true; } -// Return TRUE if object being carried by hero -bool Parser::isCarrying(uint16 wordIndex) { - debugC(1, kDebugParser, "isCarrying(%d)", wordIndex); - - for (int i = 0; i < _vm._numObj; i++) { - if ((wordIndex == _vm._objects[i].nounIndex) && _vm._objects[i].carriedFl) - return true; - } - return false; -} - -// Test whether command line contains a verb allowed by this object. -// If it does, and the object is near and passes the tests in the command -// list then carry out the actions in the action list and return TRUE -bool Parser::isObjectVerb(object_t *obj, char *comment) { - debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); +// Test whether supplied verb is included in the list of allowed verbs for +// this object. If it is, then perform the tests on it from the cmd list +// and if it passes, perform the actions in the action list. If the verb +// is catered for, return TRUE +bool Parser_v1d::isObjectVerb(char *word, object_t *obj) { +//actlist *actions; // First, find matching verb in cmd list uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands - if (cmdIndex == 0) // No commands for this obj + if (!cmdIndex) // No commands for this obj return false; int i; - for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd - if (isWordPresent(_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex])) // Was this verb used? + for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (!strcmp(word, _vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex][0])) // Is this verb catered for? break; } - if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. - return false; - - // Verb match found. Check if object is Near - char *verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; - if (!isNear(obj, verb, comment)) + if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No return false; - // Check all required objects are being carried + // Verb match found, check all required objects are being carried cmd *cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd if (cmnd->reqIndex) { // At least 1 thing in list - uint16 *reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + uint16 *reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects for (i = 0; reqs[i]; i++) { // for each obj if (!isCarrying(reqs[i])) { Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); @@ -634,7 +852,7 @@ bool Parser::isObjectVerb(object_t *obj, char *comment) { } // Required objects are present, now check state is correct - if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { + if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)){ Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataWrongIndex]); return true; } @@ -644,49 +862,211 @@ bool Parser::isObjectVerb(object_t *obj, char *comment) { obj->state = cmnd->newState; Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataDoneIndex]); _vm.scheduler().insertActionList(cmnd->actIndex); - - // See if any additional generic actions - if ((verb == _vm._arrayVerbs[_vm._look][0]) || (verb == _vm._arrayVerbs[_vm._take][0]) || (verb == _vm._arrayVerbs[_vm._drop][0])) - isGenericVerb(obj, comment); + // Special case if verb is Take or Drop. Assume additional generic actions + if ((word == _vm._arrayVerbs[_vm._take][0]) || (word == _vm._arrayVerbs[_vm._drop][0])) + isGenericVerb(word, obj); return true; } -void Parser::showDosInventory() { -// Show user all objects being carried in a variable width 2 column format - static const char *blanks = " "; - uint16 index = 0, len1 = 0, len2 = 0; +// Print text for possible background object. Return TRUE if match found +// Only match if both verb and noun found. Test_ca will match verb-only +bool Parser_v1d::isBackgroundWord(char *noun, char *verb, objectList_t obj) { + if (!noun) + return false; - for (int i = 0; i < _vm._numObj; i++) { // Find widths of 2 columns - if (_vm._objects[i].carriedFl) { - uint16 len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); - if (index++ & 1) // Right hand column - len2 = (len > len2) ? len : len2; - else - len1 = (len > len1) ? len : len1; + for (int i = 0; obj[i].verbIndex; i++) { + if ((verb == _vm._arrayVerbs[obj[i].verbIndex][0]) && (noun == _vm._arrayNouns[obj[i].nounIndex][0])) { + Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); + return true; } } - len1 += 1; // For gap between columns + return false; +} - if (len1 + len2 < (uint16)strlen(_vm._textParser[kTBOutro])) - len1 = strlen(_vm._textParser[kTBOutro]); +// Print text for possible background object. Return TRUE if match found +// If test_noun TRUE, must have a noun given +bool Parser_v1d::isCatchallVerb(bool test_noun, char *noun, char *verb, objectList_t obj) { + if (test_noun && !noun) + return false; - char buffer[XBYTES *NUM_ROWS] = "\0"; - strncat(buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); - strcat(strcat(buffer, _vm._textParser[kTBIntro]), "\n"); - index = 0; - for (int i = 0; i < _vm._numObj; i++) { // Assign strings - if (_vm._objects[i].carriedFl) { - if (index++ & 1) - strcat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); - else - strncat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); + for (int i = 0; obj[i].verbIndex; i++) { + if ((verb == _vm._arrayVerbs[obj[i].verbIndex][0]) && ((noun == _vm._arrayNouns[obj[i].nounIndex][0]) || (obj[i].nounIndex == 0))) { + Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); + return true; } } - if (index & 1) - strcat(buffer, "\n"); - strcat(buffer, _vm._textParser[kTBOutro]); + return false; +} - Utils::Box(BOX_ANY, "%s", buffer); +// Parse the user's line of text input. Generate events as necessary +void Parser_v1d::lineHandler() { + object_t *obj; + status_t &gameStatus = _vm.getGameStatus(); + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + +// Reset_prompt_line (); + Utils::strlwr(_line); // Convert to lower case + + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + if (Utils::Box(BOX_YESNO, "Are you sure you want to QUIT?") != 0) + _vm.endGame(); + else + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line)) { + _config.soundFl = false; + if (gameStatus.gameOverFl) + Utils::gameOverMsg(); + else +// _vm.file().saveOrRestore(true); + warning("STUB: saveOrRestore()"); + return; + } + + if (!strcmp("restore", _line)) { + _config.soundFl = false; +// _vm.file().saveOrRestore(false); + warning("STUB: saveOrRestore()"); + return; + } + + if (*_line == '\0') // Empty line + return; + + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { // No commands allowed! + Utils::gameOverMsg(); + return; + } + + // Find the first verb in the line + char *verb = findVerb(); + char *noun = 0; // Noun not found yet + + if (verb) { // OK, verb found. Try to match with object + do { + noun = findNextNoun(noun); // Find a noun in the line + // Must try at least once for objects allowing verb-context + for (int i = 0; i < _vm._numObj; i++) { + obj = &_vm._objects[i]; + if (isNear(verb, noun, obj, farComment)) { + if (isObjectVerb(verb, obj) // Foreground object + || isGenericVerb(verb, obj)) // Common action type + return; + } + } + if ((*farComment == '\0') && isBackgroundWord(noun, verb, _vm._backgroundObjects[*_vm._screen_p])) + return; + } while (noun); + } + noun = findNextNoun(noun); + if (*farComment != '\0') // An object matched but not near enough + Utils::Box(BOX_ANY, "%s", farComment); + else if (!isCatchallVerb(true, noun, verb, _vm._catchallList) && + !isCatchallVerb(false, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) && + !isCatchallVerb(false, noun, verb, _vm._catchallList)) + Utils::Box(BOX_ANY, "Apparently our hero either doesn't\n" + "understand what you mean or doesn't\n" + "think that would be very useful!"); +} + +Parser_v2d::Parser_v2d(HugoEngine &vm) : Parser_v1d(vm) { +} + +Parser_v2d::~Parser_v2d() { +} + +// Parse the user's line of text input. Generate events as necessary +void Parser_v2d::lineHandler() { + object_t *obj; + status_t &gameStatus = _vm.getGameStatus(); + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + +// Reset_prompt_line (); + Utils::strlwr(_line); // Convert to lower case + + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + if (Utils::Box(BOX_YESNO, "Are you sure you want to QUIT?") != 0) + _vm.endGame(); + else + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line)) { + _config.soundFl = false; + if (gameStatus.gameOverFl) + Utils::gameOverMsg(); + else +// _vm.file().saveOrRestore(true); + warning("STUB: saveOrRestore()"); + return; + } + + if (!strcmp("restore", _line)) { + _config.soundFl = false; +// _vm.file().saveOrRestore(false); + warning("STUB: saveOrRestore()"); + return; + } + + if (!strlen(_line)) // Empty line + return; + + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { // No commands allowed! + Utils::gameOverMsg(); + return; + } + + // Find the first verb in the line + char *verb = findVerb(); + char *noun = 0; // Noun not found yet + + if (verb) { // OK, verb found. Try to match with object + do { + noun = findNextNoun(noun); // Find a noun in the line + // Must try at least once for objects allowing verb-context + for (int i = 0; i < _vm._numObj; i++) { + obj = &_vm._objects[i]; + if (isNear(verb, noun, obj, farComment)) { + if (isObjectVerb(verb, obj) // Foreground object + || isGenericVerb(verb, obj)) // Common action type + return; + } + } + if ((*farComment != '\0') && isBackgroundWord(noun, verb, _vm._backgroundObjects[*_vm._screen_p])) + return; + } while (noun); + } + + noun = findNextNoun(noun); + if ( !isCatchallVerb(true, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) + && !isCatchallVerb(true, noun, verb, _vm._catchallList) + && !isCatchallVerb(false, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) + && !isCatchallVerb(false, noun, verb, _vm._catchallList)) { + if (*farComment != '\0') { // An object matched but not near enough + Utils::Box(BOX_ANY, "%s", farComment); + } else if (_maze.enabledFl && (verb == _vm._arrayVerbs[_vm._look][0])) { + Utils::Box(BOX_ANY, "You are in a maze of\n" + "twisty little paths,\n" + "which are all alike!"); + showTakeables(); + } else if (verb && noun) { // A combination I didn't think of + Utils::Box(BOX_ANY, "I don't think that would\n" + "accomplish much, somehow!"); + } else if (verb || noun) { + Utils::Box(BOX_ANY, "I don't fully understand!"); + } else { + Utils::Box(BOX_ANY, "I find that befuddling!"); + } + } } } // End of namespace Hugo -- cgit v1.2.3 From a4c16f7447103c3264d1d4fd1ae3f980e242e604 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 10 Oct 2010 09:47:19 +0000 Subject: HUGO: Move Dos strings from Parser to hugo.dat svn-id: r53109 --- engines/hugo/parser.cpp | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index a232e9df96..fae5dcf350 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -736,13 +736,13 @@ bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { return true; } else if (obj->screenIndex != *_vm._screen_p) { // Not in same screen if (obj->objValue) - strcpy (comment, "You don't have it!"); + strcpy (comment, _vm._textParser[kCmtAny4]); return false; } if (obj->cycling == INVISIBLE) { if (obj->seqNumb) { // There is an image - strcpy(comment, "I don't see it anywhere"); + strcpy(comment, _vm._textParser[kCmtAny5]); return false; } else { // No image, assume visible if ((obj->radius < 0) || @@ -754,10 +754,10 @@ bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { // or is not carrying it (small, portable objects of value) if (noun) { // Don't say unless object specified if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, "You don't have it!"); + strcpy(comment, _vm._textParser[kCmtAny4]); else - strcpy(comment, "You're not close enough!"); - } + strcpy(comment, _vm._textParser[kCmtClose]); + } return false; } } @@ -772,9 +772,9 @@ bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { // or is not carrying it (small, portable objects of value) if (noun) { // Don't say unless object specified if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, "You don't have it!"); + strcpy(comment, _vm._textParser[kCmtAny4]); else - strcpy(comment, "You're not close enough!"); + strcpy(comment, _vm._textParser[kCmtClose]); } return false; } @@ -794,23 +794,23 @@ bool Parser_v1d::isGenericVerb(char *word, object_t *obj) { if ((LOOK & obj->genericCmd) == LOOK) Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); else - Utils::Box(BOX_ANY, "I see nothing special about it"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual_1d]); } else if (word == _vm._arrayVerbs[_vm._take][0]) { if (obj->carriedFl) - Utils::Box(BOX_ANY, "You already have it"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); else if ((TAKE & obj->genericCmd) == TAKE) takeObject(obj); else if (!obj->verbOnlyFl) // Make sure not taking object in context! - Utils::Box(BOX_ANY, "It is of no use to you"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); else return false; } else if (word == _vm._arrayVerbs[_vm._drop][0]) { if (!obj->carriedFl) - Utils::Box(BOX_ANY, "You don't have it"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); else if ((DROP & obj->genericCmd) == DROP) dropObject(obj); else - Utils::Box(BOX_ANY, "No! You'll be needing it"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); } else { // It was not a generic cmd return false; } @@ -908,7 +908,7 @@ void Parser_v1d::lineHandler() { Utils::strlwr(_line); // Convert to lower case if (!strcmp("exit", _line) || strstr(_line, "quit")) { - if (Utils::Box(BOX_YESNO, "Are you sure you want to QUIT?") != 0) + if (Utils::Box(BOX_YESNO, "%s", _vm._textParser[kTBExit_1d]) != 0) _vm.endGame(); else return; @@ -969,9 +969,7 @@ void Parser_v1d::lineHandler() { else if (!isCatchallVerb(true, noun, verb, _vm._catchallList) && !isCatchallVerb(false, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) && !isCatchallVerb(false, noun, verb, _vm._catchallList)) - Utils::Box(BOX_ANY, "Apparently our hero either doesn't\n" - "understand what you mean or doesn't\n" - "think that would be very useful!"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh_1d]); } Parser_v2d::Parser_v2d(HugoEngine &vm) : Parser_v1d(vm) { @@ -990,7 +988,7 @@ void Parser_v2d::lineHandler() { Utils::strlwr(_line); // Convert to lower case if (!strcmp("exit", _line) || strstr(_line, "quit")) { - if (Utils::Box(BOX_YESNO, "Are you sure you want to QUIT?") != 0) + if (Utils::Box(BOX_YESNO, "%s", _vm._textParser[kTBExit_1d]) != 0) _vm.endGame(); else return; @@ -1054,17 +1052,14 @@ void Parser_v2d::lineHandler() { if (*farComment != '\0') { // An object matched but not near enough Utils::Box(BOX_ANY, "%s", farComment); } else if (_maze.enabledFl && (verb == _vm._arrayVerbs[_vm._look][0])) { - Utils::Box(BOX_ANY, "You are in a maze of\n" - "twisty little paths,\n" - "which are all alike!"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); showTakeables(); } else if (verb && noun) { // A combination I didn't think of - Utils::Box(BOX_ANY, "I don't think that would\n" - "accomplish much, somehow!"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse_2d]); } else if (verb || noun) { - Utils::Box(BOX_ANY, "I don't fully understand!"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoun]); } else { - Utils::Box(BOX_ANY, "I find that befuddling!"); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh_2d]); } } } -- cgit v1.2.3 From c50a149a35c7ad5d9e4c8aa8a7d2382506caa51c Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 10 Oct 2010 09:59:40 +0000 Subject: HUGO: Remove sound off when saving svn-id: r53110 --- engines/hugo/parser.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index fae5dcf350..9468ffbe54 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -916,7 +916,6 @@ void Parser_v1d::lineHandler() { // SAVE/RESTORE if (!strcmp("save", _line)) { - _config.soundFl = false; if (gameStatus.gameOverFl) Utils::gameOverMsg(); else @@ -926,7 +925,6 @@ void Parser_v1d::lineHandler() { } if (!strcmp("restore", _line)) { - _config.soundFl = false; // _vm.file().saveOrRestore(false); warning("STUB: saveOrRestore()"); return; -- cgit v1.2.3 From 440bcaa06034244dc00715bb20afc0b3205aedbc Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 10 Oct 2010 13:06:48 +0000 Subject: HUGO: Fix 'Exit' command behavior in the DOS versions svn-id: r53116 --- engines/hugo/parser.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 9468ffbe54..a680baf49c 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -910,8 +910,7 @@ void Parser_v1d::lineHandler() { if (!strcmp("exit", _line) || strstr(_line, "quit")) { if (Utils::Box(BOX_YESNO, "%s", _vm._textParser[kTBExit_1d]) != 0) _vm.endGame(); - else - return; + return; } // SAVE/RESTORE -- cgit v1.2.3 From 9c56271839dc6100be45bed9f75f5c67ec046907 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 10 Oct 2010 20:13:59 +0000 Subject: HUGO: Add debug channels to new parser functions svn-id: r53128 --- engines/hugo/parser.cpp | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index a680baf49c..300bd319d6 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -417,7 +417,7 @@ bool Parser_v1w::isBackgroundWord(objectList_t obj) { // Parse the user's line of text input. Generate events as necessary void Parser_v1w::lineHandler() { - debugC(1, kDebugParser, "lineHandler"); + debugC(1, kDebugParser, "lineHandler()"); status_t &gameStatus = _vm.getGameStatus(); @@ -660,8 +660,9 @@ bool Parser::isCarrying(uint16 wordIndex) { return false; } -void Parser::showDosInventory() { // Show user all objects being carried in a variable width 2 column format +void Parser::showDosInventory() { + debugC(1, kDebugParser, "showDosInventory()"); static const char *blanks = " "; uint16 index = 0, len1 = 0, len2 = 0; @@ -706,15 +707,17 @@ Parser_v1d::~Parser_v1d() { // Locate word in list of nouns and return ptr to string in noun list // If n is NULL, start at beginning of list, else with n -char *Parser_v1d::findNextNoun(char *n) { - int k = -1; - if (n) { // If n not NULL, find index - for (k = 0; _vm._arrayNouns[k]; k++) { - if (n == _vm._arrayNouns[k][0]) +char *Parser_v1d::findNextNoun(char *noun) { + debugC(1, kDebugParser, "findNextNoun(%s)", noun); + + int currNounIndex = -1; + if (noun) { // If noun not NULL, find index + for (currNounIndex = 0; _vm._arrayNouns[currNounIndex]; currNounIndex++) { + if (noun == _vm._arrayNouns[currNounIndex][0]) break; } } - for (int i = k + 1; _vm._arrayNouns[i]; i++) { + for (int i = currNounIndex + 1; _vm._arrayNouns[i]; i++) { for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) { if (strstr(_line, _vm._arrayNouns[i][j])) return _vm._arrayNouns[i][0]; @@ -728,6 +731,8 @@ char *Parser_v1d::findNextNoun(char *n) { // If object not near, return suitable string; may be similar object closer // If radius is -1, treat radius as infinity bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { + debugC(1, kDebugParser, "isNear(%s, %s, obj, %s)", verb, noun, comment); + if (!noun && !obj->verbOnlyFl) { // No noun specified & object not context senesitive return false; } else if (noun && (noun != _vm._arrayNouns[obj->nounIndex][0])) { // Noun specified & not same as object @@ -786,6 +791,8 @@ bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { // say_ok needed for special case of take/drop which may be handled not only // here but also in a cmd_list with a donestr string simultaneously bool Parser_v1d::isGenericVerb(char *word, object_t *obj) { + debugC(1, kDebugParser, "isGenericVerb(%s, object_t *obj)", word); + if (!obj->genericCmd) return false; @@ -823,7 +830,7 @@ bool Parser_v1d::isGenericVerb(char *word, object_t *obj) { // and if it passes, perform the actions in the action list. If the verb // is catered for, return TRUE bool Parser_v1d::isObjectVerb(char *word, object_t *obj) { -//actlist *actions; + debugC(1, kDebugParser, "isObjectVerb(%s, object_t *obj)", word); // First, find matching verb in cmd list uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands @@ -871,6 +878,8 @@ bool Parser_v1d::isObjectVerb(char *word, object_t *obj) { // Print text for possible background object. Return TRUE if match found // Only match if both verb and noun found. Test_ca will match verb-only bool Parser_v1d::isBackgroundWord(char *noun, char *verb, objectList_t obj) { + debugC(1, kDebugParser, "isBackgroundWord(%s, %s, object_list_t obj)", noun, verb); + if (!noun) return false; @@ -885,8 +894,10 @@ bool Parser_v1d::isBackgroundWord(char *noun, char *verb, objectList_t obj) { // Print text for possible background object. Return TRUE if match found // If test_noun TRUE, must have a noun given -bool Parser_v1d::isCatchallVerb(bool test_noun, char *noun, char *verb, objectList_t obj) { - if (test_noun && !noun) +bool Parser_v1d::isCatchallVerb(bool testNounFl, char *noun, char *verb, objectList_t obj) { + debugC(1, kDebugParser, "isCatchallVerb(%d, %s, %s, object_list_t obj)", (testNounFl) ? 1 : 0, noun, verb); + + if (testNounFl && !noun) return false; for (int i = 0; obj[i].verbIndex; i++) { @@ -900,6 +911,8 @@ bool Parser_v1d::isCatchallVerb(bool test_noun, char *noun, char *verb, objectLi // Parse the user's line of text input. Generate events as necessary void Parser_v1d::lineHandler() { + debugC(1, kDebugParser, "lineHandler()"); + object_t *obj; status_t &gameStatus = _vm.getGameStatus(); char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby @@ -977,6 +990,8 @@ Parser_v2d::~Parser_v2d() { // Parse the user's line of text input. Generate events as necessary void Parser_v2d::lineHandler() { + debugC(1, kDebugParser, "lineHandler()"); + object_t *obj; status_t &gameStatus = _vm.getGameStatus(); char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby -- cgit v1.2.3 From 6ebd324be47a90560bb6937eada37f5dabae94b3 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Sun, 10 Oct 2010 22:13:38 +0000 Subject: HUGO: Add specific takeObject and dropObject for H1 DOS svn-id: r53135 --- engines/hugo/parser.cpp | 93 +++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 34 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 300bd319d6..d116dda5f3 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -372,6 +372,38 @@ bool Parser_v1w::isNear(object_t *obj, char *verb, char *comment) { return true; } +// Do all things necessary to carry an object +void Parser_v1w::takeObject(object_t *obj) { + debugC(1, kDebugParser, "takeObject(object_t *obj)"); + + obj->carriedFl = true; + if (obj->seqNumb) { // Don't change if no image to display + obj->cycling = INVISIBLE; + } + _vm.adjustScore(obj->objValue); + + if (obj->seqNumb > 0) // If object has an image, force walk to dropped + obj->viewx = -1; // (possibly moved) object next time taken! + Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); +} + +// Do all necessary things to drop an object +void Parser_v1w::dropObject(object_t *obj) { + debugC(1, kDebugParser, "dropObject(object_t *obj)"); + + obj->carriedFl = false; + obj->screenIndex = *_vm._screen_p; + if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) + obj->cycling = CYCLE_FORWARD; + else + obj->cycling = NOT_CYCLING; + obj->x = _vm._hero->x - 1; + obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; + obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; + _vm.adjustScore(-obj->objValue); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); +} + // Search for matching verbs in background command list. // Noun is not required. Return TRUE if match found // Note that if the background command list has match set TRUE then do not @@ -615,40 +647,6 @@ void Parser::showTakeables() { } } -// Do all things necessary to carry an object -void Parser::takeObject(object_t *obj) { - debugC(1, kDebugParser, "takeObject(object_t *obj)"); - - obj->carriedFl = true; - if (obj->seqNumb) { // Don't change if no image to display - obj->cycling = INVISIBLE; - if (_vm.getPlatform() != Common::kPlatformWindows) - warning("takeObject : DOS version should use ALMOST_INVISIBLE"); - } - _vm.adjustScore(obj->objValue); - - if (obj->seqNumb > 0) // If object has an image, force walk to dropped - obj->viewx = -1; // (possibly moved) object next time taken! - Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); -} - -// Do all necessary things to drop an object -void Parser::dropObject(object_t *obj) { - debugC(1, kDebugParser, "dropObject(object_t *obj)"); - - obj->carriedFl = false; - obj->screenIndex = *_vm._screen_p; - if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) - obj->cycling = CYCLE_FORWARD; - else - obj->cycling = NOT_CYCLING; - obj->x = _vm._hero->x - 1; - obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; - obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; - _vm.adjustScore(-obj->objValue); - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); -} - // Return TRUE if object being carried by hero bool Parser::isCarrying(uint16 wordIndex) { debugC(1, kDebugParser, "isCarrying(%d)", wordIndex); @@ -892,6 +890,33 @@ bool Parser_v1d::isBackgroundWord(char *noun, char *verb, objectList_t obj) { return false; } +// Do all things necessary to carry an object +void Parser_v1d::takeObject(object_t *obj) { + debugC(1, kDebugParser, "takeObject(object_t *obj)"); + + obj->carriedFl = true; + if (obj->seqNumb) // Don't change if no image to display + obj->cycling = ALMOST_INVISIBLE; + + _vm.adjustScore(obj->objValue); + + Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); +} + +// Do all necessary things to drop an object +void Parser_v1d::dropObject(object_t *obj) { + debugC(1, kDebugParser, "dropObject(object_t *obj)"); + + obj->carriedFl = false; + obj->screenIndex = *_vm._screen_p; + if (obj->seqNumb) // Don't change if no image to display + obj->cycling = NOT_CYCLING; + obj->x = _vm._hero->x - 1; + obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; + _vm.adjustScore(-obj->objValue); + Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); +} + // Print text for possible background object. Return TRUE if match found // If test_noun TRUE, must have a noun given bool Parser_v1d::isCatchallVerb(bool testNounFl, char *noun, char *verb, objectList_t obj) { -- cgit v1.2.3 From 2978053a0094e5c1ba4ab871b3a27a3707197089 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Mon, 11 Oct 2010 21:41:31 +0000 Subject: HUGO: Split classes with multiple version in separate files svn-id: r53152 --- engines/hugo/parser.cpp | 799 ------------------------------------------------ 1 file changed, 799 deletions(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index d116dda5f3..0a4ca3a5a8 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -30,17 +30,11 @@ * */ -// parser.c - handles all keyboard/command input - #include "common/system.h" -#include "common/keyboard.h" -#include "hugo/game.h" #include "hugo/hugo.h" #include "hugo/parser.h" -#include "hugo/global.h" #include "hugo/file.h" -#include "hugo/schedule.h" #include "hugo/display.h" #include "hugo/route.h" #include "hugo/util.h" @@ -205,395 +199,6 @@ void Parser::command(const char *format, ...) { lineHandler(); } -Parser_v1w::Parser_v1w(HugoEngine &vm) : Parser(vm) { -} - -Parser_v1w::~Parser_v1w() { -} - -// Test whether command line contains a verb allowed by this object. -// If it does, and the object is near and passes the tests in the command -// list then carry out the actions in the action list and return TRUE -bool Parser_v1w::isObjectVerb(object_t *obj, char *comment) { - debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); - - // First, find matching verb in cmd list - uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands - if (cmdIndex == 0) // No commands for this obj - return false; - - int i; - for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd - if (isWordPresent(_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex])) // Was this verb used? - break; - } - - if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. - return false; - - // Verb match found. Check if object is Near - char *verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; - if (!isNear(obj, verb, comment)) - return false; - - // Check all required objects are being carried - cmd *cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd - if (cmnd->reqIndex) { // At least 1 thing in list - uint16 *reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects - for (i = 0; reqs[i]; i++) { // for each obj - if (!isCarrying(reqs[i])) { - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); - return true; - } - } - } - - // Required objects are present, now check state is correct - if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataWrongIndex]); - return true; - } - - // Everything checked. Change the state and carry out any actions - if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care - obj->state = cmnd->newState; - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataDoneIndex]); - _vm.scheduler().insertActionList(cmnd->actIndex); - - // See if any additional generic actions - if ((verb == _vm._arrayVerbs[_vm._look][0]) || (verb == _vm._arrayVerbs[_vm._take][0]) || (verb == _vm._arrayVerbs[_vm._drop][0])) - isGenericVerb(obj, comment); - return true; -} - -// Test whether command line contains one of the generic actions -bool Parser_v1w::isGenericVerb(object_t *obj, char *comment) { - debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); - - if (!obj->genericCmd) - return false; - - // Following is equivalent to switch, but couldn't do one - if (isWordPresent(_vm._arrayVerbs[_vm._look]) && isNear(obj, _vm._arrayVerbs[_vm._look][0], comment)) { - // Test state-dependent look before general look - if ((obj->genericCmd & LOOK_S) == LOOK_S) { - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->stateDataIndex[obj->state]]); - warning("isGenericVerb: use of state dependant look - To be validated"); - } else { - if ((LOOK & obj->genericCmd) == LOOK) { - if (_vm._textData[obj->dataIndex]) - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); - else - return false; - } else { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual]); - } - } - } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { - if (obj->carriedFl) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); - else if ((TAKE & obj->genericCmd) == TAKE) - takeObject(obj); - else if (obj->cmdIndex != 0) // No comment if possible commands - return false; - else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); - else - return false; - } else if (isWordPresent(_vm._arrayVerbs[_vm._drop])) { - if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); - else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - dropObject(obj); - else if (obj->cmdIndex == 0) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); - else - return false; - } else { // It was not a generic cmd - return false; - } - - return true; -} - -// Test whether hero is close to object. Return TRUE or FALSE -// If object not near, return suitable comment; may be another object close -// If radius is -1, treat radius as infinity -// Verb is included to determine correct comment if not near -bool Parser_v1w::isNear(object_t *obj, char *verb, char *comment) { - debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); - - if (obj->carriedFl) // Object is being carried - return true; - - if (obj->screenIndex != *_vm._screen_p) { - // Not in same screen - if (obj->objValue) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtAny2]); - return false; - } - - if (obj->cycling == INVISIBLE) { - if (obj->seqNumb) { - // There is an image - strcpy(comment, _vm._textParser[kCmtAny3]); - return false; - } else { - // No image, assume visible - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is not close enough - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - return false; - } - } - } - - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is not close enough - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - return false; - } - return true; -} - -// Do all things necessary to carry an object -void Parser_v1w::takeObject(object_t *obj) { - debugC(1, kDebugParser, "takeObject(object_t *obj)"); - - obj->carriedFl = true; - if (obj->seqNumb) { // Don't change if no image to display - obj->cycling = INVISIBLE; - } - _vm.adjustScore(obj->objValue); - - if (obj->seqNumb > 0) // If object has an image, force walk to dropped - obj->viewx = -1; // (possibly moved) object next time taken! - Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); -} - -// Do all necessary things to drop an object -void Parser_v1w::dropObject(object_t *obj) { - debugC(1, kDebugParser, "dropObject(object_t *obj)"); - - obj->carriedFl = false; - obj->screenIndex = *_vm._screen_p; - if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) - obj->cycling = CYCLE_FORWARD; - else - obj->cycling = NOT_CYCLING; - obj->x = _vm._hero->x - 1; - obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; - obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; - _vm.adjustScore(-obj->objValue); - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); -} - -// Search for matching verbs in background command list. -// Noun is not required. Return TRUE if match found -// Note that if the background command list has match set TRUE then do not -// print text if there are any recognizable nouns in the command line -bool Parser_v1w::isCatchallVerb(objectList_t obj) { - debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); - - for (int i = 0; obj[i].verbIndex != 0; i++) { - if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && - (!obj[i].matchFl || !findNoun()) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - _vm.scheduler().processBonus(obj[i].bonusIndex); - - // If this is LOOK (without a noun), show any takeable objects - if (*(_vm._arrayVerbs[obj[i].verbIndex]) == _vm._arrayVerbs[_vm._look][0]) - showTakeables(); - - return true; - } - } - return false; -} - -// Search for matching verb/noun pairs in background command list -// Print text for possible background object. Return TRUE if match found -bool Parser_v1w::isBackgroundWord(objectList_t obj) { - debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); - - for (int i = 0; obj[i].verbIndex != 0; i++) { - if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && - isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - _vm.scheduler().processBonus(obj[i].bonusIndex); - return true; - } - } - return false; -} - -// Parse the user's line of text input. Generate events as necessary -void Parser_v1w::lineHandler() { - debugC(1, kDebugParser, "lineHandler()"); - - status_t &gameStatus = _vm.getGameStatus(); - - // Toggle God Mode - if (!strncmp(_line, "PPG", 3)) { - _vm.sound().playSound(!_vm._soundTest, BOTH_CHANNELS, HIGH_PRI); - gameStatus.godModeFl ^= 1; - return; - } - - Utils::strlwr(_line); // Convert to lower case - - // God Mode cheat commands: - // goto Takes hero to named screen - // fetch Hero carries named object - // fetch all Hero carries all possible objects - // find Takes hero to screen containing named object - if (gameStatus.godModeFl) { - // Special code to allow me to go straight to any screen - if (strstr(_line, "goto")) { - for (int i = 0; i < _vm._numScreens; i++) { - if (!strcmp(&_line[strlen("goto") + 1], _vm._screenNames[i])) { - _vm.scheduler().newScreen(i); - return; - } - } - } - - // Special code to allow me to get objects from anywhere - if (strstr(_line, "fetch all")) { - for (int i = 0; i < _vm._numObj; i++) { - if (_vm._objects[i].genericCmd & TAKE) - takeObject(&_vm._objects[i]); - } - return; - } - - if (strstr(_line, "fetch")) { - for (int i = 0; i < _vm._numObj; i++) { - if (!strcmp(&_line[strlen("fetch") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { - takeObject(&_vm._objects[i]); - return; - } - } - } - - // Special code to allow me to goto objects - if (strstr(_line, "find")) { - for (int i = 0; i < _vm._numObj; i++) { - if (!strcmp(&_line[strlen("find") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { - _vm.scheduler().newScreen(_vm._objects[i].screenIndex); - return; - } - } - } - } - - // Special meta commands - // EXIT/QUIT - if (!strcmp("exit", _line) || strstr(_line, "quit")) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBExit]); - return; - } - - // SAVE/RESTORE - if (!strcmp("save", _line) && gameStatus.viewState == V_PLAY) { - _vm.file().saveGame(gameStatus.saveSlot, "Current game"); - return; - } - - if (!strcmp("restore", _line) && (gameStatus.viewState == V_PLAY || gameStatus.viewState == V_IDLE)) { - _vm.file().restoreGame(gameStatus.saveSlot); - _vm.scheduler().restoreScreen(*_vm._screen_p); - gameStatus.viewState = V_PLAY; - return; - } - - // Empty line - if (*_line == '\0') // Empty line - return; - if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! - return; - - if (gameStatus.gameOverFl) { - // No commands allowed! - Utils::gameOverMsg(); - return; - } - - char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby - - // Test for nearby objects referenced explicitly - for (int i = 0; i < _vm._numObj; i++) { - object_t *obj = &_vm._objects[i]; - if (isWordPresent(_vm._arrayNouns[obj->nounIndex])) { - if (isObjectVerb(obj, farComment) || isGenericVerb(obj, farComment)) - return; - } - } - - // Test for nearby objects that only require a verb - // Note comment is unused if not near. - for (int i = 0; i < _vm._numObj; i++) { - object_t *obj = &_vm._objects[i]; - if (obj->verbOnlyFl) { - char contextComment[XBYTES * 5] = ""; // Unused comment for context objects - if (isObjectVerb(obj, contextComment) || isGenericVerb(obj, contextComment)) - return; - } - } - - // No objects match command line, try background and catchall commands - if (isBackgroundWord(_vm._backgroundObjects[*_vm._screen_p])) - return; - if (isCatchallVerb(_vm._backgroundObjects[*_vm._screen_p])) - return; - if (isBackgroundWord(_vm._catchallList)) - return; - if (isCatchallVerb(_vm._catchallList)) - return; - - // If a not-near comment was generated, print it - if (*farComment != '\0') { - Utils::Box(BOX_ANY, "%s", farComment); - return; - } - - // Nothing matches. Report recognition success to user. - char *verb = findVerb(); - char *noun = findNoun(); - if (verb == _vm._arrayVerbs[_vm._look][0] && _maze.enabledFl) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); - showTakeables(); - } else if (verb && noun) { // A combination I didn't think of - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoPoint]); - } else if (noun) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoun]); - } else if (verb) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBVerb]); - } else { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh]); - } -} - // Locate any member of object name list appearing in command line bool Parser::isWordPresent(char **wordArr) { debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]); @@ -697,408 +302,4 @@ void Parser::showDosInventory() { Utils::Box(BOX_ANY, "%s", buffer); } -Parser_v1d::Parser_v1d(HugoEngine &vm) : Parser(vm) { -} - -Parser_v1d::~Parser_v1d() { -} - -// Locate word in list of nouns and return ptr to string in noun list -// If n is NULL, start at beginning of list, else with n -char *Parser_v1d::findNextNoun(char *noun) { - debugC(1, kDebugParser, "findNextNoun(%s)", noun); - - int currNounIndex = -1; - if (noun) { // If noun not NULL, find index - for (currNounIndex = 0; _vm._arrayNouns[currNounIndex]; currNounIndex++) { - if (noun == _vm._arrayNouns[currNounIndex][0]) - break; - } - } - for (int i = currNounIndex + 1; _vm._arrayNouns[i]; i++) { - for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) { - if (strstr(_line, _vm._arrayNouns[i][j])) - return _vm._arrayNouns[i][0]; - } - } - return 0; -} - -// Test whether hero is close to object. Return TRUE or FALSE -// If no noun specified, check context flag in object before other tests. -// If object not near, return suitable string; may be similar object closer -// If radius is -1, treat radius as infinity -bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { - debugC(1, kDebugParser, "isNear(%s, %s, obj, %s)", verb, noun, comment); - - if (!noun && !obj->verbOnlyFl) { // No noun specified & object not context senesitive - return false; - } else if (noun && (noun != _vm._arrayNouns[obj->nounIndex][0])) { // Noun specified & not same as object - return false; - } else if (obj->carriedFl) { // Object is being carried - return true; - } else if (obj->screenIndex != *_vm._screen_p) { // Not in same screen - if (obj->objValue) - strcpy (comment, _vm._textParser[kCmtAny4]); - return false; - } - - if (obj->cycling == INVISIBLE) { - if (obj->seqNumb) { // There is an image - strcpy(comment, _vm._textParser[kCmtAny5]); - return false; - } else { // No image, assume visible - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is either not close enough (stationary, valueless objects) - // or is not carrying it (small, portable objects of value) - if (noun) { // Don't say unless object specified - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny4]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - } - return false; - } - } - } - - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) { - return true; - } else { - // User is either not close enough (stationary, valueless objects) - // or is not carrying it (small, portable objects of value) - if (noun) { // Don't say unless object specified - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny4]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - } - return false; - } - - return true; -} - -// Test whether supplied verb is one of the common variety for this object -// say_ok needed for special case of take/drop which may be handled not only -// here but also in a cmd_list with a donestr string simultaneously -bool Parser_v1d::isGenericVerb(char *word, object_t *obj) { - debugC(1, kDebugParser, "isGenericVerb(%s, object_t *obj)", word); - - if (!obj->genericCmd) - return false; - - // Following is equivalent to switch, but couldn't do one - if (word == _vm._arrayVerbs[_vm._look][0]) { - if ((LOOK & obj->genericCmd) == LOOK) - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); - else - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual_1d]); - } else if (word == _vm._arrayVerbs[_vm._take][0]) { - if (obj->carriedFl) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); - else if ((TAKE & obj->genericCmd) == TAKE) - takeObject(obj); - else if (!obj->verbOnlyFl) // Make sure not taking object in context! - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); - else - return false; - } else if (word == _vm._arrayVerbs[_vm._drop][0]) { - if (!obj->carriedFl) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); - else if ((DROP & obj->genericCmd) == DROP) - dropObject(obj); - else - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); - } else { // It was not a generic cmd - return false; - } - - return true; -} - -// Test whether supplied verb is included in the list of allowed verbs for -// this object. If it is, then perform the tests on it from the cmd list -// and if it passes, perform the actions in the action list. If the verb -// is catered for, return TRUE -bool Parser_v1d::isObjectVerb(char *word, object_t *obj) { - debugC(1, kDebugParser, "isObjectVerb(%s, object_t *obj)", word); - - // First, find matching verb in cmd list - uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands - if (!cmdIndex) // No commands for this obj - return false; - - int i; - for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd - if (!strcmp(word, _vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex][0])) // Is this verb catered for? - break; - } - - if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No - return false; - - // Verb match found, check all required objects are being carried - cmd *cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd - if (cmnd->reqIndex) { // At least 1 thing in list - uint16 *reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects - for (i = 0; reqs[i]; i++) { // for each obj - if (!isCarrying(reqs[i])) { - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); - return true; - } - } - } - - // Required objects are present, now check state is correct - if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)){ - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataWrongIndex]); - return true; - } - - // Everything checked. Change the state and carry out any actions - if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care - obj->state = cmnd->newState; - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataDoneIndex]); - _vm.scheduler().insertActionList(cmnd->actIndex); - // Special case if verb is Take or Drop. Assume additional generic actions - if ((word == _vm._arrayVerbs[_vm._take][0]) || (word == _vm._arrayVerbs[_vm._drop][0])) - isGenericVerb(word, obj); - return true; -} - -// Print text for possible background object. Return TRUE if match found -// Only match if both verb and noun found. Test_ca will match verb-only -bool Parser_v1d::isBackgroundWord(char *noun, char *verb, objectList_t obj) { - debugC(1, kDebugParser, "isBackgroundWord(%s, %s, object_list_t obj)", noun, verb); - - if (!noun) - return false; - - for (int i = 0; obj[i].verbIndex; i++) { - if ((verb == _vm._arrayVerbs[obj[i].verbIndex][0]) && (noun == _vm._arrayNouns[obj[i].nounIndex][0])) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - return true; - } - } - return false; -} - -// Do all things necessary to carry an object -void Parser_v1d::takeObject(object_t *obj) { - debugC(1, kDebugParser, "takeObject(object_t *obj)"); - - obj->carriedFl = true; - if (obj->seqNumb) // Don't change if no image to display - obj->cycling = ALMOST_INVISIBLE; - - _vm.adjustScore(obj->objValue); - - Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); -} - -// Do all necessary things to drop an object -void Parser_v1d::dropObject(object_t *obj) { - debugC(1, kDebugParser, "dropObject(object_t *obj)"); - - obj->carriedFl = false; - obj->screenIndex = *_vm._screen_p; - if (obj->seqNumb) // Don't change if no image to display - obj->cycling = NOT_CYCLING; - obj->x = _vm._hero->x - 1; - obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; - _vm.adjustScore(-obj->objValue); - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); -} - -// Print text for possible background object. Return TRUE if match found -// If test_noun TRUE, must have a noun given -bool Parser_v1d::isCatchallVerb(bool testNounFl, char *noun, char *verb, objectList_t obj) { - debugC(1, kDebugParser, "isCatchallVerb(%d, %s, %s, object_list_t obj)", (testNounFl) ? 1 : 0, noun, verb); - - if (testNounFl && !noun) - return false; - - for (int i = 0; obj[i].verbIndex; i++) { - if ((verb == _vm._arrayVerbs[obj[i].verbIndex][0]) && ((noun == _vm._arrayNouns[obj[i].nounIndex][0]) || (obj[i].nounIndex == 0))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - return true; - } - } - return false; -} - -// Parse the user's line of text input. Generate events as necessary -void Parser_v1d::lineHandler() { - debugC(1, kDebugParser, "lineHandler()"); - - object_t *obj; - status_t &gameStatus = _vm.getGameStatus(); - char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby - -// Reset_prompt_line (); - Utils::strlwr(_line); // Convert to lower case - - if (!strcmp("exit", _line) || strstr(_line, "quit")) { - if (Utils::Box(BOX_YESNO, "%s", _vm._textParser[kTBExit_1d]) != 0) - _vm.endGame(); - return; - } - - // SAVE/RESTORE - if (!strcmp("save", _line)) { - if (gameStatus.gameOverFl) - Utils::gameOverMsg(); - else -// _vm.file().saveOrRestore(true); - warning("STUB: saveOrRestore()"); - return; - } - - if (!strcmp("restore", _line)) { -// _vm.file().saveOrRestore(false); - warning("STUB: saveOrRestore()"); - return; - } - - if (*_line == '\0') // Empty line - return; - - if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! - return; - - if (gameStatus.gameOverFl) { // No commands allowed! - Utils::gameOverMsg(); - return; - } - - // Find the first verb in the line - char *verb = findVerb(); - char *noun = 0; // Noun not found yet - - if (verb) { // OK, verb found. Try to match with object - do { - noun = findNextNoun(noun); // Find a noun in the line - // Must try at least once for objects allowing verb-context - for (int i = 0; i < _vm._numObj; i++) { - obj = &_vm._objects[i]; - if (isNear(verb, noun, obj, farComment)) { - if (isObjectVerb(verb, obj) // Foreground object - || isGenericVerb(verb, obj)) // Common action type - return; - } - } - if ((*farComment == '\0') && isBackgroundWord(noun, verb, _vm._backgroundObjects[*_vm._screen_p])) - return; - } while (noun); - } - noun = findNextNoun(noun); - if (*farComment != '\0') // An object matched but not near enough - Utils::Box(BOX_ANY, "%s", farComment); - else if (!isCatchallVerb(true, noun, verb, _vm._catchallList) && - !isCatchallVerb(false, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) && - !isCatchallVerb(false, noun, verb, _vm._catchallList)) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh_1d]); -} - -Parser_v2d::Parser_v2d(HugoEngine &vm) : Parser_v1d(vm) { -} - -Parser_v2d::~Parser_v2d() { -} - -// Parse the user's line of text input. Generate events as necessary -void Parser_v2d::lineHandler() { - debugC(1, kDebugParser, "lineHandler()"); - - object_t *obj; - status_t &gameStatus = _vm.getGameStatus(); - char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby - -// Reset_prompt_line (); - Utils::strlwr(_line); // Convert to lower case - - if (!strcmp("exit", _line) || strstr(_line, "quit")) { - if (Utils::Box(BOX_YESNO, "%s", _vm._textParser[kTBExit_1d]) != 0) - _vm.endGame(); - else - return; - } - - // SAVE/RESTORE - if (!strcmp("save", _line)) { - _config.soundFl = false; - if (gameStatus.gameOverFl) - Utils::gameOverMsg(); - else -// _vm.file().saveOrRestore(true); - warning("STUB: saveOrRestore()"); - return; - } - - if (!strcmp("restore", _line)) { - _config.soundFl = false; -// _vm.file().saveOrRestore(false); - warning("STUB: saveOrRestore()"); - return; - } - - if (!strlen(_line)) // Empty line - return; - - if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! - return; - - if (gameStatus.gameOverFl) { // No commands allowed! - Utils::gameOverMsg(); - return; - } - - // Find the first verb in the line - char *verb = findVerb(); - char *noun = 0; // Noun not found yet - - if (verb) { // OK, verb found. Try to match with object - do { - noun = findNextNoun(noun); // Find a noun in the line - // Must try at least once for objects allowing verb-context - for (int i = 0; i < _vm._numObj; i++) { - obj = &_vm._objects[i]; - if (isNear(verb, noun, obj, farComment)) { - if (isObjectVerb(verb, obj) // Foreground object - || isGenericVerb(verb, obj)) // Common action type - return; - } - } - if ((*farComment != '\0') && isBackgroundWord(noun, verb, _vm._backgroundObjects[*_vm._screen_p])) - return; - } while (noun); - } - - noun = findNextNoun(noun); - if ( !isCatchallVerb(true, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) - && !isCatchallVerb(true, noun, verb, _vm._catchallList) - && !isCatchallVerb(false, noun, verb, _vm._backgroundObjects[*_vm._screen_p]) - && !isCatchallVerb(false, noun, verb, _vm._catchallList)) { - if (*farComment != '\0') { // An object matched but not near enough - Utils::Box(BOX_ANY, "%s", farComment); - } else if (_maze.enabledFl && (verb == _vm._arrayVerbs[_vm._look][0])) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); - showTakeables(); - } else if (verb && noun) { // A combination I didn't think of - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse_2d]); - } else if (verb || noun) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoun]); - } else { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh_2d]); - } - } -} - } // End of namespace Hugo -- cgit v1.2.3 From 7723d91c957d07205c51be32498d45cd0a78568f Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Tue, 12 Oct 2010 21:12:54 +0000 Subject: HUGO: Add lineHandler for v3 Dos, fix/add comments svn-id: r53170 --- engines/hugo/parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/hugo/parser.cpp') diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 0a4ca3a5a8..4277d6e845 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -121,7 +121,7 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { } // Add any new chars to line buffer and display them. -// If CR pressed, pass line to Line_handler() +// If CR pressed, pass line to LineHandler() void Parser::charHandler() { debugC(4, kDebugParser, "charHandler"); -- cgit v1.2.3