GLK: ADVSYS: Noun/adjectives setup and getNoun method

This commit is contained in:
Paul Gilbert 2019-06-12 21:45:54 -07:00
parent 9efb6d71e2
commit 0e543b0682
4 changed files with 74 additions and 47 deletions

View File

@ -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<int> &verbs) {
// Iterate through the actions
for (int idx = 1; idx <= _actionCount; ++idx) {

View File

@ -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<byte> _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
*/

View File

@ -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) {

View File

@ -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<InputWord> _words;
Common::Array<InputWord>::iterator _wordPtr;
Common::Array<int> _verbs;
Common::Array<AdjectiveEntry> _adjectiveList;
Common::Array<Noun> _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
*/