From 0e543b06823e629a007bad26f94d452bfb38abf1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 12 Jun 2019 21:45:54 -0700 Subject: [PATCH] GLK: ADVSYS: Noun/adjectives setup and getNoun method --- engines/glk/advsys/game.cpp | 12 -------- engines/glk/advsys/game.h | 25 +++++++--------- engines/glk/advsys/vm.cpp | 57 ++++++++++++++++++++++++++++--------- engines/glk/advsys/vm.h | 27 ++++++++++++++---- 4 files changed, 74 insertions(+), 47 deletions(-) diff --git a/engines/glk/advsys/game.cpp b/engines/glk/advsys/game.cpp index cd19623f5de..50b258d9249 100644 --- a/engines/glk/advsys/game.cpp +++ b/engines/glk/advsys/game.cpp @@ -190,18 +190,6 @@ int Game::findWord(const Common::String &word) const { return NIL; } -bool Game::match(int obj, int noun, int *adjectives) { - if (!hasNoun(obj, noun)) - return false; - - for (int *adjPtr = adjectives; *adjPtr; ++adjPtr) { - if (!hasAdjective(obj, *adjPtr)) - return false; - } - - return true; -} - int Game::checkVerb(const Common::Array &verbs) { // Iterate through the actions for (int idx = 1; idx <= _actionCount; ++idx) { diff --git a/engines/glk/advsys/game.h b/engines/glk/advsys/game.h index 1b7c6f95b01..5920f412d52 100644 --- a/engines/glk/advsys/game.h +++ b/engines/glk/advsys/game.h @@ -169,16 +169,6 @@ private: */ int findProperty(int obj, int prop) const; - /** - * Returns true if an object has a given noun - */ - bool hasNoun(int obj, int noun) const; - - /** - * Returns true if an object has a given adjective - */ - bool hasAdjective(int obj, int adjective) const; - /** * Returns true if an action has a given verb */ @@ -205,6 +195,16 @@ private: * Read the next character for a string */ char readMsgChar(); +protected: + /** + * Returns true if an object has a given noun + */ + bool hasNoun(int obj, int noun) const; + + /** + * Returns true if an object has a given adjective + */ + bool hasAdjective(int obj, int adjective) const; public: Common::Array _data; int _residentOffset; @@ -270,11 +270,6 @@ public: return (WordType)_wordTypeTable[word]; } - /** - * Match an object against a name and list of adjectives - */ - bool match(int obj, int noun, int *adjectives); - /** * Check to see if this is a valid verb */ diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp index 54ab84c9c6e..bbe958a11b7 100644 --- a/engines/glk/advsys/vm.cpp +++ b/engines/glk/advsys/vm.cpp @@ -86,11 +86,6 @@ OpcodeMethod VM::_METHODS[0x34] = { VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(), _fp(_stack), _pc(0), _status(IN_PROGRESS), _actor(-1), _action(-1), _dObject(-1), _ndObjects(-1), _iObject(-1), _wordPtr(nullptr) { - Common::fill(&_nouns[0], &_nouns[20], 0); - Common::fill(&_nounWords[0], &_nounWords[20], -1); - Common::fill(&_adjectives[0], &_adjectives[20], (int *)nullptr); - Common::fill(&_adjectiveWords[0], &_adjectiveWords[100], -1); - Common::fill(&_adjectiveLists[0], &_adjectiveLists[100], -1); } ExecutionResult VM::execute(int offset) { @@ -354,7 +349,7 @@ void VM::opCLASS() { void VM::opMATCH() { int idx = _stack.pop() - 1; - _stack.top() = match(_stack.top(), _nouns[idx], _adjectives[idx]) ? TRUE : NIL; + _stack.top() = match(_stack.top(), _nouns[idx]._noun, _nouns[idx]._adjective) ? TRUE : NIL; } void VM::opPNOUN() { @@ -363,16 +358,16 @@ void VM::opPNOUN() { // Add the adjectives bool space = false; - for (int *aPtr = _adjectives[noun - 1]; *aPtr; ++aPtr, space = true) { + for (const AdjectiveEntry *aPtr = &_adjectiveList[noun - 1]; aPtr->_list; ++aPtr, space = true) { if (space) str += " "; - str += _words[_adjectiveWords[aPtr - _adjectiveLists]]._text; + str += _words[aPtr->_word]._text; } // Add the noun if (space) str += " "; - str += _words[_nounWords[noun - 1]]._text; + str += _words[_nouns[noun - 1]._num]._text; print(str); } @@ -447,6 +442,8 @@ bool VM::parseInput() { // Initialize the parser result fields _actor = _action = _dObject = _iObject = 0; _ndObjects = 0; + _adjectiveList.clear(); + _nouns.clear(); // Get the input line if (!getLine()) @@ -514,15 +511,35 @@ bool VM::getWord(Common::String &line) { } } -bool VM::getNoun() { - // TODO: Stub - return false; +uint VM::getNoun() { + // Skip over optional article if present + if (_wordPtr != _words.end() && getWordType(*_wordPtr) == WT_ARTICLE) + ++_wordPtr; + + // Get optional adjectives + uint alStart = _adjectiveList.size(); + while (_wordPtr != _words.end() && getWordType(*_wordPtr) == WT_ADJECTIVE) { + AdjectiveEntry ae; + ae._list = *_wordPtr++; + ae._word = _wordPtr - _words.begin() - 1; + _adjectiveList.push_back(ae); + } + _adjectiveList.push_back(AdjectiveEntry()); + + // Add a noun entry to the list + Noun n; + n._adjective = &_adjectiveList[alStart]; + n._noun = *_wordPtr++; + n._num = _wordPtr - _words.begin() - 1; + _nouns.push_back(n); + + return _nouns.size(); } bool VM::getVerb() { _verbs.clear(); - if (_words.front() == NIL || getWordType(_words.front()) != WT_VERB) { + if (*_wordPtr == NIL || getWordType(*_wordPtr) != WT_VERB) { parseError(); return false; } @@ -554,8 +571,20 @@ bool VM::getVerb() { return true; } +bool VM::match(int obj, int noun, const VM::AdjectiveEntry *adjectives) { + if (!hasNoun(obj, noun)) + return false; + + for (const VM::AdjectiveEntry *adjPtr = adjectives; adjPtr->_list; ++adjPtr) { + if (!hasAdjective(obj, adjPtr->_list)) + return false; + } + + return true; +} + void VM::parseError() { - // TODO + print(_("I don't understand.\n")); } bool VM::isWhitespace(char c) { diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h index d3b7bfc8f67..6a877c9ef0b 100644 --- a/engines/glk/advsys/vm.h +++ b/engines/glk/advsys/vm.h @@ -204,6 +204,19 @@ class VM : public GlkInterface, public Game { InputWord() : _number(0) {} operator int() const { return _number; } }; + struct AdjectiveEntry { + int _list; + int _word; + + AdjectiveEntry() : _list(0), _word(0) {} + }; + struct Noun { + int _noun; + int _num; + AdjectiveEntry *_adjective; + + Noun() : _noun(0), _num(0), _adjective(nullptr) {} + }; private: // Execution fields static OpcodeMethod _METHODS[0x34]; @@ -213,11 +226,6 @@ private: FunctionPointer _fp; // Parser fields - int *_adjectives[20]; - int _adjectiveLists[100]; - int _adjectiveWords[100]; - int _nouns[20]; - int _nounWords[20]; int _actor; int _action; int _dObject; @@ -226,6 +234,8 @@ private: Common::Array _words; Common::Array::iterator _wordPtr; Common::Array _verbs; + Common::Array _adjectiveList; + Common::Array _nouns; private: /** * Execute a single opcode within the script @@ -266,13 +276,18 @@ private: /** * Get a noun phrase and return the object it refers to */ - bool getNoun(); + uint getNoun(); /** * Get a verb phrase and return the action it refers to */ bool getVerb(); + /** + * Match an object against a name and list of adjectives + */ + bool match(int obj, int noun, const AdjectiveEntry *adjectives); + /** * Called when a parsing error occurs */