aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2019-06-10 22:40:13 -0700
committerPaul Gilbert2019-06-12 21:30:41 -0700
commit4e74751e7e40e0a3ddada4b4266c845004d2498d (patch)
treeffbdb38cb311e79cb6a9184d8fa9e00ebeb262fa
parent9c0771552d97f8e8aec1ba93d7ff689b0e58a64c (diff)
downloadscummvm-rg350-4e74751e7e40e0a3ddada4b4266c845004d2498d.tar.gz
scummvm-rg350-4e74751e7e40e0a3ddada4b4266c845004d2498d.tar.bz2
scummvm-rg350-4e74751e7e40e0a3ddada4b4266c845004d2498d.zip
GLK: ADVSYS: Added input line split up and tokenizing
-rw-r--r--engines/glk/advsys/advsys.cpp11
-rw-r--r--engines/glk/advsys/glk_interface.cpp2
-rw-r--r--engines/glk/advsys/glk_interface.h2
-rw-r--r--engines/glk/advsys/vm.cpp114
-rw-r--r--engines/glk/advsys/vm.h51
5 files changed, 162 insertions, 18 deletions
diff --git a/engines/glk/advsys/advsys.cpp b/engines/glk/advsys/advsys.cpp
index 0c63ff8dfb..3f50d84237 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 800d70836e..6ec5a08547 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 44f3db9939..95dcfa8fc5 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 53950fc5a4..21f79d596b 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 b5c5b48463..d235bd878d 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