[Scummvm-git-logs] scummvm master -> 06ffbab3c5450632de367bbea5a1a47fdc4300ff
dreammaster
paulfgilbert at gmail.com
Thu Jun 13 07:26:18 CEST 2019
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
9c0771552d GLK: ADVSYS: Remaining opcode implementations
4e74751e7e GLK: ADVSYS: Added input line split up and tokenizing
9efb6d71e2 GLK: ADVSYS: In progress implementing input line parser
0e543b0682 GLK: ADVSYS: Noun/adjectives setup and getNoun method
8612697409 GLK: ADVSYS: Remainder of parseInput method
06ffbab3c5 GLK: ADVSYS: Added singleAction method
Commit: 9c0771552d97f8e8aec1ba93d7ff689b0e58a64c
https://github.com/scummvm/scummvm/commit/9c0771552d97f8e8aec1ba93d7ff689b0e58a64c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-06-12T21:30:41-07:00
Commit Message:
GLK: ADVSYS: Remaining opcode implementations
Changed paths:
engines/glk/advsys/vm.cpp
engines/glk/advsys/vm.h
diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp
index dbfe0ad..53950fc 100644
--- a/engines/glk/advsys/vm.cpp
+++ b/engines/glk/advsys/vm.cpp
@@ -84,6 +84,11 @@ OpcodeMethod VM::_METHODS[0x34] = {
VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(),
_fp(_stack), _pc(0), _status(IN_PROGRESS) {
+ 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) {
@@ -328,30 +333,58 @@ void VM::opASET() {
}
void VM::opTMP() {
+ int val = readCodeByte();
+ _stack.top() = _fp[-val - 1];
}
void VM::opTSET() {
+ int val = readCodeByte();
+ _fp[-val - 1] = _stack.top();
}
void VM::opTSPACE() {
+ _stack.allocate(readCodeByte());
}
void VM::opCLASS() {
+ _stack.top() = getObjectField(_stack.top(), O_CLASS);
}
void VM::opMATCH() {
+ int idx = _stack.pop() - 1;
+ _stack.top() = match(_stack.top(), _nouns[idx], _adjectives[idx]) ? TRUE : NIL;
}
void VM::opPNOUN() {
+ int noun = _stack.top();
+ Common::String str;
+
+ // Add the adjectives
+ bool space = false;
+ for (int *aPtr = _adjectives[noun - 1]; *aPtr; ++aPtr, space = true) {
+ if (space)
+ str += " ";
+ str += _wordText[_adjectiveWords[aPtr - _adjectiveLists]];
+ }
+
+ // Add the noun
+ if (space)
+ str += " ";
+ str += _wordText[_nounWords[noun - 1]];
+
+ print(str);
}
void VM::opRESTART() {
+ restart();
}
void VM::opRAND() {
+ _stack.top() = getRandomNumber(_stack.top());
}
void VM::opRNDMIZE() {
+ // No implementation
}
void VM::opSEND() {
@@ -376,6 +409,7 @@ void VM::opSEND() {
}
void VM::opVOWEL() {
+ // No implementation
}
} // End of namespace AdvSys
diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h
index e7477b9..b5c5b48 100644
--- a/engines/glk/advsys/vm.h
+++ b/engines/glk/advsys/vm.h
@@ -121,10 +121,22 @@ typedef void (VM::*OpcodeMethod)();
*/
class FixedStack : public Common::FixedStack<int, 500> {
public:
+ /**
+ * Resize the stack
+ */
void resize(size_t newSize) {
- assert(newSize <= _size);
+ assert(newSize <= 500);
_size = newSize;
}
+
+ /**
+ * Allocate extra space on the stack
+ */
+ void allocate(size_t amount) {
+ uint oldSize = _size;
+ resize(_size + amount);
+ Common::fill(&_stack[oldSize], &_stack[oldSize + amount], 0);
+ }
};
/**
@@ -176,11 +188,20 @@ public:
*/
class VM : public GlkInterface, public Game {
private:
+ // Execution fields
static OpcodeMethod _METHODS[0x34];
int _pc;
ExecutionResult _status;
FixedStack _stack;
FunctionPointer _fp;
+
+ // Parser fields
+ int *_adjectives[20];
+ int _adjectiveLists[100];
+ int _adjectiveWords[100];
+ int _nouns[20];
+ int _nounWords[20];
+ Common::String _wordText[100];
private:
/**
* Execute a single opcode within the script
Commit: 4e74751e7e40e0a3ddada4b4266c845004d2498d
https://github.com/scummvm/scummvm/commit/4e74751e7e40e0a3ddada4b4266c845004d2498d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-06-12T21:30:41-07:00
Commit Message:
GLK: ADVSYS: Added input line split up and tokenizing
Changed paths:
engines/glk/advsys/advsys.cpp
engines/glk/advsys/glk_interface.cpp
engines/glk/advsys/glk_interface.h
engines/glk/advsys/vm.cpp
engines/glk/advsys/vm.h
diff --git a/engines/glk/advsys/advsys.cpp b/engines/glk/advsys/advsys.cpp
index 0c63ff8..3f50d84 100644
--- a/engines/glk/advsys/advsys.cpp
+++ b/engines/glk/advsys/advsys.cpp
@@ -26,20 +26,11 @@
namespace Glk {
namespace AdvSys {
-bool getInput() {
- // TODO: Stub
- return false;
-}
-
bool singleAction() {
// TODO: Stub
return false;
}
-bool nextAction() {
- // TODO: STub
- return false;
-}
void AdvSys::runGame() {
if (!initialize()) {
@@ -60,7 +51,7 @@ void AdvSys::runGame() {
// Get and parse a single line
if (getInput()) {
if (singleAction()) {
- while (!shouldQuit() && nextAction() && singleAction()) {}
+ while (!shouldQuit() && nextCommand() && singleAction()) {}
}
}
}
diff --git a/engines/glk/advsys/glk_interface.cpp b/engines/glk/advsys/glk_interface.cpp
index 800d708..6ec5a08 100644
--- a/engines/glk/advsys/glk_interface.cpp
+++ b/engines/glk/advsys/glk_interface.cpp
@@ -39,7 +39,7 @@ void GlkInterface::print(int number) {
print(s);
}
-Common::String GlkInterface::getLine() {
+Common::String GlkInterface::readLine() {
// TODO: Stub
return "";
}
diff --git a/engines/glk/advsys/glk_interface.h b/engines/glk/advsys/glk_interface.h
index 44f3db9..95dcfa8 100644
--- a/engines/glk/advsys/glk_interface.h
+++ b/engines/glk/advsys/glk_interface.h
@@ -56,7 +56,7 @@ protected:
/**
* Get an input line
*/
- Common::String getLine();
+ Common::String readLine();
public:
/**
* Constructor
diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp
index 53950fc..21f79d5 100644
--- a/engines/glk/advsys/vm.cpp
+++ b/engines/glk/advsys/vm.cpp
@@ -21,6 +21,7 @@
*/
#include "glk/advsys/vm.h"
+#include "common/translation.h"
namespace Glk {
namespace AdvSys {
@@ -83,7 +84,8 @@ OpcodeMethod VM::_METHODS[0x34] = {
};
VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(),
- _fp(_stack), _pc(0), _status(IN_PROGRESS) {
+ _fp(_stack), _pc(0), _status(IN_PROGRESS), _actor(-1), _action(-1), _dObject(-1),
+ _ndObjects(-1), _iObject(-1) {
Common::fill(&_nouns[0], &_nouns[20], 0);
Common::fill(&_nounWords[0], &_nounWords[20], -1);
Common::fill(&_adjectives[0], &_adjectives[20], (int *)nullptr);
@@ -302,8 +304,8 @@ void VM::opSNLIT() {
}
void VM::opYORN() {
- Common::String line = getLine();
- _stack.top() = line[0] == 'Y' || line[0] == 'y' ? TRUE : NIL;
+ Common::String line = readLine();
+ _stack.top() = !line.empty() && (line[0] == 'Y' || line[0] == 'y') ? TRUE : NIL;
}
void VM::opSAVE() {
@@ -364,13 +366,13 @@ void VM::opPNOUN() {
for (int *aPtr = _adjectives[noun - 1]; *aPtr; ++aPtr, space = true) {
if (space)
str += " ";
- str += _wordText[_adjectiveWords[aPtr - _adjectiveLists]];
+ str += _words[_adjectiveWords[aPtr - _adjectiveLists]]._text;
}
// Add the noun
if (space)
str += " ";
- str += _wordText[_nounWords[noun - 1]];
+ str += _words[_nounWords[noun - 1]]._text;
print(str);
}
@@ -412,5 +414,107 @@ void VM::opVOWEL() {
// No implementation
}
+bool VM::getInput() {
+ if (!parseInput())
+ return false;
+
+ setVariable(V_ACTOR, _actor);
+ setVariable(V_ACTION, _action);
+ setVariable(V_DOBJECT, _dObject);
+ setVariable(V_NDOBJECTS, _ndObjects);
+ setVariable(V_IOBJECT, _iObject);
+ return true;
+}
+
+bool VM::nextCommand() {
+ if (getVariable(V_NDOBJECTS) > 1) {
+ setVariable(V_ACTOR, _actor);
+ setVariable(V_ACTION, _action);
+ setVariable(V_DOBJECT, getVariable(V_DOBJECT) + 1);
+ setVariable(V_NDOBJECTS, getVariable(V_NDOBJECTS) - 1);
+ setVariable(V_IOBJECT, _iObject);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool VM::parseInput() {
+ int noun1 = 0, cnt1 = 0, noun2 = 0, cnt2 = 0;
+ int preposition = 0;
+ bool flag = false;
+
+ // Initialize the parser result fields
+ _actor = _action = _dObject = _iObject = 0;
+ _ndObjects = 0;
+
+ // Get the input line
+ if (!getLine())
+ return false;
+
+ // TODO: stub
+ return false;
+}
+
+bool VM::getLine() {
+ // Let the user type in an input line
+ Common::String line = readLine();
+ if (shouldQuit())
+ return false;
+
+ skipSpaces(line);
+ if (line.empty()) {
+ print(_("Speak up! I can't hear you!\n"));
+ return false;
+ }
+
+ // Get the words of the line
+ _words.clear();
+ while (!line.empty()) {
+ if (!getWord(line))
+ return false;
+ }
+
+ return true;
+}
+
+bool VM::getWord(Common::String &line) {
+ // Find the end of the word
+ const char *wordP = line.c_str();
+ for (; *wordP && !isWhitespace(*wordP); ++wordP) {}
+
+ // Copy out the next word
+ InputWord iw;
+ iw._text = Common::String(line.c_str(), wordP);
+ iw._text.toLowercase();
+
+ // Remove the word from the line
+ line = Common::String(wordP);
+ skipSpaces(line);
+
+ // Look up the word
+ iw._number = findWord(iw._text);
+
+ if (iw._number) {
+ _words.push_back(iw);
+ return false;
+ } else {
+ Common::String msg = Common::String::format(_("I don't know the word \"%s\".\n"), iw._text.c_str());
+ print(msg);
+ return true;
+ }
+}
+
+bool VM::isWhitespace(char c) {
+ return c == ' ' || c == ',' || c == '.';
+}
+
+bool VM::skipSpaces(Common::String &str) {
+ while (!str.empty() && isWhitespace(str[0]))
+ str.deleteChar(0);
+
+ return !str.empty();
+}
+
} // End of namespace AdvSys
} // End of namespace Glk
diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h
index b5c5b48..d235bd8 100644
--- a/engines/glk/advsys/vm.h
+++ b/engines/glk/advsys/vm.h
@@ -187,6 +187,12 @@ public:
* Main VM for AdvSys
*/
class VM : public GlkInterface, public Game {
+ struct InputWord {
+ Common::String _text;
+ int _number;
+
+ InputWord() : _number(0) {}
+ };
private:
// Execution fields
static OpcodeMethod _METHODS[0x34];
@@ -201,7 +207,13 @@ private:
int _adjectiveWords[100];
int _nouns[20];
int _nounWords[20];
- Common::String _wordText[100];
+ int _actor;
+ int _action;
+ int _dObject;
+ int _ndObjects;
+ int _iObject;
+ Common::Array<InputWord> _words;
+ InputWord *_wordPtr;
private:
/**
* Execute a single opcode within the script
@@ -221,6 +233,33 @@ private:
int readCodeWord() {
return getCodeWord(_pc += 2);
}
+
+ /**
+ * Gets an input line and parse it
+ */
+ bool parseInput();
+
+ /**
+ * Gets an input line and splits it up into the words array
+ */
+ bool getLine();
+
+ /**
+ * Get the next word of a passed input line
+ * @param line Input line
+ * @returns True if a valid word was extracted
+ */
+ bool getWord(Common::String &line);
+
+ /**
+ * Returns true if a passed character is a skippable whitespace
+ */
+ static bool isWhitespace(char c);
+
+ /**
+ * Skips over spaces in a passed string
+ */
+ static bool skipSpaces(Common::String &str);
private:
void opBRT();
void opBRF();
@@ -286,6 +325,16 @@ public:
* @returns Script result code
*/
ExecutionResult execute(int offset);
+
+ /**
+ * Get an input line and parse it
+ */
+ bool getInput();
+
+ /**
+ * Get the next command (next direct object)
+ */
+ bool nextCommand();
};
} // End of namespace AdvSys
Commit: 9efb6d71e2ec91cbfa77b236406a9d680e8e44cf
https://github.com/scummvm/scummvm/commit/9efb6d71e2ec91cbfa77b236406a9d680e8e44cf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-06-12T21:30:41-07:00
Commit Message:
GLK: ADVSYS: In progress implementing input line parser
Changed paths:
engines/glk/advsys/game.cpp
engines/glk/advsys/game.h
engines/glk/advsys/vm.cpp
engines/glk/advsys/vm.h
diff --git a/engines/glk/advsys/game.cpp b/engines/glk/advsys/game.cpp
index fe1221b..cd19623 100644
--- a/engines/glk/advsys/game.cpp
+++ b/engines/glk/advsys/game.cpp
@@ -202,7 +202,7 @@ bool Game::match(int obj, int noun, int *adjectives) {
return true;
}
-int Game::checkVerb(int *verbs) {
+int Game::checkVerb(const Common::Array<int> &verbs) {
// Iterate through the actions
for (int idx = 1; idx <= _actionCount; ++idx) {
if (hasVerb(idx, verbs))
@@ -212,7 +212,7 @@ int Game::checkVerb(int *verbs) {
return NIL;
}
-int Game::findAction(int *verbs, int preposition, int flag) {
+int Game::findAction(const Common::Array<int> &verbs, int preposition, int flag) {
// Iterate through the actions
for (int idx = 1; idx <= _actionCount; ++idx) {
if ((preposition && !hasPreposition(idx, preposition)) || !hasVerb(idx, verbs))
@@ -301,23 +301,23 @@ bool Game::hasAdjective(int obj, int adjective) const {
return false;
}
-bool Game::hasVerb(int act, int *verbs) const {
+bool Game::hasVerb(int act, const Common::Array<int> &verbs) const {
// Get the list of verbs
int link = getActionField(act, A_VERBS);
// Look for the verb
for (; link; link = readWord(link + L_NEXT)) {
- int *verb = verbs;
+ Common::Array<int>::const_iterator verb = verbs.begin();
int word = readWord(link + L_DATA);
- for (; *verb && word; link = readWord(link + L_NEXT)) {
+ for (; verb < verbs.end() && word; link = readWord(link + L_NEXT)) {
if (*verb != readWord(word + L_DATA))
break;
++verb;
}
- if (!*verb && !word)
+ if (verb == verbs.end() && !word)
return true;
}
diff --git a/engines/glk/advsys/game.h b/engines/glk/advsys/game.h
index 99cfe26..1b7c6f9 100644
--- a/engines/glk/advsys/game.h
+++ b/engines/glk/advsys/game.h
@@ -46,6 +46,19 @@ enum Action {
};
/**
+ * Word types
+ */
+enum WordType {
+ WT_UNKNOWN = 0,
+ WT_VERB = 1,
+ WT_NOUN = 2,
+ WT_ADJECTIVE = 3,
+ WT_PREPOSITION = 4,
+ WT_CONJUNCTION = 5,
+ WT_ARTICLE = 6
+};
+
+/**
* Object fields
*/
enum ObjectField {
@@ -169,7 +182,7 @@ private:
/**
* Returns true if an action has a given verb
*/
- bool hasVerb(int act, int *verbs) const;
+ bool hasVerb(int act, const Common::Array<int> &verbs) const;
/**
* Returns true if an action is in a given list
@@ -253,8 +266,8 @@ public:
/**
* Return a word's type
*/
- int getWordType(int word) const {
- return _wordTypeTable[word];
+ WordType getWordType(int word) const {
+ return (WordType)_wordTypeTable[word];
}
/**
@@ -265,12 +278,12 @@ public:
/**
* Check to see if this is a valid verb
*/
- int checkVerb(int *verbs);
+ int checkVerb(const Common::Array<int> &verbs);
/**
* Find an action matching a given description
*/
- int findAction(int *verbs, int preposition, int flag);
+ int findAction(const Common::Array<int> &verbs, int preposition, int flag);
/**
* Get an object property
diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp
index 21f79d5..54ab84c 100644
--- a/engines/glk/advsys/vm.cpp
+++ b/engines/glk/advsys/vm.cpp
@@ -85,7 +85,7 @@ 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) {
+ _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);
@@ -452,6 +452,14 @@ bool VM::parseInput() {
if (!getLine())
return false;
+ // Check for actor
+ WordType wordType = getWordType(_words.front());
+ if (wordType == WT_ADJECTIVE || wordType == WT_NOUN) {
+ if (!(_actor = getNoun()))
+ return false;
+ flag |= A_ACTOR;
+ }
+
// TODO: stub
return false;
}
@@ -475,6 +483,7 @@ bool VM::getLine() {
return false;
}
+ _wordPtr = _words.begin();
return true;
}
@@ -505,6 +514,50 @@ bool VM::getWord(Common::String &line) {
}
}
+bool VM::getNoun() {
+ // TODO: Stub
+ return false;
+}
+
+bool VM::getVerb() {
+ _verbs.clear();
+
+ if (_words.front() == NIL || getWordType(_words.front()) != WT_VERB) {
+ parseError();
+ return false;
+ }
+
+ _verbs.push_back(*_wordPtr++);
+
+ // Check for a word following the verb
+ if (!_words.empty()) {
+ _verbs.push_back(_words.front());
+
+ if (checkVerb(_verbs)) {
+ ++_wordPtr;
+ } else {
+ _verbs.push_back(_words.back());
+
+ if (checkVerb(_verbs)) {
+ _words.pop_back();
+ } else {
+ _verbs.pop_back();
+
+ if (!checkVerb(_verbs)) {
+ parseError();
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+void VM::parseError() {
+ // TODO
+}
+
bool VM::isWhitespace(char c) {
return c == ' ' || c == ',' || c == '.';
}
diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h
index d235bd8..d3b7bfc 100644
--- a/engines/glk/advsys/vm.h
+++ b/engines/glk/advsys/vm.h
@@ -113,6 +113,16 @@ enum FPOffset {
FP_ARGS = 3
};
+/**
+ * Action flags
+ */
+enum ActionFlag {
+ A_ACTOR = 1, ///< Actor
+ A_DOBJECT = 2, ///< Direct object
+ A_IOBJECT = 4 ///< Indirect object
+};
+
+
class VM;
typedef void (VM::*OpcodeMethod)();
@@ -192,6 +202,7 @@ class VM : public GlkInterface, public Game {
int _number;
InputWord() : _number(0) {}
+ operator int() const { return _number; }
};
private:
// Execution fields
@@ -213,7 +224,8 @@ private:
int _ndObjects;
int _iObject;
Common::Array<InputWord> _words;
- InputWord *_wordPtr;
+ Common::Array<InputWord>::iterator _wordPtr;
+ Common::Array<int> _verbs;
private:
/**
* Execute a single opcode within the script
@@ -252,6 +264,21 @@ private:
bool getWord(Common::String &line);
/**
+ * Get a noun phrase and return the object it refers to
+ */
+ bool getNoun();
+
+ /**
+ * Get a verb phrase and return the action it refers to
+ */
+ bool getVerb();
+
+ /**
+ * Called when a parsing error occurs
+ */
+ void parseError();
+
+ /**
* Returns true if a passed character is a skippable whitespace
*/
static bool isWhitespace(char c);
Commit: 0e543b06823e629a007bad26f94d452bfb38abf1
https://github.com/scummvm/scummvm/commit/0e543b06823e629a007bad26f94d452bfb38abf1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-06-12T21:45:54-07:00
Commit Message:
GLK: ADVSYS: Noun/adjectives setup and getNoun method
Changed paths:
engines/glk/advsys/game.cpp
engines/glk/advsys/game.h
engines/glk/advsys/vm.cpp
engines/glk/advsys/vm.h
diff --git a/engines/glk/advsys/game.cpp b/engines/glk/advsys/game.cpp
index cd19623..50b258d 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<int> &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 1b7c6f9..5920f41 100644
--- a/engines/glk/advsys/game.h
+++ b/engines/glk/advsys/game.h
@@ -170,16 +170,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
*/
bool hasVerb(int act, const Common::Array<int> &verbs) const;
@@ -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;
@@ -271,11 +271,6 @@ public:
}
/**
- * 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
*/
int checkVerb(const Common::Array<int> &verbs);
diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp
index 54ab84c..bbe958a 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 d3b7bfc..6a877c9 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<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,7 +276,7 @@ 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
@@ -274,6 +284,11 @@ private:
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
*/
void parseError();
Commit: 86126974096e14ff54aaa75fbb9cd5e4b9b5420d
https://github.com/scummvm/scummvm/commit/86126974096e14ff54aaa75fbb9cd5e4b9b5420d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-06-12T22:15:58-07:00
Commit Message:
GLK: ADVSYS: Remainder of parseInput method
Changed paths:
engines/glk/advsys/vm.cpp
diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp
index bbe958a..17db9ab 100644
--- a/engines/glk/advsys/vm.cpp
+++ b/engines/glk/advsys/vm.cpp
@@ -436,8 +436,7 @@ bool VM::nextCommand() {
bool VM::parseInput() {
int noun1 = 0, cnt1 = 0, noun2 = 0, cnt2 = 0;
- int preposition = 0;
- bool flag = false;
+ int preposition = 0, flags = 0;
// Initialize the parser result fields
_actor = _action = _dObject = _iObject = 0;
@@ -450,15 +449,100 @@ bool VM::parseInput() {
return false;
// Check for actor
- WordType wordType = getWordType(_words.front());
+ WordType wordType = getWordType(*_wordPtr);
if (wordType == WT_ADJECTIVE || wordType == WT_NOUN) {
if (!(_actor = getNoun()))
return false;
- flag |= A_ACTOR;
+ flags |= A_ACTOR;
}
- // TODO: stub
- return false;
+ // Check for a verb
+ if (getVerb())
+ return false;
+
+ // Get direct object, preposition, and/or indirect object
+ if (_wordPtr != _words.end()) {
+ // Get any direct objects
+ noun1 = _adjectiveList.size();
+ for (;;) {
+ // Get the next direct object
+ if (!getNoun())
+ return false;
+ ++cnt1;
+
+ // Check for more direct objects
+ if (_wordPtr == _words.end() || getWordType(*_wordPtr))
+ break;
+ ++_wordPtr;
+ }
+
+ // Get any reposition and indirect object
+ if (_wordPtr != _words.end()) {
+ // Get the preposition
+ if (getWordType(*_wordPtr) == WT_PREPOSITION)
+ preposition = *_wordPtr++;
+
+ // Get the indirect object
+ noun2 = _adjectiveList.size();
+ for (;;) {
+ // Get the indirect object
+ if (!getNoun())
+ return false;
+ ++cnt2;
+
+ // Check for more objects
+ if (_wordPtr == _words.end() || getWordType(*_wordPtr) != WT_CONJUNCTION)
+ break;
+ ++_wordPtr;
+ }
+ }
+
+ // Ensure we're at the end of the input line
+ if (_wordPtr != _words.end()) {
+ parseError();
+ return false;
+ }
+ }
+
+ // Setup resulting properties
+ if (preposition) {
+ if (cnt2 > 1) {
+ parseError();
+ return false;
+ }
+
+ _dObject = noun1;
+ _ndObjects = cnt1;
+ _iObject = noun2;
+ }
+ else if (noun2) {
+ if (cnt1 > 1) {
+ parseError();
+ return false;
+ }
+
+ preposition = findWord("to");
+ _dObject = noun2;
+ _ndObjects = cnt2;
+ _iObject = noun1;
+ } else {
+ _dObject = noun1;
+ _ndObjects = cnt1;
+ }
+
+ // Setup the flags for the action lookup
+ if (_dObject)
+ flags |= A_DOBJECT;
+ if (_iObject)
+ flags |= A_IOBJECT;
+
+ // Find the action
+ if (!(_action == findAction(_verbs, preposition, flags))) {
+ parseError();
+ return false;
+ }
+
+ return true;
}
bool VM::getLine() {
Commit: 06ffbab3c5450632de367bbea5a1a47fdc4300ff
https://github.com/scummvm/scummvm/commit/06ffbab3c5450632de367bbea5a1a47fdc4300ff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-06-12T22:26:06-07:00
Commit Message:
GLK: ADVSYS: Added singleAction method
Changed paths:
engines/glk/advsys/advsys.cpp
engines/glk/advsys/advsys.h
diff --git a/engines/glk/advsys/advsys.cpp b/engines/glk/advsys/advsys.cpp
index 3f50d84..26f298d 100644
--- a/engines/glk/advsys/advsys.cpp
+++ b/engines/glk/advsys/advsys.cpp
@@ -26,12 +26,6 @@
namespace Glk {
namespace AdvSys {
-bool singleAction() {
- // TODO: Stub
- return false;
-}
-
-
void AdvSys::runGame() {
if (!initialize()) {
GUIErrorMessage(_("Could not start AdvSys game"));
@@ -75,6 +69,28 @@ bool AdvSys::initialize() {
void AdvSys::deinitialize() {
}
+bool AdvSys::singleAction() {
+ // Do the before code
+ switch (execute(_beforeOffset)) {
+ case ABORT:
+ // Script aborted
+ return false;
+ case CHAIN:
+ // Execute the action handler
+ if (execute(getActionField(getVariable(V_ACTION), A_CODE)) == ABORT)
+ return false;
+
+ // fall through
+ case FINISH:
+ // Do the after code
+ if (execute(_afterOffset) == ABORT)
+ return false;
+ break;
+ }
+
+ return true;
+}
+
Common::Error AdvSys::loadGameData(strid_t save) {
return Common::kNoError;
}
diff --git a/engines/glk/advsys/advsys.h b/engines/glk/advsys/advsys.h
index 50977a6..688a8fe 100644
--- a/engines/glk/advsys/advsys.h
+++ b/engines/glk/advsys/advsys.h
@@ -43,6 +43,11 @@ private:
* Engine cleanup
*/
void deinitialize();
+
+ /**
+ * Handle a single action
+ */
+ bool singleAction();
public:
/**
* Constructor
More information about the Scummvm-git-logs
mailing list