aboutsummaryrefslogtreecommitdiff
path: root/engines/hugo
diff options
context:
space:
mode:
Diffstat (limited to 'engines/hugo')
-rw-r--r--engines/hugo/inventory.cpp2
-rw-r--r--engines/hugo/object.cpp4
-rw-r--r--engines/hugo/parser.cpp12
-rw-r--r--engines/hugo/parser.h58
-rw-r--r--engines/hugo/parser_v1w.cpp311
-rw-r--r--engines/hugo/parser_v3d.cpp251
6 files changed, 357 insertions, 281 deletions
diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp
index 19aa69c1fa..43a05d1d86 100644
--- a/engines/hugo/inventory.cpp
+++ b/engines/hugo/inventory.cpp
@@ -73,7 +73,7 @@ void InventoryHandler::constructInventory(int16 imageTotNumb, int displayNumb, b
// Copy inventory icons to remaining positions
int16 displayed = 0;
int16 carried = 0;
- for (int16 i = 0; i < imageTotNumb; i++) {
+ for (int16 i = 0; (i < imageTotNumb) && (displayed < displayNumb); i++) {
if (_vm->_object->isCarried(_vm->_invent[i])) {
// Check still room to display and past first scroll index
if (displayed < displayNumb && carried >= firstObjId) {
diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp
index 550d803bfb..464e408b40 100644
--- a/engines/hugo/object.cpp
+++ b/engines/hugo/object.cpp
@@ -113,7 +113,7 @@ void ObjectHandler::useObject(int16 objId) {
} else {
// Use status.objid on objid
// Default to first cmd verb
- sprintf(_line, "%s %s %s", _vm->_arrayVerbs[_vm->_cmdList[_objects[_vm->getGameStatus().inventoryObjId].cmdIndex][1].verbIndex][0],
+ sprintf(_line, "%s %s %s", _vm->_arrayVerbs[_vm->_cmdList[_objects[_vm->getGameStatus().inventoryObjId].cmdIndex][0].verbIndex][0],
_vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0],
_vm->_arrayNouns[obj->nounIndex][0]);
@@ -123,7 +123,7 @@ void ObjectHandler::useObject(int16 objId) {
// Look for secondary object, if found use matching verb
bool foundFl = false;
for (target_t *target = use->targets; _vm->_arrayNouns[target->nounIndex] != 0; target++)
- if (_vm->_arrayNouns[target->nounIndex][0] == _vm->_arrayNouns[obj->nounIndex][0]) {
+ if (target->nounIndex == obj->nounIndex) {
foundFl = true;
sprintf(_line, "%s %s %s", _vm->_arrayVerbs[target->verbIndex][0],
_vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0],
diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp
index 19d496dfd4..720b8e3305 100644
--- a/engines/hugo/parser.cpp
+++ b/engines/hugo/parser.cpp
@@ -86,12 +86,6 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) {
_vm->_screen->userHelp();
_checkDoubleF1Fl = !_checkDoubleF1Fl;
break;
- case Common::KEYCODE_F6: // Inventory
- showDosInventory();
- break;
- case Common::KEYCODE_F8: // Turbo mode
- _config.turboFl = !_config.turboFl;
- break;
case Common::KEYCODE_F2: // Toggle sound
_vm->_sound->toggleSound();
_vm->_sound->toggleMusic();
@@ -108,6 +102,12 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) {
_vm->_scheduler->restoreScreen(*_vm->_screen_p);
gameStatus.viewState = V_PLAY;
break;
+ case Common::KEYCODE_F6: // Inventory
+ showDosInventory();
+ break;
+ case Common::KEYCODE_F8: // Turbo mode
+ _config.turboFl = !_config.turboFl;
+ break;
case Common::KEYCODE_F9: // Boss button
warning("STUB: F9 (DOS) - BossKey");
break;
diff --git a/engines/hugo/parser.h b/engines/hugo/parser.h
index b98813c7bc..d25b1434e6 100644
--- a/engines/hugo/parser.h
+++ b/engines/hugo/parser.h
@@ -47,11 +47,12 @@ public:
Parser(HugoEngine *vm);
virtual ~Parser();
- bool isWordPresent(char **wordArr);
+ bool isWordPresent(char **wordArr);
- void charHandler();
- void command(const char *format, ...);
- void keyHandler(uint16 nChar, uint16 nFlags);
+ void charHandler();
+ void command(const char *format, ...);
+
+ virtual void keyHandler(uint16 nChar, uint16 nFlags);
virtual void lineHandler() = 0;
protected:
@@ -60,33 +61,13 @@ protected:
protected:
char *findNoun();
char *findVerb();
-
-private:
- char _ringBuffer[32]; // Ring buffer
+ bool _checkDoubleF1Fl; // Flag used to display user help or instructions
uint16 _putIndex;
uint16 _getIndex; // Index into ring buffer
- bool _checkDoubleF1Fl; // Flag used to display user help or instructions
-
- void showDosInventory();
-};
-
-class Parser_v1w : public Parser {
-public:
- Parser_v1w(HugoEngine *vm);
- ~Parser_v1w();
-
- virtual void lineHandler();
-
-protected:
- bool isBackgroundWord(objectList_t obj);
- bool isCatchallVerb(objectList_t obj);
- bool isGenericVerb(object_t *obj, char *comment);
- bool isObjectVerb(object_t *obj, char *comment);
- void takeObject(object_t *obj);
+ char _ringBuffer[32]; // Ring buffer
private:
- bool isNear(object_t *obj, char *verb, char *comment);
- void dropObject(object_t *obj);
+ void showDosInventory();
};
class Parser_v1d : public Parser {
@@ -115,12 +96,31 @@ public:
void lineHandler();
};
-class Parser_v3d : public Parser_v1w {
+class Parser_v3d : public Parser {
public:
Parser_v3d(HugoEngine *vm);
~Parser_v3d();
- void lineHandler();
+ virtual void lineHandler();
+protected:
+ bool isBackgroundWord(objectList_t obj);
+ bool isCatchallVerb(objectList_t obj);
+ bool isGenericVerb(object_t *obj, char *comment);
+ bool isObjectVerb(object_t *obj, char *comment);
+ void takeObject(object_t *obj);
+
+private:
+ bool isNear(object_t *obj, char *verb, char *comment);
+ void dropObject(object_t *obj);
+};
+
+class Parser_v1w : public Parser_v3d {
+public:
+ Parser_v1w(HugoEngine *vm);
+ ~Parser_v1w();
+
+ void keyHandler(uint16 nChar, uint16 nFlags);
+ void lineHandler();
};
} // End of namespace Hugo
diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp
index 236d24b61b..2de173712e 100644
--- a/engines/hugo/parser_v1w.cpp
+++ b/engines/hugo/parser_v1w.cpp
@@ -38,264 +38,91 @@
#include "hugo/parser.h"
#include "hugo/file.h"
#include "hugo/schedule.h"
+#include "hugo/route.h"
+#include "hugo/display.h"
#include "hugo/util.h"
#include "hugo/sound.h"
#include "hugo/object.h"
namespace Hugo {
-Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser(vm) {
+Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser_v3d(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 (!_vm->_object->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);
+void Parser_v1w::keyHandler(uint16 nChar, uint16 nFlags) {
+ debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags);
- // 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]]);
- } 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]);
- }
+ status_t &gameStatus = _vm->getGameStatus();
+ bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat
+
+// 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
}
- } 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]);
+ break;
+ case Common::KEYCODE_F1: // User Help (DOS)
+ if (_checkDoubleF1Fl)
+ _vm->_file->instructions();
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;
+ _vm->_screen->userHelp();
+ _checkDoubleF1Fl = !_checkDoubleF1Fl;
+ break;
+ case Common::KEYCODE_F2: // Toggle sound
+ _vm->_sound->toggleSound();
+ _vm->_sound->toggleMusic();
+ break;
+ case Common::KEYCODE_F3: // Repeat last line
+ gameStatus.recallFl = true;
+ break;
+ case Common::KEYCODE_F4: // Save game
+ if (gameStatus.viewState == V_PLAY)
+ _vm->_file->saveGame(-1, Common::String());
+ break;
+ case Common::KEYCODE_F5: // Restore game
+ _vm->_file->restoreGame(-1);
+ _vm->_scheduler->restoreScreen(*_vm->_screen_p);
+ gameStatus.viewState = V_PLAY;
+ break;
+ case Common::KEYCODE_F6: // Inventory
+ gameStatus.inventoryState = I_DOWN;
+ gameStatus.viewState = V_INVENT;
+ break;
+ case Common::KEYCODE_F8: // Turbo mode
+ _config.turboFl = !_config.turboFl;
+ break;
+ case Common::KEYCODE_F9: // Boss button
+ warning("STUB: F9 (DOS) - BossKey");
+ 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;
}
-
- 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])
- _vm->_object->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;
+ if (_checkDoubleF1Fl && (nChar != Common::KEYCODE_F1))
+ _checkDoubleF1Fl = false;
}
/**
diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp
index ca78307a44..c78af20ef3 100644
--- a/engines/hugo/parser_v3d.cpp
+++ b/engines/hugo/parser_v3d.cpp
@@ -44,7 +44,7 @@
namespace Hugo {
-Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser_v1w(vm) {
+Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser(vm) {
}
Parser_v3d::~Parser_v3d() {
@@ -204,4 +204,253 @@ void Parser_v3d::lineHandler() {
}
}
+/**
+* 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_v3d::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 (!_vm->_object->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_v3d::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]]);
+ } 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_v3d::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_v3d::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_v3d::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_v3d::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])
+ _vm->_object->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_v3d::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;
+}
+
} // End of namespace Hugo