[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