aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorEugene Sandulenko2015-12-23 18:39:26 +0100
committerEugene Sandulenko2015-12-27 15:41:00 +0100
commit29cb01f71c5947f77d57c686666132db705593dc (patch)
tree0193d645a420f05d495fc3ebfb6cd4c82d378c1b /engines
parenta2ac4ea859da2257bba0d60f466be4037204d4d9 (diff)
downloadscummvm-rg350-29cb01f71c5947f77d57c686666132db705593dc.tar.gz
scummvm-rg350-29cb01f71c5947f77d57c686666132db705593dc.tar.bz2
scummvm-rg350-29cb01f71c5947f77d57c686666132db705593dc.zip
WAGE: Unstubbed Script::eval()
Diffstat (limited to 'engines')
-rw-r--r--engines/wage/script.cpp239
-rw-r--r--engines/wage/script.h22
-rw-r--r--engines/wage/wage.cpp10
3 files changed, 219 insertions, 52 deletions
diff --git a/engines/wage/script.cpp b/engines/wage/script.cpp
index eb500d7df0..b9e51c082a 100644
--- a/engines/wage/script.cpp
+++ b/engines/wage/script.cpp
@@ -201,79 +201,79 @@ Script::Operand *Script::readOperand() {
Context *cont = &_world->_player->_context;
switch (operandType) {
case 0xA0: // TEXT$
- return new Operand(_inputText, Operand::TEXT_INPUT);
+ return new Operand(_inputText, TEXT_INPUT);
case 0xA1:
- return new Operand(_inputClick, Operand::CLICK_INPUT);
+ return new Operand(_inputClick, CLICK_INPUT);
case 0xC0: // STORAGE@
- return new Operand(&_world->_storageScene, Operand::SCENE);
+ return new Operand(&_world->_storageScene, SCENE);
case 0xC1: // SCENE@
- return new Operand(_world->_player->_currentScene, Operand::SCENE);
+ return new Operand(_world->_player->_currentScene, SCENE);
case 0xC2: // PLAYER@
- return new Operand(_world->_player, Operand::CHR);
+ return new Operand(_world->_player, CHR);
case 0xC3: // MONSTER@
- return new Operand(_callbacks->_monster, Operand::CHR);
+ return new Operand(_callbacks->_monster, CHR);
case 0xC4: // RANDOMSCN@
- return new Operand(_world->_orderedScenes[_callbacks->_rnd->getRandomNumber(_world->_orderedScenes.size())], Operand::SCENE);
+ return new Operand(_world->_orderedScenes[_callbacks->_rnd->getRandomNumber(_world->_orderedScenes.size())], SCENE);
case 0xC5: // RANDOMCHR@
- return new Operand(_world->_orderedChrs[_callbacks->_rnd->getRandomNumber(_world->_orderedChrs.size())], Operand::CHR);
+ return new Operand(_world->_orderedChrs[_callbacks->_rnd->getRandomNumber(_world->_orderedChrs.size())], CHR);
case 0xC6: // RANDOMOBJ@
- return new Operand(_world->_orderedObjs[_callbacks->_rnd->getRandomNumber(_world->_orderedObjs.size())], Operand::OBJ);
+ return new Operand(_world->_orderedObjs[_callbacks->_rnd->getRandomNumber(_world->_orderedObjs.size())], OBJ);
case 0xB0: // VISITS#
- return new Operand(cont->_visits, Operand::NUMBER);
+ return new Operand(cont->_visits, NUMBER);
case 0xB1: // RANDOM# for Star Trek, but VISITS# for some other games?
- return new Operand(1 + _callbacks->_rnd->getRandomNumber(100), Operand::NUMBER);
+ return new Operand(1 + _callbacks->_rnd->getRandomNumber(100), NUMBER);
case 0xB5: // RANDOM# // A random number between 1 and 100.
- return new Operand(1 + _callbacks->_rnd->getRandomNumber(100), Operand::NUMBER);
+ return new Operand(1 + _callbacks->_rnd->getRandomNumber(100), NUMBER);
case 0xB2: // LOOP#
- return new Operand(_loopCount, Operand::NUMBER);
+ return new Operand(_loopCount, NUMBER);
case 0xB3: // VICTORY#
- return new Operand(cont->_kills, Operand::NUMBER);
+ return new Operand(cont->_kills, NUMBER);
case 0xB4: // BADCOPY#
- return new Operand(0, Operand::NUMBER); // ????
+ return new Operand(0, NUMBER); // ????
case 0xFF:
{
// user variable
int value = _data->readByte();
// TODO: Verify that we're using the right index.
- return new Operand(cont->_userVariables[value - 1], Operand::NUMBER);
+ return new Operand(cont->_userVariables[value - 1], NUMBER);
}
case 0xD0:
- return new Operand(cont->_statVariables[Context::PHYS_STR_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_STR_BAS], NUMBER);
case 0xD1:
- return new Operand(cont->_statVariables[Context::PHYS_HIT_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_HIT_BAS], NUMBER);
case 0xD2:
- return new Operand(cont->_statVariables[Context::PHYS_ARM_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_ARM_BAS], NUMBER);
case 0xD3:
- return new Operand(cont->_statVariables[Context::PHYS_ACC_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_ACC_BAS], NUMBER);
case 0xD4:
- return new Operand(cont->_statVariables[Context::SPIR_STR_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_STR_BAS], NUMBER);
case 0xD5:
- return new Operand(cont->_statVariables[Context::SPIR_HIT_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_HIT_BAS], NUMBER);
case 0xD6:
- return new Operand(cont->_statVariables[Context::SPIR_ARM_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_ARM_BAS], NUMBER);
case 0xD7:
- return new Operand(cont->_statVariables[Context::SPIR_ACC_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_ACC_BAS], NUMBER);
case 0xD8:
- return new Operand(cont->_statVariables[Context::PHYS_SPE_BAS], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_SPE_BAS], NUMBER);
case 0xE0:
- return new Operand(cont->_statVariables[Context::PHYS_STR_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_STR_CUR], NUMBER);
case 0xE1:
- return new Operand(cont->_statVariables[Context::PHYS_HIT_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_HIT_CUR], NUMBER);
case 0xE2:
- return new Operand(cont->_statVariables[Context::PHYS_ARM_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_ARM_CUR], NUMBER);
case 0xE3:
- return new Operand(cont->_statVariables[Context::PHYS_ACC_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_ACC_CUR], NUMBER);
case 0xE4:
- return new Operand(cont->_statVariables[Context::SPIR_STR_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_STR_CUR], NUMBER);
case 0xE5:
- return new Operand(cont->_statVariables[Context::SPIR_HIT_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_HIT_CUR], NUMBER);
case 0xE6:
- return new Operand(cont->_statVariables[Context::SPIR_ARM_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_ARM_CUR], NUMBER);
case 0xE7:
- return new Operand(cont->_statVariables[Context::SPIR_ACC_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::SPIR_ACC_CUR], NUMBER);
case 0xE8:
- return new Operand(cont->_statVariables[Context::PHYS_SPE_CUR], Operand::NUMBER);
+ return new Operand(cont->_statVariables[Context::PHYS_SPE_CUR], NUMBER);
default:
if (operandType >= 0x20 && operandType < 0x80) {
_data->seek(-1, SEEK_CUR);
@@ -371,11 +371,11 @@ Script::Operand *Script::readStringOperand() {
int r = atol(sb->c_str());
delete sb;
- return new Operand(r, Operand::NUMBER);
+ return new Operand(r, NUMBER);
} else {
// TODO: This string could be a room name or something like that.
debug(0, "Read string %s", sb->c_str());
- return new Operand(sb, Operand::STRING);
+ return new Operand(sb, STRING);
}
}
@@ -484,8 +484,173 @@ void Script::skipBlock() {
}
}
+enum {
+ kCompEqNumNum,
+ kCompEqObjScene,
+ kCompEqChrScene,
+ kCompEqObjChr,
+ kCompEqChrChr,
+ kCompEqSceneScene,
+ kCompEqStringTextInput,
+ kCompEqTextInputString,
+ kCompEqNumberTextInput,
+ kCompEqTextInputNumber,
+ kCompLtNumNum,
+ kCompLtStringTextInput,
+ kCompLtTextInputString,
+ kCompLtObjChr,
+ kCompLtChrObj,
+ kCompLtObjScene,
+ kCompGtNumNum,
+ kCompGtStringString,
+ kCompGtChrScene
+};
+
+struct Comparator {
+ char operation;
+ OperandTypes o1;
+ OperandTypes o2;
+ int compfunc;
+} static comparators[] = {
+ { '=', NUMBER, NUMBER, kCompEqNumNum },
+ { '=', OBJ, SCENE, kCompEqObjScene },
+ { '=', CHR, SCENE, kCompEqChrScene },
+ { '=', OBJ, CHR, kCompEqObjChr },
+ { '=', CHR, CHR, kCompEqChrChr },
+ { '=', SCENE, SCENE, kCompEqSceneScene },
+ { '=', STRING, TEXT_INPUT, kCompEqStringTextInput },
+ { '=', TEXT_INPUT, STRING, kCompEqTextInputString },
+ { '=', NUMBER, TEXT_INPUT, kCompEqNumberTextInput },
+ { '=', TEXT_INPUT, NUMBER, kCompEqTextInputNumber },
+
+ { '<', NUMBER, NUMBER, kCompLtNumNum },
+ { '<', STRING, TEXT_INPUT, kCompLtStringTextInput },
+ { '<', TEXT_INPUT, STRING, kCompLtTextInputString },
+ { '<', OBJ, CHR, kCompLtObjChr },
+ { '<', CHR, OBJ, kCompLtChrObj },
+ { '<', OBJ, SCENE, kCompLtObjScene },
+ { '<', CHR, CHR, kCompEqChrChr }, // Same logic as =
+ { '<', SCENE, SCENE, kCompEqSceneScene },
+
+ { '>', NUMBER, NUMBER, kCompGtNumNum },
+ { '>', TEXT_INPUT, STRING, kCompLtTextInputString }, // Same logic as <
+ //FIXME: this prevents the below cases from working due to exact
+ //matches taking precedence over conversions...
+ //{ '>', STRING, STRING, kCompGtStringString }, // Same logic as <
+ { '>', OBJ, CHR, kCompLtObjChr }, // Same logic as <
+ { '>', OBJ, SCENE, kCompLtObjScene }, // Same logic as <
+ { '>', CHR, SCENE, kCompGtChrScene },
+ { 0, OBJ, OBJ, 0 }
+};
+
+bool Script::compare(Operand *o1, Operand *o2, int comparator) {
+ switch(comparator) {
+ case kCompEqNumNum:
+ return o1->_value.number == o2->_value.number;
+ case kCompEqObjScene:
+ error("FIXME kCompEqObjScene");
+ //return o2->_value.scene->_objs.contains(*o1->_value.obj);
+ case kCompEqChrScene:
+ error("FIXME kCompEqChrScene");
+ //return o2->_value.scene->_chrs.contains(*o1->_value.chr);
+ case kCompEqObjChr:
+ error("FIXME kCompEqObjChr");
+ //return o2->_value.chr->_inventory.contains(*o1->_value.obj);
+ case kCompEqChrChr:
+ return o1->_value.chr == o2->_value.chr;
+ case kCompEqSceneScene:
+ return o1->_value.scene == o2->_value.scene;
+ case kCompEqStringTextInput:
+ if (_inputText == NULL) {
+ return false;
+ } else {
+ Common::String s1(*_inputText), s2(*o1->_value.string);
+ s1.toLowercase();
+ s2.toLowercase();
+
+ return s1.contains(s2);
+ }
+ case kCompEqTextInputString:
+ return compare(o2, o1, kCompEqStringTextInput);
+ case kCompEqNumberTextInput:
+ if (_inputText == NULL) {
+ return false;
+ } else {
+ Common::String s1(*_inputText), s2(o1->toString());
+ s1.toLowercase();
+ s2.toLowercase();
+
+ return s1.contains(s2);
+ }
+ case kCompEqTextInputNumber:
+ if (_inputText == NULL) {
+ return false;
+ } else {
+ Common::String s1(*_inputText), s2(o2->toString());
+ s1.toLowercase();
+ s2.toLowercase();
+
+ return s1.contains(s2);
+ }
+ case kCompLtNumNum:
+ return o1->_value.number < o2->_value.number;
+ case kCompLtStringTextInput:
+ return !compare(o1, o2, kCompEqStringTextInput);
+ case kCompLtTextInputString:
+ return !compare(o2, o1, kCompEqStringTextInput);
+ case kCompLtObjChr:
+ return o1->_value.obj->_currentOwner != o2->_value.chr;
+ case kCompLtChrObj:
+ return compare(o2, o1, kCompLtObjChr);
+ case kCompLtObjScene:
+ return o1->_value.obj->_currentScene != o2->_value.scene;
+ case kCompGtNumNum:
+ return o1->_value.number > o2->_value.number;
+ case kCompGtStringString:
+ return o1->_value.string == o2->_value.string;
+ case kCompGtChrScene:
+ return (o1->_value.chr != NULL && o1->_value.chr->_currentScene != o2->_value.scene);
+ }
+
+ return false;
+}
+
bool Script::eval(Operand *lhs, const char *op, Operand *rhs) {
- warning("STUB: eval");
+ bool result = false;
+
+ if (lhs->_type == CLICK_INPUT || rhs->_type == CLICK_INPUT) {
+ return evalClickCondition(lhs, op, rhs);
+ } else if (!strcmp(op, "==") || !strcmp(op, ">>")) {
+ // TODO: check if >> can be used for click inputs and if == can be used for other things
+ // exact string match
+ if (lhs->_type == TEXT_INPUT) {
+ if ((rhs->_type != STRING && rhs->_type != NUMBER) || _inputText == NULL) {
+ result = false;
+ } else {
+ result = _inputText->equalsIgnoreCase(rhs->toString());
+ }
+ } else if (rhs->_type == TEXT_INPUT) {
+ if ((lhs->_type != STRING && lhs->_type != NUMBER) || _inputText == NULL) {
+ result = false;
+ } else {
+ result = _inputText->equalsIgnoreCase(lhs->toString());
+ }
+ } else {
+ error("UNHANDLED CASE: [lhs=%d/%s, rhs=%d/%s]",
+ lhs->_type, lhs->toString().c_str(), rhs->_type, rhs->toString().c_str());
+ }
+ if (!strcmp(op, ">>")) {
+ result = !result;
+ }
+
+ return result;
+ }
+
+ return false;
+}
+
+bool Script::evalClickCondition(Operand *lhs, const char *op, Operand *rhs) {
+ warning("STUB: evalClickCondition");
return false;
}
diff --git a/engines/wage/script.h b/engines/wage/script.h
index 1c69eb093b..d1d3d217ad 100644
--- a/engines/wage/script.h
+++ b/engines/wage/script.h
@@ -50,6 +50,16 @@
namespace Wage {
+enum OperandTypes {
+ OBJ = 0,
+ CHR = 1,
+ SCENE = 2,
+ NUMBER = 3,
+ STRING = 4,
+ CLICK_INPUT = 5,
+ TEXT_INPUT = 6
+};
+
class Script {
public:
Script(Common::SeekableReadStream *data) : _data(data) {}
@@ -68,16 +78,6 @@ private:
class Operand {
public:
- enum OperandTypes {
- OBJ = 0,
- CHR = 1,
- SCENE = 2,
- NUMBER = 3,
- STRING = 4,
- CLICK_INPUT = 5,
- TEXT_INPUT = 6
- };
-
union {
Obj *obj;
Chr *chr;
@@ -156,7 +156,9 @@ private:
void processIf();
void skipBlock();
void skipIf();
+ bool compare(Operand *o1, Operand *o2, int comparator);
bool eval(Operand *lhs, const char *op, Operand *rhs);
+ bool evalClickCondition(Operand *lhs, const char *op, Operand *rhs);
void processMove();
void processLet();
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index 5ab2a90ac1..533b30f4e3 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -113,11 +113,11 @@ Common::Error WageEngine::run() {
Common::String input("look");
_world->_globalScript->execute(_world, 1, &input, NULL, this);
- _world->_orderedScenes[1]->_design->paint(&screen, _world->_patterns, false);
- _world->_objs["frank.1"]->_design->setBounds(&r);
- _world->_objs["frank.1"]->_design->paint(&screen, _world->_patterns, false);
- _world->_scenes["temple of the holy mackeral"]->_design->setBounds(&r);
- _world->_scenes["temple of the holy mackeral"]->_design->paint(&screen, _world->_patterns, false);
+ //_world->_orderedScenes[1]->_design->paint(&screen, _world->_patterns, false);
+ //_world->_objs["frank.1"]->_design->setBounds(&r);
+ //_world->_objs["frank.1"]->_design->paint(&screen, _world->_patterns, false);
+ //_world->_scenes["temple of the holy mackeral"]->_design->setBounds(&r);
+ //_world->_scenes["temple of the holy mackeral"]->_design->paint(&screen, _world->_patterns, false);
//_world->_scenes["tower level 3"]->_design->setBounds(&r);
//_world->_scenes["tower level 3"]->_design->paint(&screen, _world->_patterns, false);