aboutsummaryrefslogtreecommitdiff
path: root/engines/avalanche/acci2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/avalanche/acci2.cpp')
-rw-r--r--engines/avalanche/acci2.cpp2098
1 files changed, 2098 insertions, 0 deletions
diff --git a/engines/avalanche/acci2.cpp b/engines/avalanche/acci2.cpp
new file mode 100644
index 0000000000..ad32ebdaed
--- /dev/null
+++ b/engines/avalanche/acci2.cpp
@@ -0,0 +1,2098 @@
+ /* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+ * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+ */
+
+/* ACCIDENCE II The parser. */
+
+#include "avalanche/avalanche.h"
+
+#include "avalanche/acci2.h"
+#include "avalanche/gyro2.h"
+#include "avalanche/lucerna2.h"
+#include "avalanche/scrolls2.h"
+#include "avalanche/visa2.h"
+#include "avalanche/timer.h"
+#include "avalanche/animation.h"
+#include "avalanche/enid2.h"
+#include "avalanche/celer2.h"
+#include "avalanche/pingo2.h"
+#include "avalanche/sequence2.h"
+
+#include "common/textconsole.h"
+
+#include <cstring>
+#include <cmath>
+
+namespace Avalanche {
+
+const Acci::VocabEntry Acci::kVocabulary[kParserWordsNum] = {
+ // Verbs: 1-49
+ {1, "EXAMINE"}, {1, "READ"}, {1, "XAM"}, // short
+ {2, "OPEN"}, {2, "LEAVE"}, {2, "UNLOCK"},
+ {3, "PAUSE"}, {47, "TA"}, // Early to avoid Take and Talk.
+ {4, "TAKE"}, {4, "GET"}, {4, "PICK"},
+ {5, "DROP"}, {6, "INVENTORY"}, {7, "TALK"},
+ {7, "SAY"}, {7, "ASK"},
+ {8, "GIVE"}, {9, "DRINK"}, {9, "IMBIBE"},
+ {9, "DRAIN"}, {10, "LOAD"}, {10, "RESTORE"},
+ {11, "SAVE"}, {12, "BRIBE"}, {12, "PAY"},
+ {13, "LOOK"}, {14, "BREAK"}, {15, "QUIT"},
+ {15, "EXIT"}, {16, "SIT"}, {16, "SLEEP"},
+ {17, "STAND"},
+ {18, "GO"}, {19, "INFO"}, {20, "UNDRESS"},
+ {20, "DOFF"},
+ {21, "DRESS"}, {21, "WEAR"}, {21, "DON"},
+ {22, "PLAY"},
+ {22, "STRUM"}, {23, "RING"}, {24, "HELP"},
+ {25, "KENDAL"}, {26, "CAPYBARA"}, {27, "BOSS"},
+ {255, "NINET"}, // block for NINETY
+ {28, "URINATE"}, {28, "MINGITE"}, {29, "NINETY"},
+ {30, "ABRACADABRA"}, {30, "PLUGH"}, {30, "XYZZY"},
+ {30, "HOCUS"}, {30, "POCUS"}, {30, "IZZY"},
+ {30, "WIZZY"}, {30, "PLOVER"},
+ {30, "MELENKURION"}, {30, "ZORTON"}, {30, "BLERBI"},
+ {30, "THURB"}, {30, "SNOEZE"}, {30, "SAMOHT"},
+ {30, "NOSIDE"}, {30, "PHUGGG"}, {30, "KNERL"},
+ {30, "MAGIC"}, {30, "KLAETU"}, {30, "VODEL"},
+ {30, "BONESCROLLS"}, {30, "RADOF"},
+ {31, "RESTART"},
+ {32, "SWALLOW"}, {32, "EAT"}, {33, "LISTEN"},
+ {33, "HEAR"}, {34, "BUY"}, {34, "PURCHASE"},
+ {34, "ORDER"}, {34, "DEMAND"},
+ {35, "ATTACK"}, {35, "HIT"}, {35, "KILL"},
+ {35, "PUNCH"}, {35, "KICK"}, {35, "SHOOT"},
+ {35, "FIRE"},
+
+ // Passwords: 36
+ {36, "TIROS"}, {36, "WORDY"}, {36, "STACK"},
+ {36, "SHADOW"}, {36, "OWL"}, {36, "ACORN"},
+ {36, "DOMESDAY"}, {36, "FLOPPY"}, {36, "DIODE"},
+ {36, "FIELD"}, {36, "COWSLIP"}, {36, "OSBYTE"},
+ {36, "OSCLI"}, {36, "TIMBER"}, {36, "ADVAL"},
+ {36, "NEUTRON"}, {36, "POSITRON"}, {36, "ELECTRON"},
+ {36, "CIRCUIT"}, {36, "AURUM"}, {36, "PETRIFY"},
+ {36, "EBBY"}, {36, "CATAPULT"}, {36, "GAMERS"},
+ {36, "FUDGE"}, {36, "CANDLE"}, {36, "BEEB"},
+ {36, "MICRO"}, {36, "SESAME"}, {36, "LORDSHIP"},
+ {37, "DIR"}, {37, "LS"}, {38, "DIE"},
+ {39, "SCORE"},
+ {40, "PUT"}, {40, "INSERT"}, {41, "KISS"},
+ {41, "SNOG"}, {41, "CUDDLE"}, {42, "CLIMB"},
+ {42, "CLAMBER"}, {43, "JUMP"}, {44, "HIGHSCORES"},
+ {44, "HISCORES"}, {45, "WAKEN"}, {45, "AWAKEN"},
+ {46, "HELLO"}, {46, "HI"}, {46, "YO"},
+ {47, "THANKS"}, // = 47, "ta", which was defined earlier.
+
+ // Nouns - Objects: 50-100
+ {50, "WINE"}, {50, "BOOZE"}, {50, "NASTY"},
+ {50, "VINEGAR"}, {51, "MONEYBAG"},
+ {51, "BAG"}, {51, "CASH"}, {51, "DOSH"},
+ {51, "WALLET"},
+ {52, "BODKIN"}, {52, "DAGGER"}, {53, "POTION"},
+ {54, "CHASTITY"}, {54, "BELT"}, {55, "BOLT"},
+ {55, "ARROW"}, {55, "DART"},
+ {56, "CROSSBOW"}, {56, "BOW"}, {57, "LUTE"},
+ {58, "PILGRIM"}, {58, "BADGE"}, {59, "MUSHROOMS"},
+ {59, "TOADSTOOLS"}, {60, "KEY"}, {61, "BELL"},
+ {62, "PRESCRIPT"}, {62, "SCROLL"}, {62, "MESSAGE"},
+ {63, "PEN"}, {63, "QUILL"}, {64, "INK"},
+ {64, "INKPOT"}, {65, "CLOTHES"}, {66, "HABIT"},
+ {66, "DISGUISE"}, {67, "ONION"},
+ {99, "PASSWORD"},
+
+ // Objects from Also are placed between 101 and 131.
+
+ // Nouns - People - Male: 150-174
+ {150, "AVVY"}, {150, "AVALOT"}, {150, "YOURSELF"},
+ {150, "ME"}, {150, "MYSELF"}, {151, "SPLUDWICK"},
+ {151, "THOMAS"}, {151, "ALCHEMIST"}, {151, "CHEMIST"},
+ {152, "CRAPULUS"}, {152, "SERF"}, {152, "SLAVE"},
+ {158, "DU"}, // <<< Put in early for Baron DU Lustie to save confusion with Duck & Duke.
+ {152, "CRAPPY"}, {153, "DUCK"}, {153, "DOCTOR"},
+ {154, "MALAGAUCHE"},
+ {155, "FRIAR"}, {155, "TUCK"}, {156, "ROBIN"},
+ {156, "HOOD"}, {157, "CWYTALOT"}, {157, "GUARD"},
+ {157, "BRIDGEKEEP"}, {158, "BARON"}, {158, "LUSTIE"},
+ {159, "DUKE"}, {159, "GRACE"}, {160, "DOGFOOD"},
+ {160, "MINSTREL"}, {161, "TRADER"}, {161, "SHOPKEEPER"},
+ {161, "STALLHOLDER"},
+ {162, "PILGRIM"}, {162, "IBYTHNETH"}, {163, "ABBOT"},
+ {163, "AYLES"}, {164, "PORT"}, {165, "SPURGE"},
+ {166, "JACQUES"}, {166, "SLEEPER"}, {166, "RINGER"},
+
+ // Nouns - People - Female: 175-199
+ {175, "WIFE"}, {175, "ARKATA"}, {176, "GEDALODAVA"},
+ {176, "GEIDA"}, {176, "PRINCESS"}, {178, "WISE"},
+ {178, "WITCH"},
+
+ // Pronouns: 200-224
+ {200, "HIM"}, {200, "MAN"}, {200, "GUY"},
+ {200, "DUDE"}, {200, "CHAP"}, {200, "FELLOW"},
+ {201, "HER"}, {201, "GIRL"}, {201, "WOMAN"},
+ {202, "IT"}, {202, "THING"},
+ {203, "MONK"}, {204, "BARMAN"}, {204, "BARTENDER"},
+
+ // Prepositions: 225-249
+ {225, "TO"}, {226, "AT"}, {227, "UP"},
+ {228, "INTO"}, {228, "INSIDE"}, {229, "OFF"},
+ {230, "UP"}, {231, "DOWN"}, {232, "ON"},
+
+ // Please: 251
+ {251, "PLEASE"},
+
+ // About: 252
+ {252, "ABOUT"}, {252, "CONCERNING"},
+
+ // Swear words: 253
+ /* I M P O R T A N T M E S S A G E
+
+ DO *NOT* READ THE LINES BELOW IF YOU ARE OF A SENSITIVE
+ DISPOSITION. THOMAS IS *NOT* RESPONSIBLE FOR THEM.
+ GOODNESS KNOWS WHO WROTE THEM.
+ READ THEM AT YOUR OWN RISK. BETTER STILL, DON'T READ THEM.
+ WHY ARE YOU SNOOPING AROUND IN MY PROGRAM, ANYWAY? */
+
+ {253, "SHIT"}, {28 , "PISS"}, {28 , "PEE"},
+ {253, "FART"}, {253, "FUCK"}, {253, "BALLS"},
+ {253, "BLAST"}, {253, "BUGGER"}, {253, "KNICKERS"},
+ {253, "BLOODY"}, {253, "HELL"}, {253, "DAMN"},
+ {253, "SMEG"},
+ // ...and other even ruder words. You didn't read them, did you? Good. */
+
+ // Answer-back smart-alec words: 249
+ {249, "YES"}, {249, "NO"}, {249, "BECAUSE"},
+
+ // Noise words: 255
+ {255, "THE"}, {255, "A"}, {255, "NOW"},
+ {255, "SOME"}, {255, "AND"}, {255, "THAT"},
+ {255, "POCUS"}, {255, "HIS"},
+ {255, "THIS"}, {255, "SENTINEL"} // for "Ken SENT Me"
+};
+
+Acci::Acci(AvalancheEngine *vm) {
+ _vm = vm;
+}
+
+void Acci::init() {
+ _vm->_gyro->_weirdWord = false;
+}
+
+void Acci::clearWords() {
+ for (byte i = 0; i < 11; i++) {
+ if (!_realWords[i].empty())
+ _realWords[i].clear();
+ }
+}
+
+byte Acci::wordNum(Common::String word) {
+ if (word.empty())
+ return 0;
+
+ for (int32 i = kParserWordsNum - 1; i >= 0; i--) {
+ if (kVocabulary[i]._word == word)
+ return kVocabulary[i]._number;
+ }
+
+ // If not found as a whole, we look for it as a substring.
+ for (int32 i = kParserWordsNum - 1; i >= 0; i--) {
+ if (Common::String(kVocabulary[i]._word.c_str(), word.size()) == word)
+ return kVocabulary[i]._number;
+ }
+
+ return kPardon;
+}
+
+void Acci::replace(Common::String oldChars, byte newChar) {
+ int16 pos = _vm->_parser->pos(oldChars, _thats);
+ while (pos != -1) {
+ if (newChar == 0)
+ _thats.deleteChar(pos);
+ else {
+ for (byte i = pos; i < pos + oldChars.size(); i++)
+ _thats.deleteChar(pos);
+ _thats.insertChar(newChar, pos);
+ }
+ pos = _vm->_parser->pos(oldChars, _thats);
+ }
+}
+
+Common::String Acci::rank() {
+ static const RankType kRanks[9] = {
+ {0, "Beginner"}, {10, "Novice"},
+ {20, "Improving"}, {35, "Not bad"},
+ {50, "Passable"}, {65, "Good"},
+ {80, "Experienced"}, {108, "The BEST!"},
+ {32767, "copyright'93"}
+ };
+
+ for (byte i = 0; i < 8; i++) {
+ if ((_vm->_gyro->_dna._score >= kRanks[i]._score) && (_vm->_gyro->_dna._score < kRanks[i + 1]._score)) {
+ return kRanks[i]._title;
+ }
+ }
+ return "";
+}
+
+Common::String Acci::totalTime() {
+ // There are 65535 clock ticks in a second, 1092.25 in a minute, and 65535 in an hour.
+ const double ticksInOneSec = (double)(65535) / 3600;
+ uint16 h, m, s;
+
+ h = floor(_vm->_gyro->_dna._totalTime / ticksInOneSec); // No. of seconds.
+ m = h % 3600;
+ h /= 3600;
+ s = m % 60;
+ m /= 60;
+
+ Common::String result = "You've been playing for ";
+ if (h > 0)
+ result += Common::String::format("%d hours, ", h);
+ if ((m > 0) || (h != 0))
+ result = Common::String::format("%d minutes and ", m);
+ return result + Common::String::format("%d seconds", s);
+}
+
+void Acci::cheatParse(Common::String codes) {
+// uint16 num;
+// int16 e;
+// char cmd;
+// int16 se, sx, sy;
+
+ warning("STUB: Acci::cheatParse()");
+}
+
+
+
+void Acci::stripPunctuation(Common::String &word) {
+ const char punct[] = "~`!@#$%^&*()_+-={}[]:\"|;'\\,./<>?";
+
+ for (byte i = 0; i < 32; i++) {
+ for (;;) {
+ int16 pos = _vm->_parser->pos(Common::String(punct[i]), word);
+ if (pos == -1)
+ break;
+ word.deleteChar(pos);
+ }
+ }
+}
+
+void Acci::displayWhat(byte target, bool animate, bool &ambiguous) {
+ if (target == kPardon) {
+ ambiguous = true;
+ if (animate)
+ _vm->_scrolls->displayText("Whom?");
+ else
+ _vm->_scrolls->displayText("What?");
+ } else {
+ if (animate) {
+ Common::String tmpStr = Common::String::format("{ %s }", _vm->_gyro->getName(target).c_str());
+ _vm->_scrolls->displayText(tmpStr);
+ } else {
+ Common::String z = _vm->_gyro->getItem(target);
+ if (z != "") {
+ Common::String tmpStr = Common::String::format("{ %s }", z.c_str());
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ }
+ }
+}
+
+bool Acci::doPronouns() {
+ bool ambiguous = false;
+
+ for (byte i = 0; i < _thats.size(); i++) {
+ byte wordCode = _thats[i];
+ switch (wordCode) {
+ case 200: {
+ displayWhat(_vm->_gyro->_him, true, ambiguous);
+ _thats.setChar(_vm->_gyro->_him, i);
+ }
+ break;
+ case 201: {
+ displayWhat(_vm->_gyro->_her, true, ambiguous);
+ _thats.setChar(_vm->_gyro->_her, i);
+ }
+ break;
+ case 202: {
+ displayWhat(_vm->_gyro->_it, false, ambiguous);
+ _thats.setChar(_vm->_gyro->_it, i);
+ }
+ break;
+ }
+ }
+
+ return ambiguous;
+}
+
+void Acci::properNouns() {
+ _vm->_parser->_inputText.toLowercase();
+
+ // We set every word's first character to uppercase.
+ for (byte i = 1; i < (_vm->_parser->_inputText.size() - 1); i++) {
+ if (_vm->_parser->_inputText[i] == ' ')
+ _vm->_parser->_inputText.setChar(toupper(_vm->_parser->_inputText[i + 1]), i + 1);
+ }
+
+ // And the first character as well.
+ _vm->_parser->_inputText.setChar(toupper(_vm->_parser->_inputText[0]), 0);
+}
+
+void Acci::sayIt() {
+ Common::String x = _vm->_parser->_inputText;
+ x.setChar(toupper(x[0]), 0);
+ Common::String tmpStr = Common::String::format("%c1%s.%c%c2", Scrolls::kControlRegister, x.c_str(),
+ Scrolls::kControlSpeechBubble, Scrolls::kControlRegister);
+ _vm->_scrolls->displayText(tmpStr);
+}
+
+void Acci::storeInterrogation(byte interrogation) {
+ if (_vm->_parser->_inputText.empty())
+ return;
+
+ // Strip _vm->_parser->_inputText:
+ while ((_vm->_parser->_inputText[0] == ' ') && (!_vm->_parser->_inputText.empty()))
+ _vm->_parser->_inputText.deleteChar(0);
+ while ((_vm->_parser->_inputText.lastChar() == ' ') && (!_vm->_parser->_inputText.empty()))
+ _vm->_parser->_inputText.deleteLastChar();
+
+ _vm->_timer->loseTimer(Timer::kReasonCardiffsurvey); // If you want to use any other timer, put this into the case statement.
+
+ switch (interrogation) {
+ case 1:
+ _vm->_parser->_inputText.toLowercase();
+ sayIt();
+ _vm->_gyro->_dna._favouriteDrink = _vm->_parser->_inputText;
+ _vm->_gyro->_dna._cardiffQuestionNum = 2;
+ break;
+ case 2:
+ properNouns();
+ sayIt();
+ _vm->_gyro->_dna._favouriteSong = _vm->_parser->_inputText;
+ _vm->_gyro->_dna._cardiffQuestionNum = 3;
+ break;
+ case 3:
+ properNouns();
+ sayIt();
+ _vm->_gyro->_dna._worstPlaceOnEarth = _vm->_parser->_inputText;
+ _vm->_gyro->_dna._cardiffQuestionNum = 4;
+ break;
+ case 4:
+ _vm->_parser->_inputText.toLowercase();
+ sayIt();
+ if (!_vm->_gyro->_dna._spareEvening.empty())
+ _vm->_gyro->_dna._spareEvening.clear();
+ _vm->_gyro->_dna._spareEvening = _vm->_parser->_inputText;
+ _vm->_visa->displayScrollChain('z', 5); // His closing statement...
+ _vm->_animation->_sprites[1].walkTo(4); // The end of the drawbridge
+ _vm->_animation->_sprites[1]._vanishIfStill = true; // Then go away!
+ _vm->_gyro->_magics[1]._operation = Gyro::kMagicNothing;
+ _vm->_gyro->_dna._cardiffQuestionNum = 5;
+ break;
+ case 99:
+ //store_high(_vm->_parser->_inputText);
+ warning("STUB: Acci::store_interrogation()");
+ break;
+ }
+
+ if (interrogation < 4)
+ _vm->_timer->cardiffSurvey();
+}
+
+
+
+void Acci::parse() {
+ // First parsing - word identification
+ if (!_thats.empty())
+ _thats.clear();
+
+ byte n = 0;
+ _polite = false;
+ _verb = kPardon;
+ _thing = kPardon;
+ _thing2 = kPardon;
+ _person = kPardon;
+ clearWords();
+
+
+ // A cheat mode attempt.
+ if (_vm->_parser->_inputText[0] == '.') {
+ cheatParse(_vm->_parser->_inputText);
+ _thats = kNothing;
+ return;
+ }
+
+ // Are we being interrogated right now?
+ if (_vm->_gyro->_interrogation > 0) {
+ storeInterrogation(_vm->_gyro->_interrogation);
+ _vm->_gyro->_weirdWord = true;
+ return;
+ }
+
+ // Actually process the command.
+ Common::String inputText = _vm->_parser->_inputText + ' ';
+ Common::String inputTextUpper = inputText;
+ inputTextUpper.toUppercase();
+ while (!inputTextUpper.empty()) {
+ while ((!inputTextUpper.empty()) && (inputTextUpper[0] == ' ')) {
+ inputTextUpper.deleteChar(0);
+ inputText.deleteChar(0);
+ }
+ if (inputTextUpper.empty())
+ break;
+
+ // Get the following word of the strings.
+ byte size = _vm->_parser->pos(Common::String(' '), inputTextUpper) + 1;
+ char *subStr = new char[size];
+ Common::strlcpy(subStr, inputTextUpper.c_str(), size);
+ Common::String thisword = subStr;
+ Common::strlcpy(subStr, inputText.c_str(), size);
+ _realWords[n] = subStr;
+ delete[] subStr;
+
+ stripPunctuation(inputTextUpper);
+
+ bool notfound = true;
+
+ // Check also[] first, which contains words about the actual room.
+ if (!thisword.empty()) {
+ for (byte i = 0; i < 31; i++) {
+ if ((_vm->_gyro->_also[i][0] != 0) && (_vm->_parser->pos(',' + thisword, *_vm->_gyro->_also[i][0]) > -1)) {
+ _thats += Common::String(99 + i);
+ notfound = false;
+ }
+ }
+ }
+
+ // Check Accis's own table (words[]) for "global" commands.
+ if (notfound) {
+ byte answer = wordNum(thisword);
+ if (answer == kPardon) {
+ notfound = true;
+ _thats = _thats + kPardon;
+ } else
+ _thats = _thats + answer;
+ n++;
+ }
+
+ // Delete words we already processed.
+ int16 spacePos = _vm->_parser->pos(Common::String(' '), inputTextUpper);
+ if (spacePos > -1) {
+ for (byte i = 0; i <= spacePos; i++)
+ inputTextUpper.deleteChar(0);
+ }
+
+ spacePos = _vm->_parser->pos(Common::String(' '), inputText);
+ if (spacePos > -1) {
+ for (byte i = 0; i <= spacePos; i++)
+ inputText.deleteChar(0);
+ }
+ }
+
+ Common::String unkString;
+ int16 pos = _vm->_parser->pos(Common::String('\xFE'), _thats);
+ if (pos > -1)
+ unkString = _realWords[pos];
+ else
+ unkString.clear();
+
+ // Replace words' codes that mean the same.
+ replace(Common::String("\xFF"), 0); // zap noise words
+ replace(Common::String("\xD\xE2"), 1); // "look at" = "examine"
+ replace(Common::String("\xD\xE4"), 1); // "look in" = "examine"
+ replace(Common::String("\x4\xE6"), 17); // "get up" = "stand"
+ replace(Common::String("\x4\xE7"), 17); // "get down" = "stand"... well, why not?
+ replace(Common::String("\x12\xE4"), 2); // "go in" = "open [door]"
+ replace(Common::String("\x1C\xE5"), 253); // "P' off" is a swear word
+ replace(Common::String("\x4\x6"), 6); // "Take inventory" (remember Colossal Adventure?)
+ replace(Common::String("\x28\xE8"), 21); // "put on" = "don"
+ replace(Common::String("\x4\xE5"), 20); // "take off" = "doff"
+
+ // Words that could mean more than one _person
+ if (_vm->_gyro->_dna._room == r__nottspub)
+ replace(Common::String('\xCC'), 164); // Barman = Port
+ else
+ replace(Common::String('\xCC'), 154); // Barman = Malagauche
+
+ switch (_vm->_gyro->_dna._room) {
+ case r__aylesoffice:
+ replace(Common::String('\xCB'), 163); // Monk = Ayles
+ break;
+ case r__musicroom:
+ replace(Common::String('\xCB'), 166); // Monk = Jacques
+ break;
+ default:
+ replace(Common::String('\xCB'), 162); // Monk = Ibythneth
+ }
+
+ if (doPronouns()) {
+ _vm->_gyro->_weirdWord = true;
+ _thats = kNothing;
+ return;
+ }
+
+ // Second parsing.
+ if (!_vm->_gyro->_subject.empty())
+ _vm->_gyro->_subject.clear();
+ _vm->_gyro->_subjectNum = 0; // Find subject of conversation.
+
+ for (int i = 0; (i < 11) && !_realWords[i].empty(); i++) {
+ if ((_realWords[i][0] == '\'') || (_realWords[i][0] == '\"')) {
+ _vm->_gyro->_subjectNum = (byte)_thats[i];
+ _thats.setChar(kMoved, i);
+ break;
+ }
+ }
+
+ if ((_vm->_gyro->_subjectNum == 0) && !_thats.empty()) { // Still not found.
+ for (uint16 i = 0; i < _thats.size() - 1; i++) {
+ if ((byte)_thats[i] == 252) { // The word is "about", or something similar.
+ _vm->_gyro->_subjectNum = (byte)_thats[i + 1];
+ _thats.setChar(0, i + 1);
+ break;
+ }
+ }
+ }
+
+ if ((_vm->_gyro->_subjectNum == 0) && !_thats.empty()) { // STILL not found! Must be the word after "say".
+ for (uint16 i = 0; i < _thats.size() - 1; i++) {
+ if (((byte)_thats[i] == 7) && ((byte)_thats[i + 1] != 0) && !((225 <= (byte)_thats[i + 1]) && ((byte)_thats[i + 1] <= 229))) {
+ // SAY not followed by a preposition
+ _vm->_gyro->_subjectNum = (byte)_thats[i + 1];
+ _thats.setChar(0, i + 1);
+ break;
+ }
+ }
+ }
+
+ for (int16 i = _thats.size() - 1; i >= 0; i--) { // Reverse order, so first will be used.
+ if (((byte)_thats[i] == 253) || ((byte)_thats[i] == 249) || ((1 <= (byte)_thats[i]) && ((byte)_thats[i] <= 49)))
+ _verb = (byte)_thats[i];
+ else if ((50 <= (byte)_thats[i]) && ((byte)_thats[i] <= 149)) {
+ _thing2 = _thing;
+ _thing = (byte)_thats[i];
+ } else if ((150 <= (byte)_thats[i]) && ((byte)_thats[i] <= 199))
+ _person = (byte)_thats[i];
+ else if ((byte)_thats[i] == 251)
+ _polite = true;
+ }
+
+ if ((!unkString.empty()) && (_verb != kVerbCodeExam) && (_verb != kVerbCodeTalk) && (_verb != kVerbCodeSave) && (_verb != kVerbCodeLoad) && (_verb != kVerbCodeDir)) {
+ Common::String tmpStr = Common::String::format("Sorry, but I have no idea what \"%s\" means. Can you rephrase it?", unkString.c_str());
+ _vm->_scrolls->displayText(tmpStr);
+ _vm->_gyro->_weirdWord = true;
+ } else
+ _vm->_gyro->_weirdWord = false;
+
+ if (_thats.empty())
+ _thats = kNothing;
+
+ if (_thing != kPardon)
+ _vm->_gyro->_it = _thing;
+
+ if (_person != kPardon) {
+ if (_person < 175)
+ _vm->_gyro->_him = _person;
+ else
+ _vm->_gyro->_her = _person;
+ }
+}
+
+void Acci::examineObject() {
+ if (_thing != _vm->_gyro->_thinks)
+ _vm->_lucerna->thinkAbout(_thing, Gyro::kThing);
+ switch (_thing) {
+ case Gyro::kObjectWine :
+ switch (_vm->_gyro->_dna._wineState) {// 4 is perfect wine. 0 is not holding the wine.
+ case 1:
+ _vm->_visa->displayScrollChain('t', 1); // Normal examine wine scroll
+ break;
+ case 2:
+ _vm->_visa->displayScrollChain('d', 6); // Bad wine
+ break;
+ case 3:
+ _vm->_visa->displayScrollChain('d', 7); // Vinegar
+ break;
+ }
+ break;
+ case Gyro::kObjectOnion:
+ if (_vm->_gyro->_dna._rottenOnion)
+ _vm->_visa->displayScrollChain('q', 21); // Yucky onion.
+ else
+ _vm->_visa->displayScrollChain('t', 18); // Normal onion scroll
+ break;
+ default:
+ _vm->_visa->displayScrollChain('t', _thing); // <<< Ordinarily
+ }
+}
+
+bool Acci::isPersonHere() { // Person equivalent of "holding".
+ if ((_person == kPardon) || (_person == 0) || (_vm->_gyro->_whereIs[_person - 150] == _vm->_gyro->_dna._room))
+ return true;
+ else {
+ Common::String tmpStr;
+ if (_person < 175)
+ tmpStr = Common::String::format("He isn't around at the moment.");
+ else
+ tmpStr = Common::String::format("She isn't around at the moment.");
+ _vm->_scrolls->displayText(tmpStr);
+ return false;
+ }
+}
+
+void Acci::exampers() {
+ if (isPersonHere()) {
+ if (_thing != _vm->_gyro->_thinks)
+ _vm->_lucerna->thinkAbout(_person, Gyro::kPerson);
+ _person -= 149;
+ switch (_person) { // Special cases
+ case 11:
+ if (_vm->_gyro->_dna._wonNim) {
+ _vm->_visa->displayScrollChain('Q', 8); // "I'm Not Playing!"
+ return;
+ }
+ break;
+ case 99:
+ if (_vm->_gyro->_dna._lustieIsAsleep) {
+ _vm->_visa->displayScrollChain('Q', 65); // He's asleep. (65! Wow!)
+ return;
+ }
+ break;
+ }
+ // Otherwise...
+ _vm->_visa->displayScrollChain('p', _person);
+ }
+
+ // And afterwards...
+ if ((_person == 14) && (!_vm->_gyro->_dna._aylesIsAwake))
+ _vm->_visa->displayScrollChain('Q', 13);
+}
+
+/**
+ * Return whether Avvy is holding an object or not
+ * @remarks Originally called 'holding'
+ */
+bool Acci::isHolding() {
+ if ((51 <= _thing) && (_thing <= 99)) // Also.
+ return true;
+
+ bool holdingResult = false;
+
+ if (_thing > 100)
+ _vm->_scrolls->displayText("Be reasonable!");
+ else if (!_vm->_gyro->_dna._objects[_thing - 1]) // Verbs that need "_thing" to be in the inventory.
+ _vm->_scrolls->displayText("You're not holding it, Avvy.");
+ else
+ holdingResult = true;
+
+ return holdingResult;
+}
+
+void Acci::openBox(bool isOpening) {
+ if ((_vm->_gyro->_dna._room == r__yours) && (_thing == 54)) {
+ _vm->_celer->drawBackgroundSprite(-1, -1, 5);
+
+ _vm->_celer->updateBackgroundSprites();
+ _vm->_animation->animLink();
+ _vm->_graphics->refreshScreen();
+
+ _vm->_system->delayMillis(55);
+
+ if (!isOpening) {
+ _vm->_celer->drawBackgroundSprite(-1, -1, 6);
+ _vm->_celer->updateBackgroundSprites();
+ _vm->_animation->animLink();
+ _vm->_graphics->refreshScreen();
+ }
+ }
+}
+
+void Acci::examine() {
+ // EITHER it's an object OR it's an Also OR it's a _person OR it's something else.
+ if ((_person == kPardon) && (_thing != kPardon)) {
+ if (isHolding()) {
+ // Remember: it's been Slipped! Ie subtract 49.
+ if ((1 <= _thing) && (_thing <= 49)) // Standard object
+ examineObject();
+ else if ((50 <= _thing) && (_thing <= 100)) { // Also _thing
+ openBox(true);
+ _vm->_scrolls->displayText(*_vm->_gyro->_also[_thing - 50][1]);
+ openBox(false);
+ }
+ }
+ } else if (_person != kPardon)
+ exampers();
+ else
+ _vm->_scrolls->displayText("It's just as it looks on the picture."); // Don't know: guess.
+}
+
+void Acci::inventory() {
+ byte itemNum = 0;
+ Common::String tmpStr = Common::String::format("You're carrying %c", Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+
+ for (byte i = 0; i < kObjectNum; i++) {
+ if (_vm->_gyro->_dna._objects[i]) {
+ itemNum++;
+ if (itemNum == _vm->_gyro->_dna._carryNum) {
+ tmpStr = Common::String::format("and %c", Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+
+ _vm->_scrolls->displayText(_vm->_gyro->getItem(i + 1) + Scrolls::kControlToBuffer);
+
+ if ((i + 1) == _vm->_gyro->_dna._wearing) {
+ tmpStr = Common::String::format(", which you're wearing%c", Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+
+ if (itemNum < _vm->_gyro->_dna._carryNum) {
+ tmpStr = Common::String::format(", %c", Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ }
+ }
+
+ if (_vm->_gyro->_dna._wearing == kNothing) {
+ tmpStr = Common::String::format("...%c%c...and you're stark naked!", Scrolls::kControlNewLine, Scrolls::kControlNewLine);
+ _vm->_scrolls->displayText(tmpStr);
+ } else
+ _vm->_scrolls->displayText(".");
+}
+
+void Acci::swallow() { // Eat something.
+ switch (_thing) {
+ case Gyro::kObjectWine:
+ switch (_vm->_gyro->_dna._wineState) { // 4 is perfect
+ case 1:
+ if (_vm->_gyro->_dna._teetotal) {
+ _vm->_visa->displayScrollChain('D', 6);
+ return;
+ }
+ _vm->_visa->displayScrollChain('U', 1);
+ _vm->_pingo->wobble();
+ _vm->_visa->displayScrollChain('U', 2);
+ _vm->_gyro->_dna._objects[Gyro::kObjectWine - 1] = false;
+ _vm->_lucerna->refreshObjectList();
+ drink();
+ break;
+ case 2:
+ case 3:
+ _vm->_visa->displayScrollChain('d', 8);
+ break; // You can't drink it!
+ }
+ break;
+ case Gyro::kObjectPotion:
+ _vm->_gyro->setBackgroundColor(4);
+ _vm->_visa->displayScrollChain('U', 3);
+ _vm->_lucerna->gameOver();
+ _vm->_gyro->setBackgroundColor(0);
+ break;
+ case Gyro::kObjectInk:
+ _vm->_visa->displayScrollChain('U', 4);
+ break;
+ case Gyro::kObjectChastity:
+ _vm->_visa->displayScrollChain('U', 5);
+ break;
+ case Gyro::kObjectMushroom:
+ _vm->_visa->displayScrollChain('U', 6);
+ _vm->_lucerna->gameOver();
+ break;
+ case Gyro::kObjectOnion:
+ if (_vm->_gyro->_dna._rottenOnion)
+ _vm->_visa->displayScrollChain('U', 11);
+ else {
+ _vm->_visa->displayScrollChain('U', 8);
+ _vm->_gyro->_dna._objects[Gyro::kObjectOnion - 1] = false;
+ _vm->_lucerna->refreshObjectList();
+ }
+ break;
+ default:
+ if ((_vm->_gyro->_dna._room == r__argentpub) || (_vm->_gyro->_dna._room == r__nottspub))
+ _vm->_scrolls->displayText("Try BUYing things before you drink them!");
+ else
+ _vm->_scrolls->displayText("The taste of it makes you retch!");
+ }
+}
+
+void Acci::peopleInRoom() {
+ byte numPeople = 0; // Number of people in the room.
+
+ for (byte i = 1; i < 29; i++) { // Start at 1 so we don't list Avvy himself!
+ if (_vm->_gyro->_whereIs[i] == _vm->_gyro->_dna._room)
+ numPeople++;
+ }
+
+ if (numPeople == 0) // If nobody's here, we can cut out straight away.
+ return;
+
+ Common::String tmpStr;
+ byte actPerson = 0; // Actually listed people.
+ for (byte i = 1; i < 29; i++) {
+ if (_vm->_gyro->_whereIs[i] == _vm->_gyro->_dna._room) {
+ actPerson++;
+ if (actPerson == 1) // First on the list.
+ _vm->_scrolls->displayText(_vm->_gyro->getName(i + 150) + Scrolls::kControlToBuffer);
+ else if (actPerson < numPeople) { // The middle...
+ tmpStr = Common::String::format(", %s%c", _vm->_gyro->getName(i + 150), Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ } else { // The end.
+ tmpStr = Common::String::format(" and %s%c", _vm->_gyro->getName(i + 150), Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ }
+ }
+
+ if (numPeople == 1) {
+ tmpStr = Common::String::format(" is%c", Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ } else {
+ tmpStr = Common::String::format(" are%c", Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+
+ _vm->_scrolls->displayText(" here."); // End and display it.
+}
+
+void Acci::lookAround() {
+ _vm->_scrolls->displayText(*_vm->_gyro->_also[0][1]);
+ switch (_vm->_gyro->_dna._room) {
+ case r__spludwicks:
+ if (_vm->_gyro->_dna._avariciusTalk > 0)
+ _vm->_visa->displayScrollChain('q', 23);
+ else
+ peopleInRoom();
+ break;
+ case r__robins:
+ if (_vm->_gyro->_dna._tiedUp)
+ _vm->_visa->displayScrollChain('q', 38);
+ if (_vm->_gyro->_dna._mushroomGrowing)
+ _vm->_visa->displayScrollChain('q', 55);
+ break;
+ case r__insidecardiffcastle:
+ if (!_vm->_gyro->_dna._takenPen)
+ _vm->_visa->displayScrollChain('q', 49);
+ break;
+ case r__lustiesroom:
+ if (_vm->_gyro->_dna._lustieIsAsleep)
+ _vm->_visa->displayScrollChain('q', 65);
+ break;
+ case r__catacombs:
+ switch (_vm->_gyro->_dna._catacombY * 256 + _vm->_gyro->_dna._catacombX) {
+ case 258 :
+ _vm->_visa->displayScrollChain('q', 80); // Inside art gallery.
+ break;
+ case 514 :
+ _vm->_visa->displayScrollChain('q', 81); // Outside ditto.
+ break;
+ case 260 :
+ _vm->_visa->displayScrollChain('q', 82); // Outside Geida's room.
+ break;
+ }
+ break;
+ default:
+ peopleInRoom();
+ }
+}
+
+void Acci::openDoor() {
+ // Special cases.
+ switch (_vm->_gyro->_dna._room) {
+ case r__yours:
+ if (_vm->_animation->inField(2)) {
+ // Opening the box.
+ _thing = 54; // The box.
+ _person = kPardon;
+ examine();
+ return;
+ }
+ break;
+ case r__spludwicks:
+ if (_thing == 61) {
+ _vm->_visa->displayScrollChain('q', 85);
+ return;
+ }
+ break;
+ }
+
+ if ((!_vm->_gyro->_dna._userMovesAvvy) && (_vm->_gyro->_dna._room != r__lusties))
+ return; // No doors can open if you can't move Avvy.
+
+ for (byte fv = 8; fv < 15; fv++) {
+ if (_vm->_animation->inField(fv + 1)) {
+ fv -= 8;
+
+ switch (_vm->_gyro->_portals[fv]._operation) {
+ case Gyro::kMagicExclaim:
+ _vm->_animation->_sprites[0].bounce();
+ _vm->_visa->displayScrollChain('x', _vm->_gyro->_portals[fv]._data);
+ break;
+ case Gyro::kMagicTransport:
+ _vm->_animation->flipRoom((_vm->_gyro->_portals[fv]._data) >> 8, // High byte
+ (_vm->_gyro->_portals[fv]._data) & 0x0F // Low byte
+ );
+ break;
+ case Gyro::kMagicUnfinished:
+ _vm->_animation->_sprites[0].bounce();
+ _vm->_scrolls->displayText("Sorry. This place is not available yet!");
+ break;
+ case Gyro::kMagicSpecial:
+ _vm->_animation->callSpecial(_vm->_gyro->_portals[fv]._data);
+ break;
+ case Gyro::kMagicOpenDoor:
+ _vm->_animation->openDoor((_vm->_gyro->_portals[fv]._data) >> 8, (_vm->_gyro->_portals[fv]._data) & 0x0F, fv + 9);
+ break;
+ }
+
+ return;
+ }
+ }
+
+ if (_vm->_gyro->_dna._room == r__map)
+ _vm->_scrolls->displayText(Common::String("Avvy, you can complete the whole game without ever going "
+ "to anywhere other than Argent, Birmingham, Cardiff, Nottingham and Norwich."));
+ else
+ _vm->_scrolls->displayText("Door? What door?");
+}
+
+
+
+void Acci::silly() {
+ _vm->_scrolls->displayText("Don't be silly!");
+}
+
+void Acci::putProc() {
+ if (!isHolding())
+ return;
+
+ _thing2 -= 49; // Slip the second object.
+ char temp = _thing;
+ _thing = _thing2;
+ if (!isHolding())
+ return;
+ _thing = temp;
+
+ // Thing is the _thing which you're putting in. _thing2 is where you're putting it.
+ switch (_thing2) {
+ case Gyro::kObjectWine:
+ if (_thing == Gyro::kObjectOnion) {
+ if (_vm->_gyro->_dna._rottenOnion)
+ _vm->_scrolls->displayText("That's a bit like shutting the stable door after the horse has bolted!");
+ else { // Put onion into wine?
+ if (_vm->_gyro->_dna._wineState != 3) {
+ Common::String tmpStr = Common::String::format("%cOignon au vin%c is a bit too strong for your tastes!", Scrolls::kControlItalic, Scrolls::kControlRoman);
+ _vm->_scrolls->displayText(tmpStr);
+ } else { // Put onion into vinegar! Yes!
+ _vm->_gyro->_dna._onionInVinegar = true;
+ _vm->_lucerna->incScore(7);
+ _vm->_visa->displayScrollChain('u', 9);
+ }
+ }
+ } else
+ silly();
+ break;
+
+ case 54:
+ if (_vm->_gyro->_dna._room == r__yours) { // Put something into the box.
+ if (_vm->_gyro->_dna._boxContent != kNothing)
+ _vm->_scrolls->displayText("There's something in the box already, Avvy. Try taking that out first.");
+ else {
+ switch (_thing) {
+ case Gyro::kObjectMoney:
+ _vm->_scrolls->displayText("You'd better keep some ready cash on you!");
+ break;
+ case Gyro::kObjectBell:
+ _vm->_scrolls->displayText("That's a silly place to keep a bell.");
+ break;
+ case Gyro::kObjectBodkin:
+ _vm->_scrolls->displayText("But you might need it!");
+ break;
+ case Gyro::kObjectOnion:
+ _vm->_scrolls->displayText("Just give it to Spludwick, Avvy!");
+ break;
+ default: // Put the object into the box...
+ if (_vm->_gyro->_dna._wearing == _thing) {
+ Common::String tmpStr = Common::String::format("You'd better take %s off first!", _vm->_gyro->getItem(_thing).c_str());
+ _vm->_scrolls->displayText(tmpStr);
+ } else {
+ openBox(true); // Open box.
+
+ _vm->_gyro->_dna._boxContent = _thing;
+ _vm->_gyro->_dna._objects[_thing - 1] = false;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_scrolls->displayText("OK, it's in the box.");
+
+ openBox(false); // Shut box.
+ }
+ }
+ }
+ } else
+ silly();
+ break;
+
+ default:
+ silly();
+ }
+}
+
+/**
+ * Display text when ingredients are not in the right order
+ * @remarks Originally called 'not_in_order'
+ */
+void Acci::notInOrder() {
+ Common::String tmpStr = Common::String::format("Sorry, I need the ingredients in the right order for this potion. " \
+ "What I need next is %s%c2%c", _vm->_gyro->getItem(_vm->_gyro->kSpludwicksOrder[_vm->_gyro->_dna._givenToSpludwick]),
+ Scrolls::kControlRegister, Scrolls::kControlSpeechBubble);
+ _vm->_scrolls->displayText(tmpStr);
+}
+
+/**
+ * Move Spludwick to cauldron
+ * @remarks Originally called 'go_to_cauldron'
+ */
+void Acci::goToCauldron() {
+ _vm->_animation->_sprites[1]._callEachStepFl = false; // Stops Geida_Procs.
+ _vm->_timer->addTimer(1, Timer::kProcSpludwickGoesToCauldron, Timer::kReasonSpludwickWalk);
+ _vm->_animation->_sprites[1].walkTo(2);
+}
+
+/**
+ * Check is it's possible to give something to Spludwick
+ * @remarks Originally called 'give2spludwick'
+ */
+bool Acci::giveToSpludwick() {
+ if (_vm->_gyro->kSpludwicksOrder[_vm->_gyro->_dna._givenToSpludwick] != _thing) {
+ notInOrder();
+ return false;
+ }
+
+ switch (_thing) {
+ case Gyro::kObjectOnion:
+ _vm->_gyro->_dna._objects[Gyro::kObjectOnion - 1] = false;
+ if (_vm->_gyro->_dna._rottenOnion)
+ _vm->_visa->displayScrollChain('q', 22);
+ else {
+ _vm->_gyro->_dna._givenToSpludwick++;
+ _vm->_visa->displayScrollChain('q', 20);
+ goToCauldron();
+ _vm->_lucerna->incScore(3);
+ }
+ _vm->_lucerna->refreshObjectList();
+ break;
+ case Gyro::kObjectInk:
+ _vm->_gyro->_dna._objects[Gyro::kObjectInk - 1] = false;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_gyro->_dna._givenToSpludwick++;
+ _vm->_visa->displayScrollChain('q', 24);
+ goToCauldron();
+ _vm->_lucerna->incScore(3);
+ break;
+ case Gyro::kObjectMushroom:
+ _vm->_gyro->_dna._objects[Gyro::kObjectMushroom - 1] = false;
+ _vm->_visa->displayScrollChain('q', 25);
+ _vm->_lucerna->incScore(5);
+ _vm->_gyro->_dna._givenToSpludwick++;
+ goToCauldron();
+ _vm->_gyro->_dna._objects[Gyro::kObjectPotion - 1] = true;
+ _vm->_lucerna->refreshObjectList();
+ break;
+ default:
+ return true;
+ }
+
+ return false;
+}
+
+void Acci::drink() {
+ _vm->_gyro->_dna._alcoholLevel += 1;
+ if (_vm->_gyro->_dna._alcoholLevel == 5) {
+ _vm->_gyro->_dna._objects[Gyro::kObjectKey - 1] = true; // Get the key.
+ _vm->_gyro->_dna._teetotal = true;
+ _vm->_gyro->_dna._avvyIsAwake = false;
+ _vm->_gyro->_dna._avvyInBed = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_lucerna->dusk();
+ _vm->_gyro->hangAroundForAWhile();
+ _vm->_animation->flipRoom(1, 1);
+ _vm->_gyro->setBackgroundColor(14);
+ _vm->_animation->_sprites[0]._visible = false;
+ }
+}
+
+void Acci::cardiffClimbing() {
+ if (_vm->_gyro->_dna._standingOnDais) { // Clamber up.
+ _vm->_scrolls->displayText("You climb down, back onto the floor.");
+ _vm->_gyro->_dna._standingOnDais = false;
+ _vm->_animation->appearPed(1, 3);
+ } else { // Clamber down.
+ if (_vm->_animation->inField(1)) {
+ _vm->_scrolls->displayText("You clamber up onto the dais.");
+ _vm->_gyro->_dna._standingOnDais = true;
+ _vm->_animation->appearPed(1, 2);
+ } else
+ _vm->_scrolls->displayText("Get a bit closer, Avvy.");
+ }
+}
+
+void Acci::already() {
+ _vm->_scrolls->displayText("You're already standing!");
+}
+
+void Acci::standUp() {
+ switch (_vm->_gyro->_dna._room) {
+ case r__yours: // Avvy isn't asleep.
+ if (_vm->_gyro->_dna._avvyIsAwake && _vm->_gyro->_dna._avvyInBed) { // But he's in bed.
+ if (_vm->_gyro->_dna._teetotal) {
+ _vm->_visa->displayScrollChain('d', 12);
+ _vm->_gyro->setBackgroundColor(0);
+ _vm->_visa->displayScrollChain('d', 14);
+ }
+ _vm->_animation->_sprites[0]._visible = true;
+ _vm->_gyro->_dna._userMovesAvvy = true;
+ _vm->_animation->appearPed(1, 2);
+ _vm->_gyro->_dna._direction = Gyro::kDirectionLeft;
+ _vm->_celer->drawBackgroundSprite(-1, -1, 4); // Picture of empty pillow.
+ _vm->_lucerna->incScore(1);
+ _vm->_gyro->_dna._avvyInBed = false;
+ _vm->_timer->loseTimer(Timer::kReasonArkataShouts);
+ } else
+ already();
+ break;
+
+ case r__insidecardiffcastle:
+ cardiffClimbing();
+ break;
+
+ case r__nottspub:
+ if (_vm->_gyro->_dna._sittingInPub) {
+ _vm->_celer->drawBackgroundSprite(-1, -1, 4); // Not sitting down.
+ _vm->_animation->_sprites[0]._visible = true; // But standing up.
+ _vm->_animation->appearPed(1, 4); // And walking away.
+ _vm->_gyro->_dna._sittingInPub = false; // Really not sitting down.
+ _vm->_gyro->_dna._userMovesAvvy = true; // And ambulant.
+ } else
+ already();
+ break;
+ default:
+ already();
+ }
+}
+
+void Acci::getProc(char thing) {
+ switch (_vm->_gyro->_dna._room) {
+ case r__yours:
+ if (_vm->_animation->inField(2)) {
+ if (_vm->_gyro->_dna._boxContent == thing) {
+ _vm->_celer->drawBackgroundSprite(-1, -1, 5);
+ _vm->_scrolls->displayText("OK, I've got it.");
+ _vm->_gyro->_dna._objects[thing - 1] = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_gyro->_dna._boxContent = kNothing;
+ _vm->_celer->drawBackgroundSprite(-1, -1, 6);
+ } else {
+ Common::String tmpStr = Common::String::format("I can't see %s in the box.", _vm->_gyro->getItem(thing));
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ } else
+ _vm->_visa->displayScrollChain('q', 57);
+ break;
+ case r__insidecardiffcastle:
+ switch (thing) {
+ case Gyro::kObjectPen:
+ if (_vm->_animation->inField(2)) { // Standing on the dais.
+ if (_vm->_gyro->_dna._takenPen)
+ _vm->_scrolls->displayText("It's not there, Avvy.");
+ else {
+ // OK: we're taking the pen, and it's there.
+ _vm->_celer->drawBackgroundSprite(-1, -1, 4); // No pen there now.
+ _vm->_animation->callSpecial(3); // Zap!
+ _vm->_gyro->_dna._takenPen = true;
+ _vm->_gyro->_dna._objects[Gyro::kObjectPen - 1] = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_scrolls->displayText("Taken.");
+ }
+ } else if (_vm->_gyro->_dna._standingOnDais)
+ _vm->_visa->displayScrollChain('q', 53);
+ else
+ _vm->_visa->displayScrollChain('q', 51);
+ break;
+ case Gyro::kObjectBolt:
+ _vm->_visa->displayScrollChain('q', 52);
+ break;
+ default:
+ _vm->_visa->displayScrollChain('q', 57);
+ }
+ break;
+ case r__robins:
+ if ((thing == Gyro::kObjectMushroom) & (_vm->_animation->inField(1)) & (_vm->_gyro->_dna._mushroomGrowing)) {
+ _vm->_celer->drawBackgroundSprite(-1, -1, 3);
+ _vm->_scrolls->displayText("Got it!");
+ _vm->_gyro->_dna._mushroomGrowing = false;
+ _vm->_gyro->_dna._takenMushroom = true;
+ _vm->_gyro->_dna._objects[Gyro::kObjectMushroom - 1] = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_lucerna->incScore(3);
+ } else
+ _vm->_visa->displayScrollChain('q', 57);
+ break;
+ default:
+ _vm->_visa->displayScrollChain('q', 57);
+ }
+}
+
+/**
+ * Give the lute to Geida
+ * @remarks Originally called 'give_Geida_the_lute'
+ */
+void Acci::giveGeidaTheLute() {
+ if (_vm->_gyro->_dna._room != r__lustiesroom) {
+ Common::String tmpStr = Common::String::format("Not yet. Try later!%c2%c", Scrolls::kControlRegister, Scrolls::kControlSpeechBubble);
+ _vm->_scrolls->displayText(tmpStr);
+ return;
+ }
+ _vm->_gyro->_dna._objects[Gyro::kObjectLute - 1] = false;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_visa->displayScrollChain('q', 64); // She plays it.
+
+ _vm->_timer->addTimer(1, Timer::kProcGiveLuteToGeida, Timer::kReasonGeidaSings);
+ _vm->_enid->backToBootstrap(4);
+}
+
+void Acci::playHarp() {
+ if (_vm->_animation->inField(7))
+ _vm->_scrolls->musicalScroll();
+ else
+ _vm->_scrolls->displayText("Get a bit closer to it, Avvy!");
+}
+
+void Acci::winSequence() {
+ _vm->_visa->displayScrollChain('q', 78);
+ _vm->_sequence->firstShow(7);
+ _vm->_sequence->thenShow(8);
+ _vm->_sequence->thenShow(9);
+ _vm->_sequence->startToClose();
+ _vm->_timer->addTimer(30, Timer::kProcWinning, Timer::kReasonWinning);
+}
+
+void Acci::personSpeaks() {
+ if ((_person == kPardon) || (_person == 0)) {
+ if ((_vm->_gyro->_him == kPardon) || (_vm->_gyro->_whereIs[_vm->_gyro->_him - 150] != _vm->_gyro->_dna._room))
+ _person = _vm->_gyro->_her;
+ else
+ _person = _vm->_gyro->_him;
+ }
+
+ if (_vm->_gyro->_whereIs[_person - 150] != _vm->_gyro->_dna._room) {
+ Common::String tmpStr = Common::String::format("%c1%c", Scrolls::kControlRegister, Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr); // Avvy himself!
+ return;
+ }
+
+ bool found = false; // The _person we're looking for's code is in _person.
+
+ for (byte i = 0; i < _vm->_animation->kSpriteNumbMax; i++) {
+ if (_vm->_animation->_sprites[i]._quick && ((_vm->_animation->_sprites[i]._stat._acciNum + 149) == _person)) {
+ Common::String tmpStr = Common::String::format("%c%c%c", Scrolls::kControlRegister, '1' + i, Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ found = true;
+ }
+ }
+
+ if (found)
+ return;
+
+ for (byte i = 0; i < 16; i++) {
+ if ((_vm->_gyro->kQuasipeds[i]._who == _person) && (_vm->_gyro->kQuasipeds[i]._room == _vm->_gyro->_dna._room)) {
+ Common::String tmpStr = Common::String::format("%c%c%c", Scrolls::kControlRegister, 'A' + i, Scrolls::kControlToBuffer);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ }
+}
+void Acci::heyThanks() {
+ personSpeaks();
+ Common::String tmpStr = Common::String::format("Hey, thanks!%c(But now, you've lost it!)", Scrolls::kControlSpeechBubble);
+ _vm->_scrolls->displayText(tmpStr);
+ _vm->_gyro->_dna._objects[_thing - 1] = false;
+}
+
+/**
+ * @remarks Originally called 'do_that'
+ */
+void Acci::doThat() {
+ static const Common::String booze[] = {"Bitter", "GIED", "Whisky", "Cider", "", "", "", "Mead"};
+ static const char kWhat[] = "That's not possible!";
+
+ if (_thats == Common::String(kNothing)) {
+ if (!_thats.empty())
+ _thats.clear();
+ return;
+ }
+
+ if (_vm->_gyro->_weirdWord)
+ return;
+
+ if (_thing < 200)
+ _thing -= 49; // "Slip"
+
+
+ if ((_verb != kVerbCodeLoad) && (_verb != kVerbCodeSave) && (_verb != kVerbCodeQuit) && (_verb != kVerbCodeInfo) && (_verb != kVerbCodeHelp)
+ && (_verb != kVerbCodeLarrypass) && (_verb != kVerbCodePhaon) && (_verb != kVerbCodeBoss) && (_verb != kVerbCodeCheat) && (_verb != kVerbCodeRestart)
+ && (_verb != kVerbCodeDir) && (_verb != kVerbCodeScore) && (_verb != kVerbCodeHiscores) && (_verb != kVerbCodeSmartAlec)) {
+ if (!_vm->_gyro->_alive) {
+ _vm->_scrolls->displayText(Common::String("You're dead, so don't talk. What are you, a ghost or something? Try restarting, or restoring a saved game!"));
+ return;
+ }
+ if (!_vm->_gyro->_dna._avvyIsAwake && (_verb != kVerbCodeDie) && (_verb != kVerbCodeExpletive) && (_verb != kVerbCodeWake)) {
+ _vm->_scrolls->displayText("Talking in your sleep? Try waking up!");
+ return;
+ }
+ }
+
+ switch (_verb) {
+ case kVerbCodeExam:
+ examine();
+ break;
+ case kVerbCodeOpen:
+ openDoor();
+ break;
+ case kVerbCodePause: { // Note that the original game doesn't care about the "O.K." box neither, it accepts clicks from everywhere on the screen to continue. Just like my code.
+ Common::String tmpStr = Common::String::format("Game paused.%c%c%cPress Enter, Esc, or click the mouse on the \"O.K.\" box to continue.", Scrolls::kControlCenter, Scrolls::kControlNewLine, Scrolls::kControlNewLine);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodeGet:
+ if (_thing != kPardon) { // Legitimate try to pick something up.
+ if (_vm->_gyro->_dna._carryNum >= kCarryLimit)
+ _vm->_scrolls->displayText("You can't carry any more!");
+ else
+ getProc(_thing);
+ } else { // Not... ditto.
+ if (_person != kPardon)
+ _vm->_scrolls->displayText("You can't sweep folk off their feet!");
+ else
+ _vm->_scrolls->displayText("I assure you, you don't need it.");
+ }
+ break;
+ case kVerbCodeDrop:
+ _vm->_scrolls->displayText(Common::String("Two years ago you dropped a florin in the street. Three days ") +
+ "later it was gone! So now you never leave ANYTHING lying around. OK?");
+ break;
+ case kVerbCodeInv:
+ inventory();
+ break;
+ case kVerbCodeTalk:
+ if (_person == kPardon) {
+ if (_vm->_gyro->_subjectNum == 99) // They typed "say password".
+ _vm->_scrolls->displayText(Common::String("Yes, but what ") + Scrolls::kControlItalic + "is" + Scrolls::kControlRoman + " the password?");
+ else if (((1 <= _vm->_gyro->_subjectNum) && (_vm->_gyro->_subjectNum <= 49)) || (_vm->_gyro->_subjectNum == 253) || (_vm->_gyro->_subjectNum == 249)) {
+ _thats.deleteChar(0);
+
+ for (byte i = 0; i < 10; i++)
+ _realWords[i] = _realWords[i + 1];
+
+ _verb = _vm->_gyro->_subjectNum;
+ doThat();
+ return;
+ } else {
+ _person = _vm->_gyro->_subjectNum;
+ _vm->_gyro->_subjectNum = 0;
+ if ((_person == 0) || (_person == kPardon))
+ _vm->_scrolls->displayText("Talk to whom?");
+ else if (isPersonHere())
+ _vm->_visa->talkTo(_person);
+ }
+ } else if (isPersonHere())
+ _vm->_visa->talkTo(_person);
+ break;
+ case kVerbCodeGive:
+ if (isHolding()) {
+ if (_person == kPardon)
+ _vm->_scrolls->displayText("Give to whom?");
+ else if (isPersonHere()) {
+ switch (_thing) {
+ case Gyro::kObjectMoney :
+ _vm->_scrolls->displayText("You can't bring yourself to give away your moneybag.");
+ break;
+ case Gyro::kObjectBodkin:
+ case Gyro::kObjectBell:
+ case Gyro::kObjectClothes:
+ case Gyro::kObjectHabit :
+ _vm->_scrolls->displayText("Don't give it away, it might be useful!");
+ break;
+ default:
+ switch (_person) {
+ case Gyro::kPeopleCrapulus:
+ if (_thing == Gyro::kObjectWine) {
+ _vm->_scrolls->displayText("Crapulus grabs the wine and gulps it down.");
+ _vm->_gyro->_dna._objects[Gyro::kObjectWine - 1] = false;
+ } else
+ heyThanks();
+ break;
+ case Gyro::kPeopleCwytalot:
+ if ((_thing == Gyro::kObjectCrossbow) || (_thing == Gyro::kObjectBolt))
+ _vm->_scrolls->displayText(Common::String("You might be able to influence Cwytalot more if you used it!"));
+ else
+ heyThanks();
+ break;
+ case Gyro::kPeopleSpludwick:
+ if (giveToSpludwick())
+ heyThanks();
+ break;
+ case Gyro::kPeopleIbythneth:
+ if (_thing == Gyro::kObjectBadge) {
+ _vm->_visa->displayScrollChain('q', 32); // Thanks! Wow!
+ _vm->_lucerna->incScore(3);
+ _vm->_gyro->_dna._objects[Gyro::kObjectBadge - 1] = false;
+ _vm->_gyro->_dna._objects[Gyro::kObjectHabit - 1] = true;
+ _vm->_gyro->_dna._givenBadgeToIby = true;
+ _vm->_celer->drawBackgroundSprite(-1, -1, 8);
+ _vm->_celer->drawBackgroundSprite(-1, -1, 9);
+ } else
+ heyThanks();
+ break;
+ case Gyro::kPeopleAyles:
+ if (_vm->_gyro->_dna._aylesIsAwake) {
+ if (_thing == Gyro::kObjectPen) {
+ _vm->_gyro->_dna._objects[Gyro::kObjectPen - 1] = false;
+ _vm->_visa->displayScrollChain('q', 54);
+ _vm->_gyro->_dna._objects[Gyro::kObjectInk - 1] = true;
+ _vm->_gyro->_dna._givenPenToAyles = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_lucerna->incScore(2);
+ } else
+ heyThanks();
+ } else
+ _vm->_scrolls->displayText("But he's asleep!");
+ break;
+ case Gyro::kPeopleGeida:
+ switch (_thing) {
+ case Gyro::kObjectPotion:
+ _vm->_gyro->_dna._objects[Gyro::kObjectPotion - 1] = false;
+ _vm->_visa->displayScrollChain('u', 16); // She drinks it.
+ _vm->_lucerna->incScore(2);
+ _vm->_gyro->_dna._givenPotionToGeida = true;
+ _vm->_lucerna->refreshObjectList();
+ break;
+ case Gyro::kObjectLute:
+ giveGeidaTheLute();
+ break;
+ default:
+ heyThanks();
+ }
+ break;
+ case Gyro::kPeopleArkata:
+ switch (_thing) {
+ case Gyro::kObjectPotion:
+ if (_vm->_gyro->_dna._givenPotionToGeida)
+ winSequence();
+ else
+ _vm->_visa->displayScrollChain('q', 77); // That Geida woman!
+ break;
+ default:
+ heyThanks();
+ }
+ break;
+ default:
+ heyThanks();
+ }
+ }
+ }
+ _vm->_lucerna->refreshObjectList(); // Just in case...
+ }
+ break;
+
+ case kVerbCodeEat:
+ case kVerbCodeDrink:
+ if (isHolding())
+ swallow();
+ break;
+
+ case kVerbCodeLoad:
+ break;
+ case kVerbCodeSave:
+ break;
+ // We don't handle these two because we use ScummVM's save/load system.
+
+ case kVerbCodePay:
+ _vm->_scrolls->displayText("No money need change hands.");
+ break;
+ case kVerbCodeLook:
+ lookAround();
+ break;
+ case kVerbCodeBreak:
+ _vm->_scrolls->displayText("Vandalism is prohibited within this game!");
+ break;
+ case kVerbCodeQuit: // quit
+ if (_vm->_gyro->kDemo) {
+ warning("STUB: Acci::doThat() - case kVerbCodequit");
+ // _vm->_visa->displayScrollChain('pos', 31);
+ // close(demofile);
+ // exit(0); // Change this later!!!
+ }
+ if (!_polite)
+ _vm->_scrolls->displayText("How about a `please\", Avvy?");
+ else if (_vm->_scrolls->displayQuestion(Common::String(Scrolls::kControlRegister) + 'C' + Scrolls::kControlIcon + "Do you really want to quit?"))
+ _vm->_gyro->_letMeOut = true;
+ break;
+ case kVerbCodeGo:
+ _vm->_scrolls->displayText("Just use the arrow keys to walk there.");
+ break;
+ case kVerbCodeInfo: {
+ _vm->_scrolls->_aboutScroll = true;
+
+ Common::String toDisplay;
+ for (byte i = 0; i < 7; i++)
+ toDisplay += Scrolls::kControlNewLine;
+ toDisplay = toDisplay + "LORD AVALOT D'ARGENT" + Scrolls::kControlCenter + Scrolls::kControlNewLine
+ + "The medi\x91val descendant of" + Scrolls::kControlNewLine
+ + "Denarius Avaricius Sextus" + Scrolls::kControlNewLine + Scrolls::kControlNewLine
+ + "version " + _vm->_gyro->kVersionNum + Scrolls::kControlNewLine + Scrolls::kControlNewLine + "Copyright \xEF "
+ + _vm->_gyro->kCopyright + ", Mark, Mike and Thomas Thurman." + Scrolls::kControlRegister + 'Y' + Scrolls::kControlIcon;
+ _vm->_scrolls->displayText(toDisplay);
+ _vm->_scrolls->_aboutScroll = false;
+ }
+ break;
+ case kVerbCodeUndress:
+ if (_vm->_gyro->_dna._wearing == kNothing)
+ _vm->_scrolls->displayText("You're already stark naked!");
+ else if (_vm->_gyro->_dna._avvysInTheCupboard) {
+ _vm->_scrolls->displayText(Common::String("You take off ") + _vm->_gyro->getItem(_vm->_gyro->_dna._wearing) + '.');
+ _vm->_gyro->_dna._wearing = kNothing;
+ _vm->_lucerna->refreshObjectList();
+ } else
+ _vm->_scrolls->displayText("Hadn't you better find somewhere more private, Avvy?");
+ break;
+ case kVerbCodeWear:
+ if (isHolding()) { // Wear something.
+ switch (_thing) {
+ case Gyro::kObjectChastity:
+ // \? are used to avoid that ??! is parsed as a trigraph
+ _vm->_scrolls->displayText("Hey, what kind of a weirdo are you\?\?!");
+ break;
+ case Gyro::kObjectClothes:
+ case Gyro::kObjectHabit: { // Change this!
+ if (_vm->_gyro->_dna._wearing != kNothing) {
+ if (_vm->_gyro->_dna._wearing == _thing)
+ _vm->_scrolls->displayText("You're already wearing that.");
+ else
+ _vm->_scrolls->displayText("You'll be rather warm wearing two sets of clothes!");
+ return;
+ } else
+ _vm->_gyro->_dna._wearing = _thing;
+
+ _vm->_lucerna->refreshObjectList();
+
+ byte i;
+ if (_thing == Gyro::kObjectHabit)
+ i = 3;
+ else
+ i = 0;
+ if (_vm->_animation->_sprites[0]._id != i) {
+ int16 x = _vm->_animation->_sprites[0]._x;
+ int16 y = _vm->_animation->_sprites[0]._y;
+ _vm->_animation->_sprites[0].remove();
+ _vm->_animation->_sprites[0].init(i, true, _vm->_animation);
+ _vm->_animation->_sprites[0].appear(x, y, Animation::kDirLeft);
+ _vm->_animation->_sprites[0]._visible = false;
+ }
+ }
+ break;
+ default:
+ _vm->_scrolls->displayText(kWhat);
+ }
+ }
+ break;
+ case kVerbCodePlay:
+ if (_thing == kPardon) {
+ switch (_vm->_gyro->_dna._room) { // They just typed "play"...
+ case r__argentpub: { // ...in the pub, => play Nim.
+ warning("STUB: Acci::doThat() - case kVerbCodeplay");
+ // play_nim();
+ // The following parts are copied from play_nim().
+ // The player automatically wins the game everytime he wins, until I implement the mini-game.
+
+ if (_vm->_gyro->_dna._wonNim) { // Already won the game.
+ _vm->_visa->displayScrollChain('Q', 6);
+ return;
+ }
+
+ if (!_vm->_gyro->_dna._askedDogfoodAboutNim) {
+ _vm->_visa->displayScrollChain('q', 84);
+ return;
+ }
+
+ _vm->_visa->displayScrollChain('Q', 3);
+ _vm->_gyro->_dna._playedNim++;
+
+ // You won - strange!
+ _vm->_visa->displayScrollChain('Q', 7); // You won! Give us a lute!
+ _vm->_gyro->_dna._objects[Gyro::kObjectLute - 1] = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_gyro->_dna._wonNim = true;
+ _vm->_celer->drawBackgroundSprite(-1, -1, 1); // Show the settle with no lute on it.
+ _vm->_lucerna->incScore(7); // 7 points for winning!
+
+ if (_vm->_gyro->_dna._playedNim == 1)
+ _vm->_lucerna->incScore(3); // 3 points for playing your 1st game.
+
+ // A warning to the player that there should have been a mini-game. TODO: Remove it later!!!
+ _vm->_scrolls->displayText(Common::String("P.S.: There should have been the mini-game called \"Nim\", but I haven't implemented it yet: you win and get the lute automatically.")
+ + Scrolls::kControlNewLine + Scrolls::kControlNewLine + "Peter (uruk)");
+ }
+ break;
+ case r__musicroom:
+ playHarp();
+ break;
+ }
+ } else if (isHolding()) {
+ switch (_thing) {
+ case Gyro::kObjectLute :
+ _vm->_visa->displayScrollChain('U', 7);
+
+ if (_vm->_gyro->_whereIs[Gyro::kPeopleCwytalot - 150] == _vm->_gyro->_dna._room)
+ _vm->_visa->displayScrollChain('U', 10);
+
+ if (_vm->_gyro->_whereIs[Gyro::kPeopleDuLustie - 150] == _vm->_gyro->_dna._room)
+ _vm->_visa->displayScrollChain('U', 15);
+ break;
+ case 52:
+ if (_vm->_gyro->_dna._room == r__musicroom)
+ playHarp();
+ else
+ _vm->_scrolls->displayText(kWhat);
+ break;
+ case 55:
+ if (_vm->_gyro->_dna._room == r__argentpub)
+ // play_nim();
+ warning("STUB: Acci::doThat() - case kVerbCodeplay");
+ else
+ _vm->_scrolls->displayText(kWhat);
+ break;
+ default:
+ _vm->_scrolls->displayText(kWhat);
+ }
+ }
+ break;
+ case kVerbCodeRing:
+ if (isHolding()) {
+ if (_thing == Gyro::kObjectBell) {
+ _vm->_scrolls->displayText("Ding, dong, ding, dong, ding, dong, ding, dong...");
+ if ((_vm->_gyro->_dna._bellsAreRinging) & (_vm->_gyro->setFlag('B')))
+ // \? are used to avoid that ??! is parsed as a trigraph
+ _vm->_scrolls->displayText("(Are you trying to join in, Avvy\?\?!)");
+ } else
+ _vm->_scrolls->displayText(kWhat);
+ }
+ break;
+ case kVerbCodeHelp:
+ // boot_help();
+ warning("STUB: Acci::doThat() - case kVerbCodehelp");
+ break;
+ case kVerbCodeLarrypass:
+ _vm->_scrolls->displayText("Wrong game!");
+ break;
+ case kVerbCodePhaon:
+ _vm->_scrolls->displayText("Hello, Phaon!");
+ break;
+ case kVerbCodeBoss:
+ // bosskey();
+ warning("STUB: Acci::doThat() - case kVerbCodeboss");
+ break;
+ case kVerbCodePee:
+ if (_vm->_gyro->setFlag('P')) {
+ _vm->_scrolls->displayText("Hmm, I don't think anyone will notice...");
+ _vm->_timer->addTimer(4, Timer::kProcUrinate, Timer::kReasonGoToToilet);
+ } else
+ _vm->_scrolls->displayText(Common::String("It would be ") + Scrolls::kControlItalic + "VERY"
+ + Scrolls::kControlRoman + " unwise to do that here, Avvy!");
+ break;
+ case kVerbCodeCheat:
+ _vm->_scrolls->displayText(Common::String(Scrolls::kControlItalic) + "Cheat mode now enabled.");
+ _vm->_gyro->_cheat = true;
+ break;
+ case kVerbCodeMagic:
+ if (_vm->_gyro->_dna._avariciusTalk > 0)
+ _vm->_visa->displayScrollChain('q', 19);
+ else {
+ if ((_vm->_gyro->_dna._room == 12) & (_vm->_animation->inField(2))) { // Avaricius appears!
+ _vm->_visa->displayScrollChain('q', 17);
+ if (_vm->_gyro->_whereIs[1] == 12)
+ _vm->_visa->displayScrollChain('q', 18);
+ else {
+ _vm->_animation->_sprites[1].init(1, false, _vm->_animation); // Avaricius
+ _vm->_animation->appearPed(2, 4);
+ _vm->_animation->_sprites[1].walkTo(5);
+ _vm->_animation->_sprites[1]._callEachStepFl = true;
+ _vm->_animation->_sprites[1]._eachStepProc = Animation::kProcBackAndForth;
+ _vm->_gyro->_dna._avariciusTalk = 14;
+ _vm->_timer->addTimer(177, Timer::kProcAvariciusTalks, Timer::kReasonAvariciusTalks);
+ }
+ } else
+ _vm->_scrolls->displayText("Nothing appears to happen...");
+ }
+ break;
+ case kVerbCodeSmartAlec:
+ _vm->_scrolls->displayText("Listen, smart alec, that was just rhetoric.");
+ break;
+ case kVerbCodeExpletive:
+ switch (_vm->_gyro->_dna._sworeNum) {
+ case 0:
+ _vm->_scrolls->displayText(Common::String("Avvy! Do you mind? There might be kids playing!")
+ + Scrolls::kControlNewLine + Scrolls::kControlNewLine + "(I shouldn't say it again, if I were you!)");
+ break;
+ case 1:
+ _vm->_scrolls->displayText(Common::String("You hear a distant rumble of thunder. Must you always do things I tell you not to?")
+ + Scrolls::kControlNewLine + Scrolls::kControlNewLine + "Don't do it again!");
+ break;
+ default:
+ _vm->_pingo->zonk();
+ _vm->_scrolls->displayText(Common::String("A crack of lightning shoots from the sky, and fries you.")
+ + Scrolls::kControlNewLine + Scrolls::kControlNewLine + "(`Such is the anger of the gods, Avvy!\")");
+ _vm->_lucerna->gameOver();
+ }
+ _vm->_gyro->_dna._sworeNum++;
+ break;
+ case kVerbCodeListen:
+ if ((_vm->_gyro->_dna._bellsAreRinging) & (_vm->_gyro->setFlag('B')))
+ _vm->_scrolls->displayText("All other noise is drowned out by the ringing of the bells.");
+ else if (_vm->_gyro->_listen.empty())
+ _vm->_scrolls->displayText("You can't hear anything much at the moment, Avvy.");
+ else
+ _vm->_scrolls->displayText(_vm->_gyro->_listen);
+ break;
+ case kVerbCodeBuy: // What are they trying to buy?
+ switch (_vm->_gyro->_dna._room) {
+ case r__argentpub:
+ if (_vm->_animation->inField(6)) { // We're in a pub, and near the bar.
+ switch (_thing) {
+ case 51:
+ case 53:
+ case 54:
+ case 58: // Beer, whisky, cider or mead.
+ if (_vm->_gyro->_dna._malagauche == 177) { // Already getting us one.
+ _vm->_visa->displayScrollChain('D', 15);
+ return;
+ }
+
+ if (_vm->_gyro->_dna._teetotal) {
+ _vm->_visa->displayScrollChain('D', 6);
+ return;
+ }
+
+ if (_vm->_gyro->_dna._alcoholLevel == 0)
+ _vm->_lucerna->incScore(3);
+
+ _vm->_celer->drawBackgroundSprite(-1, -1, 12);
+ _vm->_scrolls->displayText(booze[_thing - 51] + ", please." + Scrolls::kControlRegister + '1' + Scrolls::kControlSpeechBubble);
+ _vm->_gyro->_dna._drinking = _thing;
+
+ _vm->_celer->drawBackgroundSprite(-1, -1, 10);
+ _vm->_gyro->_dna._malagauche = 177;
+ _vm->_timer->addTimer(27, Timer::kProcBuyDrinks, Timer::kReasonDrinks);
+ break;
+ case 52:
+ examine();
+ break; // We have a right one here - buy Pepsi??!
+ case Gyro::kObjectWine:
+ if (_vm->_gyro->_dna._objects[Gyro::kObjectWine - 1]) // We've already got the wine!
+ _vm->_visa->displayScrollChain('D', 2); // 1 bottle's shufishent!
+ else {
+ if (_vm->_gyro->_dna._malagauche == 177) { // Already getting us one.
+ _vm->_visa->displayScrollChain('D', 15);
+ return;
+ }
+
+ if (_vm->_gyro->_dna._carryNum >= kCarryLimit) {
+ _vm->_scrolls->displayText("Your hands are full.");
+ return;
+ }
+
+ _vm->_celer->drawBackgroundSprite(-1, -1, 12);
+ _vm->_scrolls->displayText(Common::String("Wine, please.") + Scrolls::kControlRegister + '1' + Scrolls::kControlSpeechBubble);
+ if (_vm->_gyro->_dna._alcoholLevel == 0)
+ _vm->_lucerna->incScore(3);
+ _vm->_celer->drawBackgroundSprite(-1, -1, 10);
+ _vm->_gyro->_dna._malagauche = 177;
+
+ _vm->_timer->addTimer(27, Timer::kProcBuyWine, Timer::kReasonDrinks);
+ }
+ break;
+ }
+ } else
+ _vm->_visa->displayScrollChain('D', 5); // Go to the bar!
+ break;
+
+ case r__outsideducks:
+ if (_vm->_animation->inField(6)) {
+ if (_thing == Gyro::kObjectOnion) {
+ if (_vm->_gyro->_dna._objects[Gyro::kObjectOnion - 1])
+ _vm->_visa->displayScrollChain('D', 10); // Not planning to juggle with the things!
+ else if (_vm->_gyro->_dna._carryNum >= kCarryLimit)
+ _vm->_scrolls->displayText("Before you ask, you remember that your hands are full.");
+ else {
+ if (_vm->_gyro->_dna._boughtOnion)
+ _vm->_visa->displayScrollChain('D', 11);
+ else {
+ _vm->_visa->displayScrollChain('D', 9);
+ _vm->_lucerna->incScore(3);
+ }
+ _vm->_gyro->decreaseMoney(3); // It costs thruppence.
+ _vm->_gyro->_dna._objects[Gyro::kObjectOnion - 1] = true;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_gyro->_dna._boughtOnion = true;
+ _vm->_gyro->_dna._rottenOnion = false; // It's OK when it leaves the stall!
+ _vm->_gyro->_dna._onionInVinegar = false;
+ }
+ } else
+ _vm->_visa->displayScrollChain('D', 0);
+ } else
+ _vm->_visa->displayScrollChain('D', 0);
+ break;
+
+ case r__nottspub:
+ _vm->_visa->displayScrollChain('n', 15); // Can't sell to southerners.
+ break;
+ default:
+ _vm->_visa->displayScrollChain('D', 0); // Can't buy that.
+ }
+ break;
+ case kVerbCodeAttack:
+ if ((_vm->_gyro->_dna._room == r__brummieroad) &&
+ ((_person == 157) || (_thing == Gyro::kObjectCrossbow) || (_thing == Gyro::kObjectBolt))
+ && (_vm->_gyro->_whereIs[7] == _vm->_gyro->_dna._room)) {
+ switch (_vm->_gyro->_dna._objects[Gyro::kObjectBolt - 1] + _vm->_gyro->_dna._objects[Gyro::kObjectCrossbow - 1] * 2) {
+ // 0 = neither, 1 = only bolt, 2 = only crossbow, 3 = both.
+ case 0:
+ _vm->_visa->displayScrollChain('Q', 10);
+ _vm->_scrolls->displayText("(At the very least, don't use your bare hands!)");
+ break;
+ case 1:
+ _vm->_scrolls->displayText("Attack _vm->_gyro->him with only a crossbow bolt? Are you planning on playing darts?!");
+ break;
+ case 2:
+ _vm->_scrolls->displayText("Come on, Avvy! You're not going to get very far with only a crossbow!");
+ break;
+ case 3:
+ _vm->_visa->displayScrollChain('Q', 11);
+ _vm->_gyro->_dna._cwytalotGone = true;
+ _vm->_gyro->_dna._objects[Gyro::kObjectBolt - 1] = false;
+ _vm->_gyro->_dna._objects[Gyro::kObjectCrossbow - 1] = false;
+ _vm->_lucerna->refreshObjectList();
+ _vm->_gyro->_magics[11]._operation = Gyro::kMagicNothing;
+ _vm->_lucerna->incScore(7);
+ _vm->_animation->_sprites[1].walkTo(2);
+ _vm->_animation->_sprites[1]._vanishIfStill = true;
+ _vm->_animation->_sprites[1]._callEachStepFl = false;
+ _vm->_gyro->_whereIs[7] = 177;
+ break;
+ default:
+ _vm->_visa->displayScrollChain('Q', 10); // Please try not to be so violent!
+ }
+ } else
+ _vm->_visa->displayScrollChain('Q', 10);
+ break;
+ case kVerbCodePasswd:
+ if (_vm->_gyro->_dna._room != r__bridge)
+ _vm->_visa->displayScrollChain('Q', 12);
+ else {
+ bool ok = true;
+ for (byte i = 0; i < _thats.size(); i++) {
+ Common::String temp = _realWords[i];
+ temp.toUppercase();
+ int pwdId = _vm->_gyro->_dna._passwordNum + kFirstPassword;
+ for (byte j = 0; j < kVocabulary[pwdId]._word.size(); j++) {
+ if (kVocabulary[pwdId]._word[j] != temp[j])
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ if (_vm->_gyro->_dna._drawbridgeOpen != 0)
+ _vm->_scrolls->displayText("Contrary to your expectations, the drawbridge fails to close again.");
+ else {
+ _vm->_lucerna->incScore(4);
+ _vm->_scrolls->displayText("The drawbridge opens!");
+ _vm->_timer->addTimer(7, Timer::kProcOpenDrawbridge, Timer::kReasonDrawbridgeFalls);
+ _vm->_gyro->_dna._drawbridgeOpen = 1;
+ }
+ } else
+ _vm->_visa->displayScrollChain('Q', 12);
+ }
+ break;
+ case kVerbCodeDir:
+ _vm->_enid->dir(_realWords[1]);
+ break;
+ case kVerbCodeDie:
+ _vm->_lucerna->gameOver();
+ break;
+ case kVerbCodeScore: {
+ Common::String tmpStr = Common::String::format("Your score is %d,%c%cout of a possible 128.%c%cThis gives you a rank of %s.%c%c%s", _vm->_gyro->_dna._score, Scrolls::kControlCenter, Scrolls::kControlNewLine, Scrolls::kControlNewLine, Scrolls::kControlNewLine, rank().c_str(), Scrolls::kControlNewLine, Scrolls::kControlNewLine, totalTime().c_str());
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodePut:
+ putProc();
+ break;
+ case kVerbCodeStand:
+ standUp();
+ break;
+ case kVerbCodeKiss:
+ if (_person == kPardon)
+ _vm->_scrolls->displayText("Kiss whom?");
+ else if (isPersonHere()) {
+ switch (_person) {
+ case Gyro::kPeopleArkata:
+ _vm->_visa->displayScrollChain('U', 12);
+ break;
+ case Gyro::kPeopleGeida:
+ _vm->_visa->displayScrollChain('U', 13);
+ break;
+ case Gyro::kPeopleWisewoman:
+ _vm->_visa->displayScrollChain('U', 14);
+ break;
+ default:
+ _vm->_visa->displayScrollChain('U', 5); // You WHAT?
+ }
+ } else if ((150 <= _person) && (_person <= 174))
+ _vm->_scrolls->displayText("Hey, what kind of a weirdo are you??");
+
+ break;
+ case kVerbCodeClimb:
+ if (_vm->_gyro->_dna._room == r__insidecardiffcastle)
+ cardiffClimbing();
+ else // In the wrong room!
+ _vm->_scrolls->displayText("Not with your head for heights, Avvy!");
+ break;
+ case kVerbCodeJump:
+ _vm->_timer->addTimer(1, Timer::kProcJump, Timer::kReasonJumping);
+ _vm->_gyro->_dna._userMovesAvvy = false;
+ break;
+ case kVerbCodeHiscores:
+ // show_highs();
+ warning("STUB: Acci::doThat() - case kVerbCodehighscores");
+ break;
+ case kVerbCodeWake:
+ if (isPersonHere())
+ switch (_person) {
+ case kPardon:
+ case Gyro::kPeopleAvalot:
+ case 0:
+ if (!_vm->_gyro->_dna._avvyIsAwake) {
+ _vm->_gyro->_dna._avvyIsAwake = true;
+ _vm->_lucerna->incScore(1);
+ _vm->_gyro->_dna._avvyInBed = true;
+ _vm->_celer->drawBackgroundSprite(-1, -1, 3); // Picture of Avvy, awake in bed.
+ if (_vm->_gyro->_dna._teetotal)
+ _vm->_visa->displayScrollChain('d', 13);
+ } else
+ _vm->_scrolls->displayText("You're already awake, Avvy!");
+ break;
+ case Gyro::kPeopleAyles:
+ if (!_vm->_gyro->_dna._aylesIsAwake)
+ _vm->_scrolls->displayText("You can't seem to wake him by yourself.");
+ break;
+ case Gyro::kPeopleJacques: {
+ Common::String tmpStr = Common::String::format("Brother Jacques, Brother Jacques, are you asleep?%c1%c" \
+ "Hmmm... that doesn't seem to do any good...", Scrolls::kControlRegister, Scrolls::kControlSpeechBubble);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ break;
+ default:
+ _vm->_scrolls->displayText("It's difficult to awaken people who aren't asleep...!");
+ }
+ break;
+ case kVerbCodeSit:
+ if (_vm->_gyro->_dna._room == r__nottspub) {
+ if (_vm->_gyro->_dna._sittingInPub)
+ _vm->_scrolls->displayText("You're already sitting!");
+ else {
+ _vm->_animation->_sprites[0].walkTo(4); // Move Avvy to the place, and sit him down.
+ _vm->_timer->addTimer(1, Timer::kProcAvvySitDown, Timer::kReasonSittingDown);
+ }
+ } else { // Default doodah.
+ _vm->_lucerna->dusk();
+ _vm->_gyro->hangAroundForAWhile();
+ _vm->_lucerna->dawn();
+ Common::String tmpStr = Common::String::format("A few hours later...%cnothing much has happened...", Scrolls::kControlParagraph);
+ _vm->_scrolls->displayText(tmpStr);
+ }
+ break;
+ case kVerbCodeRestart:
+ if (_vm->_scrolls->displayQuestion("Restart game and lose changes?")) {
+ _vm->_lucerna->dusk();
+ _vm->_gyro->newGame();
+ _vm->_lucerna->dawn();
+ }
+ break;
+ case kPardon:
+ _vm->_scrolls->displayText("Hey, a verb would be helpful!");
+ break;
+ case kVerbCodeHello:
+ personSpeaks();
+ _vm->_scrolls->displayText(Common::String("Hello.") + Scrolls::kControlSpeechBubble);
+ break;
+ case kVerbCodeThanks:
+ personSpeaks();
+ _vm->_scrolls->displayText(Common::String("That's OK.") + Scrolls::kControlSpeechBubble);
+ break;
+ default:
+ _vm->_scrolls->displayText(Common::String(Scrolls::kControlBell) + "Parser bug!");
+ }
+}
+
+void Acci::verbOpt(byte verb, Common::String &answer, char &ansKey) {
+ switch (verb) {
+ case kVerbCodeExam:
+ answer = "Examine";
+ ansKey = 'x';
+ break; // The ubiquitous one.
+ // kVerbCodegive isn't dealt with by this procedure, but by ddm__with.
+ case kVerbCodeDrink:
+ answer = "Drink";
+ ansKey = 'D';
+ break;
+ case kVerbCodeWear:
+ answer = "Wear";
+ ansKey = 'W';
+ break;
+ case kVerbCodeRing:
+ answer = "Ring";
+ ansKey = 'R';
+ break; // Only the bell!
+ case kVerbCodePlay:
+ answer = "Play";
+ ansKey = 'P';
+ break;
+ case kVerbCodeEat:
+ answer = "Eat";
+ ansKey = 'E';
+ break;
+ default:
+ answer = "? Unknown!"; // Bug!
+ ansKey = '?';
+ }
+}
+
+} // End of namespace Avalanche.