GLK: ADVSYS: Added input line split up and tokenizing

This commit is contained in:
Paul Gilbert 2019-06-10 22:40:13 -07:00
parent 9c0771552d
commit 4e74751e7e
5 changed files with 162 additions and 18 deletions

View file

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

View file

@ -39,7 +39,7 @@ void GlkInterface::print(int number) {
print(s);
}
Common::String GlkInterface::getLine() {
Common::String GlkInterface::readLine() {
// TODO: Stub
return "";
}

View file

@ -56,7 +56,7 @@ protected:
/**
* Get an input line
*/
Common::String getLine();
Common::String readLine();
public:
/**
* Constructor

View file

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

View file

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