1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "titanic/true_talk/tt_concept.h"
24 #include "titanic/true_talk/script_handler.h"
25 #include "titanic/true_talk/tt_script_base.h"
26 #include "titanic/true_talk/tt_word.h"
27 #include "titanic/titanic.h"
28 
29 namespace Titanic {
30 
TTconcept()31 TTconcept::TTconcept() : _string1(" "), _string2(" "),
32 		_nextP(nullptr), _scriptP(nullptr), _wordP(nullptr), _word2P(nullptr), _status(SS_VALID),
33 		_scriptType(ST_UNKNOWN_SCRIPT), _field14(0), _field1C(0), _field20(0), _field30(0), _field34(0) {
34 	if (setStatus())
35 		setScriptType(ST_UNKNOWN_SCRIPT);
36 	else
37 		reset();
38 }
39 
TTconcept(TTscriptBase * script,ScriptType scriptType)40 TTconcept::TTconcept(TTscriptBase *script, ScriptType scriptType) :
41 		_string1(" "), _string2(" "), _nextP(nullptr), _wordP(nullptr), _word2P(nullptr), _scriptP(nullptr),
42 		_status(SS_VALID), _scriptType(ST_UNKNOWN_SCRIPT), _field14(0), _field1C(0), _field20(0), _field30(0),
43 		_field34(0) {
44 	if (!script->getStatus()) {
45 		setScriptType(scriptType);
46 		_scriptP = script;
47 
48 		if (scriptType == ST_UNKNOWN_SCRIPT && script->_id == 1)
49 			_scriptType = ST_ROOM_SCRIPT;
50 	}
51 
52 	if (_status)
53 		reset();
54 }
55 
TTconcept(TTword * word,ScriptType scriptType)56 TTconcept::TTconcept(TTword *word, ScriptType scriptType) :
57 		_string1(" "), _string2(" "), _nextP(nullptr), _wordP(nullptr), _word2P(nullptr), _scriptP(nullptr),
58 		_status(SS_VALID), _scriptType(ST_UNKNOWN_SCRIPT), _field14(0), _field1C(0), _field20(0),
59 		_field30(0), _field34(0), _flag(false) {
60 	if (!word || !setStatus() || word->getStatus()) {
61 		_status = SS_5;
62 	} else {
63 		_status = initializeWordRef(word);
64 		if (!_status)
65 			setScriptType(scriptType);
66 	}
67 
68 	if (_status)
69 		reset();
70 }
71 
TTconcept(TTconcept & src)72 TTconcept::TTconcept(TTconcept &src) :
73 		_string1(src._string1), _string2(src._string2), _nextP(nullptr),
74 		_wordP(nullptr), _word2P(nullptr), _scriptP(nullptr), _status(SS_VALID),
75 		_scriptType(ST_UNKNOWN_SCRIPT), _field14(0), _field1C(0), _field20(0),
76 		_field30(0), _field34(0), _flag(false) {
77 	if (src.getStatus()) {
78 		_status = SS_5;
79 	} else {
80 		if (setStatus()) {
81 			_status = SS_VALID;
82 			_scriptP = src._scriptP;
83 
84 			if (src._wordP) {
85 				_status = initializeWordRef(src._wordP);
86 				initialize(src);
87 			}
88 		}
89 	}
90 
91 	if (_status)
92 		reset();
93 }
94 
~TTconcept()95 TTconcept::~TTconcept() {
96 	if (_word2P) {
97 		_word2P->deleteSiblings();
98 		delete _word2P;
99 	}
100 	delete _wordP;
101 
102 	if (_flag)
103 		g_vm->_exeResources._owner->setParserConcept(this, nullptr);
104 }
105 
deleteSiblings()106 void TTconcept::deleteSiblings() {
107 	for (TTconcept *currP = _nextP, *nextP; currP; currP = nextP) {
108 		nextP = currP->_nextP;
109 		delete currP;
110 	}
111 
112 	_nextP = nullptr;
113 }
114 
setStatus()115 bool TTconcept::setStatus() {
116 	if (_string1.isValid() && _string2.isValid()) {
117 		_status = SS_VALID;
118 		return true;
119 	} else {
120 		_status = SS_11;
121 		return false;
122 	}
123 }
124 
setScriptType(ScriptType scriptType)125 void TTconcept::setScriptType(ScriptType scriptType) {
126 	_nextP = nullptr;
127 	_field14 = 0;
128 	_scriptType = scriptType;
129 	_field1C = -1;
130 	_field20 = 0;
131 	_word2P = nullptr;
132 	_field30 = 0;
133 	_field34 = 0;
134 	_flag = false;
135 	_status = 0;
136 }
137 
initializeWordRef(TTword * word)138 int TTconcept::initializeWordRef(TTword *word) {
139 	delete _wordP;
140 	_wordP = word->copy();
141 	return 0;
142 }
143 
reset()144 void TTconcept::reset() {
145 	delete _wordP;
146 	_wordP = nullptr;
147 	_scriptP = nullptr;
148 
149 	int oldStatus = _status;
150 	setScriptType(ST_UNKNOWN_SCRIPT);
151 	_status = oldStatus;
152 }
153 
compareTo(const char * str) const154 bool TTconcept::compareTo(const char *str) const {
155 	return _wordP != nullptr &&
156 		_wordP->compareTo(str);
157 }
158 
compareTo(TTword * word) const159 bool TTconcept::compareTo(TTword *word) const {
160 	if (_wordP && _wordP->compareTo(word->_text))
161 		return true;
162 
163 	if (_scriptP && _scriptP->getId() == 1 && word->comparePronounTo(1))
164 		return true;
165 
166 	return false;
167 }
168 
initialize(TTconcept & src)169 void TTconcept::initialize(TTconcept &src) {
170 	_nextP = src._nextP;
171 	_field14 = src._field14;
172 	_scriptType = src._scriptType;
173 	_field1C = src._field1C;
174 	_field20 = src._field20;
175 
176 	if (src._word2P) {
177 		_word2P = src._word2P->copyWords();
178 		if (src._word2P->getChainStatus())
179 			_status = 11;
180 	} else {
181 		_word2P = nullptr;
182 	}
183 
184 	_field30 = src._field30;
185 	_field34 = src._field34;
186 
187 	if (src._flag) {
188 		g_vm->_exeResources._owner->setParserConcept(this, &src);
189 		src.setFlag(true);
190 		_flag = true;
191 	}
192 
193 	_status = src._status;
194 }
195 
copyFrom(TTconcept * src)196 void TTconcept::copyFrom(TTconcept *src) {
197 	if (this != src) {
198 		if (src->getStatus()) {
199 			_status = SS_5;
200 		} else {
201 			_string1 = src->_string1;
202 			_string2 = src->_string2;
203 
204 			if (setStatus()) {
205 				_scriptP = src->_scriptP;
206 				if (src->_wordP) {
207 					_status = initializeWordRef(src->_wordP);
208 					initialize(*src);
209 				} else {
210 					_wordP = nullptr;
211 					initialize(*src);
212 				}
213 			}
214 		}
215 	}
216 
217 	if (_status)
218 		reset();
219 }
220 
setOwner(TTconcept * src)221 int TTconcept::setOwner(TTconcept *src) {
222 	if (src->_wordP) {
223 		TTword *newWord = src->_wordP->copy();
224 		return setOwner(newWord, 1);
225 	}
226 
227 	return 0;
228 }
229 
setOwner(TTword * src,bool dontDup)230 int TTconcept::setOwner(TTword *src, bool dontDup) {
231 	TTword *word = dontDup ? src : src->copy();
232 
233 	if (word) {
234 		if (!_word2P) {
235 			_word2P = word;
236 		} else {
237 			// Add word to end of word list
238 			TTword *tailP = _word2P;
239 			while (tailP->_nextP)
240 				tailP = tailP->_nextP;
241 
242 			tailP->_nextP = word;
243 		}
244 	}
245 
246 	return 0;
247 }
248 
checkWordId1() const249 bool TTconcept::checkWordId1() const {
250 	return (_wordP && (_wordP->_id == 200 || _wordP->_id == 201 ||
251 		_wordP->_id == 602 || _wordP->_id == 607)) ||
252 		(_scriptP && _scriptP->_id <= 2);
253 }
254 
checkWordId2() const255 bool TTconcept::checkWordId2() const {
256 	return (_wordP && _wordP->_id == 204) || (_scriptP && _scriptP->getId() == 3);
257 }
258 
checkWordId3() const259 bool TTconcept::checkWordId3() const {
260 	return isWordClass(WC_ABSTRACT) || isWordClass(WC_ADJECTIVE) ||
261 		(isWordClass(WC_ADVERB) && getTheWordId() != 910);
262 }
263 
checkWordClass() const264 bool TTconcept::checkWordClass() const {
265 	return _scriptP || (_wordP && (_wordP->_wordClass == WC_THING || _wordP->_wordClass == WC_PRONOUN));
266 }
267 
getText()268 const TTstring TTconcept::getText() {
269 	if (_scriptP)
270 		return _scriptP->getText();
271 	else if (_wordP)
272 		return _wordP->getText();
273 	else
274 		return TTstring();
275 }
276 
findByWordId(int id)277 TTconcept *TTconcept::findByWordId(int id) {
278 	for (TTconcept *conceptP = this; conceptP; conceptP = conceptP->_nextP) {
279 		if (conceptP->_wordP && conceptP->_wordP->_id == id)
280 			return conceptP;
281 	}
282 
283 	return nullptr;
284 }
285 
findByWordClass(WordClass wordClass)286 TTconcept *TTconcept::findByWordClass(WordClass wordClass) {
287 	for (TTconcept *conceptP = this; conceptP; conceptP = conceptP->_nextP) {
288 		if (conceptP->_wordP && conceptP->_wordP->_wordClass == wordClass)
289 			return conceptP;
290 	}
291 
292 	return nullptr;
293 }
294 
findBy20(int val)295 TTconcept *TTconcept::findBy20(int val) {
296 	for (TTconcept *conceptP = this; conceptP; conceptP = conceptP->_nextP) {
297 		if (conceptP->_field20 == val)
298 			return conceptP;
299 	}
300 
301 	return nullptr;
302 }
303 
isTheWordId(int id) const304 bool TTconcept::isTheWordId(int id) const {
305 	return _wordP && _wordP->_id == id;
306 }
307 
getTheWordId() const308 int TTconcept::getTheWordId() const {
309 	return _wordP ? _wordP->_id : 0;
310 }
311 
isWordId(const TTconcept * concept,int id)312 bool isWordId(const TTconcept *concept, int id) {
313 	return concept ? concept->isTheWordId(id) : 0;
314 }
315 
getWordId(const TTconcept * concept)316 int getWordId(const TTconcept *concept) {
317 	return concept ? concept->getTheWordId() : 0;
318 }
319 
320 } // End of namespace Titanic
321