/* 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. * */ #include "common/file.h" #include "titanic/true_talk/tt_vocab.h" #include "titanic/true_talk/tt_adj.h" #include "titanic/true_talk/tt_action.h" #include "titanic/true_talk/tt_adj.h" #include "titanic/true_talk/tt_major_word.h" #include "titanic/true_talk/tt_picture.h" #include "titanic/true_talk/tt_pronoun.h" #include "titanic/titanic.h" namespace Titanic { TTvocab::TTvocab(int val): _headP(nullptr), _tailP(nullptr), _word(nullptr), _fieldC(0), _field10(0), _vocabMode(val) { _field14 = load("STVOCAB.TXT"); } TTvocab::~TTvocab() { if (_headP) { _headP->deleteSiblings(); delete _headP; _headP = _tailP = nullptr; } } int TTvocab::load(const CString &name) { SimpleFile *file = g_vm->_exeResources._owner->openResource(name); int result = 0; bool skipFlag; while (!result && !file->eos()) { skipFlag = false; WordMode mode = (WordMode)file->readNumber(); TTstring space(" "); switch (mode) { case 0: { if (_word) result = _word->readSyn(file); skipFlag = true; break; } case 1: { TTaction *word = new TTaction(space, WMODE_NONE, 0, 0, 0); result = word->load(file); _word = word; break; } case 2: { TTpicture *word = new TTpicture(space, WMODE_NONE, 0, 0, 0, 0, 0); result = word->load(file); _word = word; break; } case 3: case 9: { TTmajorWord *word = new TTmajorWord(space, WMODE_NONE, 0, 0); result = word->load(file, mode); _word = word; break; } case 4: case 5: case 7: { TTword *word = new TTword(space, WMODE_NONE, 0); result = word->load(file, mode); _word = word; break; } case 8: { TTadj *word = new TTadj(space, WMODE_NONE, 0, 0, 0); result = word->load(file); _word = word; break; } case 6: { TTpronoun *word = new TTpronoun(space, WMODE_NONE, 0, 0, 0); result = word->load(file); _word = word; break; } default: result = 4; break; } if (!skipFlag && _word) { if (result) { // Something wrong occurred, so delete word delete _word; _word = nullptr; } else { // Add the word to the master vocab list addWord(_word); } } } // Close resource and return result delete file; return result; } void TTvocab::addWord(TTword *word) { TTword *existingWord = findWord(word->_string); if (existingWord) { if (word->_synP) { // Move over the synonym existingWord->appendNode(word->_synP); word->_synP = nullptr; } _word = nullptr; if (word) delete word; } else if (_tailP) { _tailP->_nextP = word; _tailP = word; } else { if (!_headP) _headP = word; _tailP = word; } } TTword *TTvocab::findWord(const TTstring &str) { TTsynonym *tempNode = new TTsynonym(); bool flag = false; TTword *word = _headP; while (word && !flag) { if (_vocabMode != 3 || strcmp(word->c_str(), str)) { if (word->findSynByName(str, tempNode, _vocabMode)) flag = true; else word = word->_nextP; } else { flag = true; } } delete tempNode; return word; } TTword *TTvocab::getWord(TTstring &str, TTword **srcWord) const { TTword *word = getPrimeWord(str, srcWord); if (!word) { TTstring tempStr(str); if (tempStr.size() > 2) { word = getSuffixedWord(tempStr); if (!word) word = getPrefixedWord(tempStr); } } return word; } TTword *TTvocab::getPrimeWord(TTstring &str, TTword **srcWord) const { TTsynonym tempSyn; char c = str.charAt(0); TTword *newWord = nullptr; TTword *vocabP; if (!Common::isDigit(c)) { vocabP = _headP; newWord = new TTword(str, WMODE_3, 300); } else { for (vocabP = _headP; vocabP && !newWord; vocabP = vocabP->_nextP) { if (_vocabMode == 3 && !strcmp(str.c_str(), vocabP->c_str())) { newWord = vocabP->copy(); newWord->_nextP = nullptr; newWord->setSyn(nullptr); } else if (vocabP->findSynByName(str, &tempSyn, _vocabMode)) { // Create a copy of the word and the found synonym TTsynonym *newSyn = new TTsynonym(tempSyn); newSyn->_nextP = newSyn->_priorP = nullptr; newWord = vocabP->copy(); newWord->_nextP = nullptr; newWord->setSyn(newSyn); } } } if (srcWord) // Pass out the pointer to the original word *srcWord = vocabP; // Return the new copy of the word return newWord; } TTword *TTvocab::getSuffixedWord(TTstring &str) const { TTstring tempStr(str); TTword *word = nullptr; if (tempStr.hasSuffix("s")) { tempStr.deleteSuffix(1); word = getPrimeWord(tempStr); if (!word) { if (!tempStr.hasSuffix("e")) { tempStr = str; } else { tempStr.deleteLastChar(); word = getPrimeWord(tempStr); } } } else if (tempStr.hasSuffix("ing")) { tempStr.deleteSuffix(3); word = getPrimeWord(tempStr); if (word) { if (word->_wordMode == 1) { delete word; word = nullptr; } else { delete word; word = new TTadj(str, WMODE_8, 0, 0, 0); } } else { tempStr += "e"; word = getPrimeWord(tempStr); if (word) { if (word->_wordMode != 1) { delete word; word = new TTadj(str, WMODE_8, 0, 0, 0); } } else { tempStr.deleteSuffix(2); word = getPrimeWord(tempStr); if (word) { if (word->_wordMode != 1) { delete word; word = new TTadj(str, WMODE_8, 0, 0, 0); } } else { tempStr = str; } } } } else if (tempStr.hasSuffix("ed")) { tempStr.deleteSuffix(1); word = getPrimeWord(tempStr); // TODO } // TODO return nullptr; } TTword *TTvocab::getPrefixedWord(TTstring &str) const { TTstring tempStr(str); TTword *word = nullptr; int prefixLen = 0; if (tempStr.hasPrefix("pre")) { prefixLen = 3; } else if (tempStr.hasPrefix("re") || tempStr.hasPrefix("co")) { prefixLen = 2; } else if (tempStr.hasPrefix("inter") || tempStr.hasPrefix("multi")) { prefixLen = 5; } else if (tempStr.hasPrefix("over") || tempStr.hasPrefix("post") || tempStr.hasPrefix("self")) { prefixLen = 4; } if (prefixLen) { // Known prefix found, so scan for word without prefix tempStr.deletePrefix(prefixLen); word = getPrimeWord(tempStr); if (word) tempStr = str; } else if (tempStr.hasPrefix("anti") || tempStr.hasPrefix("counter")) { prefixLen = tempStr[0] == 'a' ? 4 : 7; tempStr.deletePrefix(prefixLen); word = getPrimeWord(tempStr); if (!word) tempStr = str; else if (word->_wordMode == 8) { delete word; word = nullptr; } } else if (tempStr.hasPrefix("hyper") || tempStr.hasPrefix("super") || tempStr.hasPrefix("ultra")) { tempStr.deletePrefix(5); word = getPrimeWord(tempStr); if (!word) tempStr = str; else if (word->_wordMode == 8) { int val1 = word->proc15(); int val2 = word->proc15(); if (val2 < 5) { if (--val1 > 0) word->unkFn1(val1); } else if (++val1 < 11) { word->unkFn1(val1); } } } if (word) { // Set the original word on either the found word or synonym if (word->hasSynonyms()) word->setSynStr(&str); else word->_string = str; } delete tempStr; return word; } } // End of namespace Titanic