aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/advsys
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/advsys')
-rw-r--r--engines/glk/advsys/game.cpp12
-rw-r--r--engines/glk/advsys/game.h23
-rw-r--r--engines/glk/advsys/vm.cpp55
-rw-r--r--engines/glk/advsys/vm.h29
4 files changed, 106 insertions, 13 deletions
diff --git a/engines/glk/advsys/game.cpp b/engines/glk/advsys/game.cpp
index fe1221baf7..cd19623f5d 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 99cfe26068..1b7c6f95b0 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 21f79d596b..54ab84c9c6 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 d235bd878d..d3b7bfc8f6 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);