]> git.localhorst.tv Git - l2e.git/blob - src/loader/Interpreter.cpp
moved menu prototypes to test.l2s
[l2e.git] / src / loader / Interpreter.cpp
1 /*
2  * Interpreter.cpp
3  *
4  *  Created on: Aug 26, 2012
5  *      Author: holy
6  */
7
8 #include "Interpreter.h"
9
10 #include "ParsedSource.h"
11 #include "../battle/Hero.h"
12 #include "../battle/Monster.h"
13 #include "../battle/PartyLayout.h"
14 #include "../common/Ikari.h"
15 #include "../common/Item.h"
16 #include "../common/Spell.h"
17 #include "../common/TargetingMode.h"
18 #include "../graphics/ComplexAnimation.h"
19 #include "../graphics/Font.h"
20 #include "../graphics/Frame.h"
21 #include "../graphics/Gauge.h"
22 #include "../graphics/Menu.h"
23 #include "../graphics/SimpleAnimation.h"
24 #include "../graphics/Sprite.h"
25
26 #include <algorithm>
27 #include <cstring>
28 #include <SDL_image.h>
29
30 using battle::Hero;
31 using battle::Monster;
32 using battle::PartyLayout;
33 using battle::Stats;
34 using common::Ikari;
35 using common::Item;
36 using common::Spell;
37 using common::TargetingMode;
38 using graphics::Animation;
39 using graphics::Color;
40 using graphics::Font;
41 using graphics::Frame;
42 using graphics::Gauge;
43 using graphics::ComplexAnimation;
44 using graphics::SimpleAnimation;
45 using graphics::Sprite;
46 using geometry::Vector;
47 using std::make_pair;
48 using std::map;
49 using std::set;
50 using std::string;
51 using std::vector;
52
53 namespace loader {
54
55 Interpreter::~Interpreter() {
56         for (vector<ComplexAnimation *>::const_iterator i(complexAnimations.begin()), end(complexAnimations.end()); i != end; ++i) {
57                 delete *i;
58         }
59         for (vector<Font *>::const_iterator i(fonts.begin()), end(fonts.end()); i != end; ++i) {
60                 delete *i;
61         }
62         for (vector<Frame *>::const_iterator i(frames.begin()), end(frames.end()); i != end; ++i) {
63                 delete *i;
64         }
65         for (vector<Gauge *>::const_iterator i(gauges.begin()), end(gauges.end()); i != end; ++i) {
66                 delete *i;
67         }
68         for (vector<Hero *>::const_iterator i(heroes.begin()), end(heroes.end()); i != end; ++i) {
69                 delete *i;
70         }
71         for (vector<Ikari *>::const_iterator i(ikaris.begin()), end(ikaris.end()); i != end; ++i) {
72                 delete *i;
73         }
74         for (vector<SDL_Surface *>::const_iterator i(images.begin()), end(images.end()); i != end; ++i) {
75                 SDL_FreeSurface(*i);
76         }
77         for (vector<Item *>::const_iterator i(items.begin()), end(items.end()); i != end; ++i) {
78                 delete *i;
79         }
80         for (vector<graphics::MenuProperties *>::const_iterator i(menuProperties.begin()), end(menuProperties.end()); i != end; ++i) {
81                 delete *i;
82         }
83         for (vector<Monster *>::const_iterator i(monsters.begin()), end(monsters.end()); i != end; ++i) {
84                 delete *i;
85         }
86         for (vector<PartyLayout *>::const_iterator i(partyLayouts.begin()), end(partyLayouts.end()); i != end; ++i) {
87                 delete *i;
88         }
89         for (vector<SimpleAnimation *>::const_iterator i(simpleAnimations.begin()), end(simpleAnimations.end()); i != end; ++i) {
90                 delete *i;
91         }
92         for (vector<Spell *>::const_iterator i(spells.begin()), end(spells.end()); i != end; ++i) {
93                 delete *i;
94         }
95         for (vector<Sprite *>::const_iterator i(sprites.begin()), end(sprites.end()); i != end; ++i) {
96                 delete *i;
97         }
98         for (vector<const char *>::const_iterator i(strings.begin()), end(strings.end()); i != end; ++i) {
99                 delete *i;
100         }
101         for (vector<TargetingMode *>::const_iterator i(targetingModes.begin()), end(targetingModes.end()); i != end; ++i) {
102                 delete *i;
103         }
104 }
105
106
107 Animation *Interpreter::GetAnimation(const std::string &name) {
108         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
109         if (i != parsedDefinitions.end()) {
110                 if (i->second.type == COMPLEX_ANIMATION) {
111                         return complexAnimations[i->second.index];
112                 } else if (i->second.type == SIMPLE_ANIMATION) {
113                         return simpleAnimations[i->second.index];
114                 } else {
115                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Animation");
116                 }
117         } else {
118                 throw Error("access to undefined Animation " + name);
119         }
120 }
121
122 bool Interpreter::GetBoolean(const std::string &name) const {
123         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
124         if (i != parsedDefinitions.end()) {
125                 if (i->second.type == BOOLEAN) {
126                         return booleans[i->second.index];
127                 } else {
128                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Boolean");
129                 }
130         } else {
131                 throw Error("access to undefined Boolean " + name);
132         }
133 }
134
135 const Color &Interpreter::GetColor(const std::string &name) const {
136         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
137         if (i != parsedDefinitions.end()) {
138                 if (i->second.type == COLOR) {
139                         return colors[i->second.index];
140                 } else {
141                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Color");
142                 }
143         } else {
144                 throw Error("access to undefined Color " + name);
145         }
146 }
147
148 Font *Interpreter::GetFont(const std::string &name) {
149         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
150         if (i != parsedDefinitions.end()) {
151                 if (i->second.type == FONT) {
152                         return fonts[i->second.index];
153                 } else {
154                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Font");
155                 }
156         } else {
157                 throw Error("access to undefined Font " + name);
158         }
159 }
160
161 Frame *Interpreter::GetFrame(const std::string &name) {
162         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
163         if (i != parsedDefinitions.end()) {
164                 if (i->second.type == FRAME) {
165                         return frames[i->second.index];
166                 } else {
167                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Frame");
168                 }
169         } else {
170                 throw Error("access to undefined Frame " + name);
171         }
172 }
173
174 Gauge *Interpreter::GetGauge(const std::string &name) {
175         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
176         if (i != parsedDefinitions.end()) {
177                 if (i->second.type == GAUGE) {
178                         return gauges[i->second.index];
179                 } else {
180                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Gauge");
181                 }
182         } else {
183                 throw Error("access to undefined Gauge " + name);
184         }
185 }
186
187 Hero *Interpreter::GetHero(const std::string &name) {
188         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
189         if (i != parsedDefinitions.end()) {
190                 if (i->second.type == HERO) {
191                         return heroes[i->second.index];
192                 } else {
193                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Hero");
194                 }
195         } else {
196                 throw Error("access to undefined Hero " + name);
197         }
198 }
199
200 Ikari *Interpreter::GetIkari(const std::string &name) {
201         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
202         if (i != parsedDefinitions.end()) {
203                 if (i->second.type == IKARI) {
204                         return ikaris[i->second.index];
205                 } else {
206                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Ikari");
207                 }
208         } else {
209                 throw Error("access to undefined Ikari " + name);
210         }
211 }
212
213 Item *Interpreter::GetItem(const std::string &name) {
214         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
215         if (i != parsedDefinitions.end()) {
216                 if (i->second.type == ITEM) {
217                         return items[i->second.index];
218                 } else {
219                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Item");
220                 }
221         } else {
222                 throw Error("access to undefined Item " + name);
223         }
224 }
225
226 graphics::MenuProperties *Interpreter::GetMenuProperties(const std::string &name) {
227         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
228         if (i != parsedDefinitions.end()) {
229                 if (i->second.type == MENU_PROPERTIES) {
230                         return menuProperties[i->second.index];
231                 } else {
232                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to MenuProperties");
233                 }
234         } else {
235                 throw Error("access to undefined MenuProperties " + name);
236         }
237 }
238
239 Monster *Interpreter::GetMonster(const std::string &name) {
240         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
241         if (i != parsedDefinitions.end()) {
242                 if (i->second.type == MONSTER) {
243                         return monsters[i->second.index];
244                 } else {
245                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Monster");
246                 }
247         } else {
248                 throw Error("access to undefined Monster " + name);
249         }
250 }
251
252 int Interpreter::GetNumber(const std::string &name) const {
253         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
254         if (i != parsedDefinitions.end()) {
255                 if (i->second.type == NUMBER) {
256                         return numbers[i->second.index];
257                 } else {
258                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Number");
259                 }
260         } else {
261                 throw Error("access to undefined Number " + name);
262         }
263 }
264
265 PartyLayout *Interpreter::GetPartyLayout(const std::string &name) {
266         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
267         if (i != parsedDefinitions.end()) {
268                 if (i->second.type == PARTY_LAYOUT) {
269                         return partyLayouts[i->second.index];
270                 } else {
271                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to PartyLayout");
272                 }
273         } else {
274                 throw Error("access to undefined PartyLayout " + name);
275         }
276 }
277
278 const char *Interpreter::GetPath(const std::string &name) const {
279         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
280         if (i != parsedDefinitions.end()) {
281                 if (i->second.type == PATH) {
282                         return strings[i->second.index];
283                 } else {
284                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Path");
285                 }
286         } else {
287                 throw Error("access to undefined Path " + name);
288         }
289 }
290
291 Spell *Interpreter::GetSpell(const std::string &name) {
292         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
293         if (i != parsedDefinitions.end()) {
294                 if (i->second.type == SPELL) {
295                         return spells[i->second.index];
296                 } else {
297                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Spell");
298                 }
299         } else {
300                 throw Error("access to undefined Spell " + name);
301         }
302 }
303
304 Sprite *Interpreter::GetSprite(const std::string &name) {
305         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
306         if (i != parsedDefinitions.end()) {
307                 if (i->second.type == SPRITE) {
308                         return sprites[i->second.index];
309                 } else {
310                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Sprite");
311                 }
312         } else {
313                 throw Error("access to undefined Sprite " + name);
314         }
315 }
316
317 const char *Interpreter::GetString(const std::string &name) const {
318         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
319         if (i != parsedDefinitions.end()) {
320                 // TODO: enable path to string casting some time
321                 if (i->second.type == STRING /* || i->second.type == PATH */) {
322                         return strings[i->second.index];
323                 } else {
324                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to String");
325                 }
326         } else {
327                 throw Error("access to undefined String " + name);
328         }
329 }
330
331 TargetingMode *Interpreter::GetTargetingMode(const std::string &name) {
332         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
333         if (i != parsedDefinitions.end()) {
334                 if (i->second.type == TARGETING_MODE) {
335                         return targetingModes[i->second.index];
336                 } else {
337                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to TargetingMode");
338                 }
339         } else {
340                 throw Error("access to undefined TargetingMode " + name);
341         }
342 }
343
344 Vector<int> Interpreter::GetVector(const std::string &name) const {
345         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
346         if (i != parsedDefinitions.end()) {
347                 if (i->second.type == VECTOR) {
348                         return vectors[i->second.index];
349                 } else {
350                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Vector");
351                 }
352         } else {
353                 throw Error("access to undefined Vector " + name);
354         }
355 }
356
357
358 void Interpreter::ReadSource() {
359         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
360                 ReadDefinition(source.GetDefinition(*i));
361         }
362 }
363
364 void Interpreter::ReadDefinition(const Definition &dfn) {
365         if (parsedDefinitions.find(dfn.Identifier()) != parsedDefinitions.end()) {
366                 return;
367         }
368         if (dfn.HasLiteralValue()) {
369                 ReadLiteral(dfn);
370         } else {
371                 ReadObject(dfn);
372         }
373 }
374
375 void Interpreter::ReadLiteral(const Definition &dfn) {
376         switch (dfn.GetLiteral()->GetType()) {
377                 case Literal::ARRAY_VALUES:
378                         valueArrays.push_back(dfn.GetLiteral()->GetValues());
379                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VALUE_ARRAY, valueArrays.size() - 1)));
380                         break;
381                 case Literal::ARRAY_PROPS:
382                         propertyListArrays.push_back(dfn.GetLiteral()->GetPropertyLists());
383                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PROPERTY_LIST_ARRAY, propertyListArrays.size() - 1)));
384                         break;
385                 case Literal::BOOLEAN:
386                         booleans.push_back(dfn.GetLiteral()->GetBoolean());
387                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, BOOLEAN, booleans.size() - 1)));
388                         break;
389                 case Literal::COLOR:
390                         colors.push_back(Color(dfn.GetLiteral()->GetRed(), dfn.GetLiteral()->GetGreen(), dfn.GetLiteral()->GetBlue(), dfn.GetLiteral()->GetAlpha()));
391                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COLOR, colors.size() - 1)));
392                         break;
393                 case Literal::NUMBER:
394                         numbers.push_back(dfn.GetLiteral()->GetNumber());
395                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, NUMBER, numbers.size() - 1)));
396                         break;
397                 case Literal::PATH:
398                         {
399                                 char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
400                                 std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
401                                 str[dfn.GetLiteral()->GetString().size()] = '\0';
402                                 strings.push_back(str);
403                         }
404                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PATH, strings.size() - 1)));
405                         break;
406                 case Literal::STRING:
407                         {
408                                 char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
409                                 std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
410                                 str[dfn.GetLiteral()->GetString().size()] = '\0';
411                                 strings.push_back(str);
412                         }
413                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, STRING, strings.size() - 1)));
414                         break;
415                 case Literal::VECTOR:
416                         vectors.push_back(Vector<int>(dfn.GetLiteral()->GetX(), dfn.GetLiteral()->GetY()));
417                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VECTOR, vectors.size() - 1)));
418                         break;
419                 case Literal::OBJECT:
420                         ReadObject(dfn);
421                         break;
422         }
423 }
424
425 Animation *Interpreter::GetAnimation(const Value &v) {
426         if (v.IsLiteral()) {
427                 if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
428                         ComplexAnimation *a(new ComplexAnimation);
429                         ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
430                         complexAnimations.push_back(a);
431                         return a;
432                 } else {
433                         SimpleAnimation *a(new SimpleAnimation);
434                         ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
435                         simpleAnimations.push_back(a);
436                         return a;
437                 }
438         } else {
439                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
440                 return GetAnimation(v.GetIdentifier());
441         }
442 }
443
444 bool Interpreter::GetBoolean(const Value &v) {
445         if (v.IsLiteral()) {
446                 return v.GetLiteral().GetBoolean();
447         } else {
448                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
449                 return GetBoolean(v.GetIdentifier());
450         }
451 }
452
453 Color Interpreter::GetColor(const Value &v) {
454         if (v.IsLiteral()) {
455                 return Color(v.GetLiteral().GetRed(), v.GetLiteral().GetGreen(), v.GetLiteral().GetBlue(), v.GetLiteral().GetAlpha());
456         } else {
457                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
458                 return GetColor(v.GetIdentifier());
459         }
460 }
461
462 Font *Interpreter::GetFont(const Value &v) {
463         if (v.IsLiteral()) {
464                 Font *f(new Font);
465                 ReadFont(*f, *v.GetLiteral().GetProperties());
466                 return f;
467         } else {
468                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
469                 return GetFont(v.GetIdentifier());
470         }
471 }
472
473 Frame *Interpreter::GetFrame(const Value &v) {
474         if (v.IsLiteral()) {
475                 Frame *f(new Frame);
476                 ReadFrame(*f, *v.GetLiteral().GetProperties());
477                 return f;
478         } else {
479                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
480                 return GetFrame(v.GetIdentifier());
481         }
482 }
483
484 Gauge *Interpreter::GetGauge(const Value &v) {
485         if (v.IsLiteral()) {
486                 Gauge *g(new Gauge);
487                 ReadGauge(*g, *v.GetLiteral().GetProperties());
488                 return g;
489         } else {
490                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
491                 return GetGauge(v.GetIdentifier());
492         }
493 }
494
495 Hero *Interpreter::GetHero(const Value &v) {
496         if (v.IsLiteral()) {
497                 Hero *h(new Hero);
498                 ReadHero(*h, *v.GetLiteral().GetProperties());
499                 return h;
500         } else {
501                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
502                 return GetHero(v.GetIdentifier());
503         }
504 }
505
506 Ikari *Interpreter::GetIkari(const Value &v) {
507         if (v.IsLiteral()) {
508                 Ikari *i(new Ikari);
509                 ReadIkari(*i, *v.GetLiteral().GetProperties());
510                 return i;
511         } else {
512                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
513                 return GetIkari(v.GetIdentifier());
514         }
515 }
516
517 SDL_Surface *Interpreter::GetImage(const Value &v) {
518         string path(GetPath(v));
519         map<string, SDL_Surface *>::const_iterator i(imageCache.find(path));
520         if (i == imageCache.end()) {
521                 SDL_Surface *image(IMG_Load(path.c_str()));
522                 images.push_back(image);
523                 imageCache.insert(make_pair(path, image));
524                 return image;
525         } else {
526                 return i->second;
527         }
528 }
529
530 Item *Interpreter::GetItem(const Value &v) {
531         if (v.IsLiteral()) {
532                 Item *i(new Item);
533                 ReadItem(*i, *v.GetLiteral().GetProperties());
534                 return i;
535         } else {
536                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
537                 return GetItem(v.GetIdentifier());
538         }
539 }
540
541 graphics::MenuProperties *Interpreter::GetMenuProperties(const Value &v) {
542         if (v.IsLiteral()) {
543                 graphics::MenuProperties *m(new graphics::MenuProperties);
544                 ReadMenuProperties(*m, *v.GetLiteral().GetProperties());
545                 return m;
546         } else {
547                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
548                 return GetMenuProperties(v.GetIdentifier());
549         }
550 }
551
552 Monster *Interpreter::GetMonster(const Value &v) {
553         if (v.IsLiteral()) {
554                 Monster *m(new Monster);
555                 ReadMonster(*m, *v.GetLiteral().GetProperties());
556                 return m;
557         } else {
558                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
559                 return GetMonster(v.GetIdentifier());
560         }
561 }
562
563 int Interpreter::GetNumber(const Value &v) {
564         if (v.IsLiteral()) {
565                 return v.GetLiteral().GetNumber();
566         } else {
567                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
568                 return GetNumber(v.GetIdentifier());
569         }
570 }
571
572 PartyLayout *Interpreter::GetPartyLayout(const Value &v) {
573         if (v.IsLiteral()) {
574                 PartyLayout *l(new PartyLayout);
575                 ReadPartyLayout(*l, *v.GetLiteral().GetProperties());
576                 return l;
577         } else {
578                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
579                 return GetPartyLayout(v.GetIdentifier());
580         }
581 }
582
583 const char *Interpreter::GetPath(const Value &v) {
584         if (v.IsLiteral()) {
585                 return v.GetLiteral().GetString().c_str();
586         } else {
587                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
588                 return GetPath(v.GetIdentifier());
589         }
590 }
591
592 const PropertyList *Interpreter::GetPropertyList(const Value &v) {
593         if (v.IsLiteral()) {
594                 return v.GetLiteral().GetProperties();
595         } else {
596                 throw Error("cannot reference property lists");
597         }
598 }
599
600 const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
601         if (v.IsLiteral()) {
602                 return v.GetLiteral().GetPropertyLists();
603         } else {
604                 throw Error("cannot reference property list arrays");
605         }
606 }
607
608 Spell *Interpreter::GetSpell(const Value &v) {
609         if (v.IsLiteral()) {
610                 Spell *s(new Spell);
611                 ReadSpell(*s, *v.GetLiteral().GetProperties());
612                 return s;
613         } else {
614                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
615                 return GetSpell(v.GetIdentifier());
616         }
617 }
618
619 Sprite *Interpreter::GetSprite(const Value &v) {
620         if (v.IsLiteral()) {
621                 Sprite *s(new Sprite);
622                 ReadSprite(*s, *v.GetLiteral().GetProperties());
623                 return s;
624         } else {
625                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
626                 return GetSprite(v.GetIdentifier());
627         }
628 }
629
630 const char *Interpreter::GetString(const Value &v) {
631         if (v.IsLiteral()) {
632                 return v.GetLiteral().GetString().c_str();
633         } else {
634                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
635                 return GetString(v.GetIdentifier());
636         }
637 }
638
639 TargetingMode *Interpreter::GetTargetingMode(const Value &v) {
640         if (v.IsLiteral()) {
641                 TargetingMode *t(new TargetingMode);
642                 ReadTargetingMode(*t, *v.GetLiteral().GetProperties());
643                 return t;
644         } else {
645                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
646                 return GetTargetingMode(v.GetIdentifier());
647         }
648 }
649
650 Vector<int> Interpreter::GetVector(const Value &v) {
651         if (v.IsLiteral()) {
652                 return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
653         } else {
654                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
655                 return GetVector(v.GetIdentifier());
656         }
657 }
658
659 const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
660         if (v.IsLiteral()) {
661                 return v.GetLiteral().GetValues();
662         } else {
663                 throw Error("cannot reference value arrays");
664         }
665 }
666
667
668 void Interpreter::ReadObject(const Definition &dfn) {
669         if (dfn.TypeName() == "ComplexAnimation") {
670                 ComplexAnimation *animation(new ComplexAnimation);
671                 int index(complexAnimations.size());
672                 complexAnimations.push_back(animation);
673                 ReadComplexAnimation(*animation, *dfn.GetProperties());
674                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COMPLEX_ANIMATION, index)));
675         } else if (dfn.TypeName() == "Font") {
676                 Font *font(new Font);
677                 int index(fonts.size());
678                 fonts.push_back(font);
679                 ReadFont(*font, *dfn.GetProperties());
680                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FONT, index)));
681         } else if (dfn.TypeName() == "Frame") {
682                 Frame *frame(new Frame);
683                 int index(frames.size());
684                 frames.push_back(frame);
685                 ReadFrame(*frame, *dfn.GetProperties());
686                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FRAME, index)));
687         } else if (dfn.TypeName() == "Gauge") {
688                 Gauge *gauge(new Gauge);
689                 int index(gauges.size());
690                 gauges.push_back(gauge);
691                 ReadGauge(*gauge, *dfn.GetProperties());
692                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, GAUGE, index)));
693         } else if (dfn.TypeName() == "Hero") {
694                 Hero *hero(new Hero);
695                 int index(heroes.size());
696                 heroes.push_back(hero);
697                 ReadHero(*hero, *dfn.GetProperties());
698                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, HERO, index)));
699         } else if (dfn.TypeName() == "Ikari") {
700                 Ikari *ikari(new Ikari);
701                 int index(ikaris.size());
702                 ikaris.push_back(ikari);
703                 ReadIkari(*ikari, *dfn.GetProperties());
704                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, IKARI, index)));
705         } else if (dfn.TypeName() == "Item") {
706                 Item *item(new Item);
707                 int index(items.size());
708                 items.push_back(item);
709                 ReadItem(*item, *dfn.GetProperties());
710                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, ITEM, index)));
711         } else if (dfn.TypeName() == "MenuProperties") {
712                 graphics::MenuProperties *mprops(new graphics::MenuProperties);
713                 int index(menuProperties.size());
714                 menuProperties.push_back(mprops);
715                 ReadMenuProperties(*mprops, *dfn.GetProperties());
716                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MENU_PROPERTIES, index)));
717         } else if (dfn.TypeName() == "Monster") {
718                 Monster *monster(new Monster);
719                 int index(monsters.size());
720                 monsters.push_back(monster);
721                 ReadMonster(*monster, *dfn.GetProperties());
722                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MONSTER, index)));
723         } else if (dfn.TypeName() == "PartyLayout") {
724                 PartyLayout *layout(new PartyLayout);
725                 int index(partyLayouts.size());
726                 partyLayouts.push_back(layout);
727                 ReadPartyLayout(*layout, *dfn.GetProperties());
728                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PARTY_LAYOUT, index)));
729         } else if (dfn.TypeName() == "SimpleAnimation") {
730                 SimpleAnimation *animation(new SimpleAnimation);
731                 int index(simpleAnimations.size());
732                 simpleAnimations.push_back(animation);
733                 ReadSimpleAnimation(*animation, *dfn.GetProperties());
734                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SIMPLE_ANIMATION, index)));
735         } else if (dfn.TypeName() == "Spell") {
736                 Spell *spell(new Spell);
737                 int index(spells.size());
738                 spells.push_back(spell);
739                 ReadSpell(*spell, *dfn.GetProperties());
740                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPELL, index)));
741         } else if (dfn.TypeName() == "Sprite") {
742                 Sprite *sprite(new Sprite);
743                 int index(sprites.size());
744                 sprites.push_back(sprite);
745                 ReadSprite(*sprite, *dfn.GetProperties());
746                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPRITE, index)));
747         } else if (dfn.TypeName() == "TargetingMode") {
748                 TargetingMode *mode(new TargetingMode);
749                 int index(targetingModes.size());
750                 targetingModes.push_back(mode);
751                 ReadTargetingMode(*mode, *dfn.GetProperties());
752                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, TARGETING_MODE, index)));
753         } else {
754                 throw Error("unhandled object type: " + dfn.TypeName());
755         }
756 }
757
758
759 void Interpreter::ReadComplexAnimation(ComplexAnimation &a, const PropertyList &props) {
760         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
761                 if (i->first == "sprite") {
762                         a.SetSprite(GetSprite(*i->second));
763                 } else if (i->first == "frametime") {
764                         a.SetFrameTime(GetNumber(*i->second));
765                 } else if (i->first == "repeat") {
766                         a.SetRepeat(GetBoolean(*i->second));
767                 } else if (i->first == "frames") {
768                         const vector<PropertyList *> &values(GetPropertyListArray(*i->second));
769                         for (vector<PropertyList *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
770                                 ComplexAnimation::FrameProp frame;
771                                 ReadComplexAnimationFrame(frame, **i);
772                                 a.AddFrame(frame);
773                         }
774                 } else {
775                         throw Error("unknown ComplexAnimation property: " + i->first);
776                 }
777         }
778 }
779
780 void Interpreter::ReadComplexAnimationFrame(ComplexAnimation::FrameProp &f, const PropertyList &props) {
781         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
782                 if (i->first == "column") {
783                         f.col = GetNumber(*i->second);
784                 } else if (i->first == "row") {
785                         f.row = GetNumber(*i->second);
786                 } else if (i->first == "disposition") {
787                         f.disposition = GetVector(*i->second);
788                 } else {
789                         throw Error("unknown ComplexAnimationFrame property: " + i->first);
790                 }
791         }
792 }
793
794 void Interpreter::ReadFont(Font &f, const PropertyList &props) {
795         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
796                 if (i->first == "sprite") {
797                         f.SetSprite(GetSprite(*i->second));
798                 } else if (i->first == "columnoffset") {
799                         f.SetColOffset(GetNumber(*i->second));
800                 } else if (i->first == "rowoffset") {
801                         f.SetRowOffset(GetNumber(*i->second));
802                 } else {
803                         throw Error("unknown Font property: " + i->first);
804                 }
805         }
806 }
807
808 void Interpreter::ReadFrame(Frame &f, const PropertyList &props) {
809         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
810                 if (i->first == "image") {
811                         f.SetSurface(GetImage(*i->second));
812                 } else if (i->first == "border") {
813                         f.SetBorderSize(GetVector(*i->second));
814                 } else if (i->first == "repeat") {
815                         f.SetRepeatSize(GetVector(*i->second));
816                 } else if (i->first == "offset") {
817                         f.SetOffset(GetVector(*i->second));
818                 } else {
819                         throw Error("unknown Frame property: " + i->first);
820                 }
821         }
822 }
823
824 void Interpreter::ReadGauge(Gauge &g, const PropertyList &props) {
825         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
826                 if (i->first == "image") {
827                         g.SetSurface(GetImage(*i->second));
828                 } else if (i->first == "full") {
829                         g.SetFullOffset(GetVector(*i->second));
830                 } else if (i->first == "empty") {
831                         g.SetEmptyOffset(GetVector(*i->second));
832                 } else if (i->first == "height") {
833                         g.SetHeight(GetNumber(*i->second));
834                 } else if (i->first == "start") {
835                         g.SetStartWidth(GetNumber(*i->second));
836                 } else if (i->first == "repeat") {
837                         g.SetRepeatWidth(GetNumber(*i->second));
838                 } else if (i->first == "end") {
839                         g.SetEndWidth(GetNumber(*i->second));
840                 } else {
841                         throw Error("unknown Gauge property: " + i->first);
842                 }
843         }
844 }
845
846 void Interpreter::ReadIkari(Ikari &ikari, const PropertyList &props) {
847         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
848                 if (i->first == "name") {
849                         ikari.SetName(GetString(*i->second));
850                 } else if (i->first == "cost") {
851                         ikari.SetCost(GetNumber(*i->second));
852                 } else if (i->first == "targets") {
853                         ikari.GetTargetingMode() = *GetTargetingMode(*i->second);
854                 } else if (i->first == "magical") {
855                         if (GetBoolean(*i->second)) {
856                                 ikari.SetMagical();
857                         }
858                 } else if (i->first == "physical") {
859                         if (GetBoolean(*i->second)) {
860                                 ikari.SetPhysical();
861                         }
862                 } else {
863                         throw Error("unknown Ikari property: " + i->first);
864                 }
865         }
866 }
867
868 void Interpreter::ReadItem(Item &item, const PropertyList &props) {
869         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
870                 if (i->first == "name") {
871                         item.SetName(GetString(*i->second));
872                 } else if (i->first == "menuicon") {
873                         item.SetMenuIcon(GetSprite(*i->second));
874                 } else if (i->first == "battle") {
875                         if (GetBoolean(*i->second)) {
876                                 item.SetUsableInBattle();
877                         }
878                 } else if (i->first == "targets") {
879                         item.GetTargetingMode() = *GetTargetingMode(*i->second);
880                 } else if (i->first == "ikari") {
881                         item.SetIkari(GetIkari(*i->second));
882                 } else if (i->first == "attackanimation") {
883                         item.SetAttackAnimation(GetAnimation(*i->second));
884                 } else {
885                         throw Error("unknown Item property: " + i->first);
886                 }
887         }
888 }
889
890 void Interpreter::ReadHero(Hero &h, const PropertyList &props) {
891         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
892                 if (i->first == "name") {
893                         h.SetName(GetString(*i->second));
894                 } else if (i->first == "sprite") {
895                         h.SetSprite(GetSprite(*i->second));
896                 } else if (i->first == "level") {
897                         h.SetLevel(GetNumber(*i->second));
898                 } else if (i->first == "maxHealth") {
899                         h.SetMaxHealth(GetNumber(*i->second));
900                 } else if (i->first == "health") {
901                         h.SetHealth(GetNumber(*i->second));
902                 } else if (i->first == "maxMana") {
903                         h.SetMaxMana(GetNumber(*i->second));
904                 } else if (i->first == "mana") {
905                         h.SetMana(GetNumber(*i->second));
906                 } else if (i->first == "ip") {
907                         h.SetIP(GetNumber(*i->second));
908                 } else if (i->first == "stats") {
909                         battle::Stats stats;
910                         ReadStats(stats, *GetPropertyList(*i->second));
911                         h.SetStats(stats);
912                 } else if (i->first == "attackAnimation") {
913                         h.SetAttackAnimation(GetAnimation(*i->second));
914                 } else if (i->first == "spellAnimation") {
915                         h.SetSpellAnimation(GetAnimation(*i->second));
916                 } else if (i->first == "meleeAnimation") {
917                         h.SetMeleeAnimation(GetAnimation(*i->second));
918                 } else {
919                         throw Error("unknown Hero property: " + i->first);
920                 }
921         }
922 }
923
924 void Interpreter::ReadMenuProperties(graphics::MenuProperties &mprops, const PropertyList &props) {
925         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
926                 if (i->first == "font") {
927                         mprops.font = GetFont(*i->second);
928                 } else if (i->first == "disabledFont") {
929                         mprops.disabledFont = GetFont(*i->second);
930                 } else if (i->first == "cursor") {
931                         mprops.cursor = GetSprite(*i->second);
932                 } else if (i->first == "charsPerEntry") {
933                         mprops.charsPerEntry = GetNumber(*i->second);
934                 } else if (i->first == "rows") {
935                         mprops.rows = GetNumber(*i->second);
936                 } else if (i->first == "rowGap") {
937                         mprops.rowGap = GetNumber(*i->second);
938                 } else if (i->first == "iconSpace") {
939                         mprops.iconSpace = GetNumber(*i->second);
940                 } else if (i->first == "cols") {
941                         mprops.cols = GetNumber(*i->second);
942                 } else if (i->first == "colGap") {
943                         mprops.colGap = GetNumber(*i->second);
944                 } else if (i->first == "delimiter") {
945                         mprops.delimiter = *GetString(*i->second);
946                 } else if (i->first == "charsPerNumber") {
947                         mprops.charsPerNumber = GetNumber(*i->second);
948                 } else if (i->first == "charsPerAdditionalText") {
949                         mprops.charsPerAdditionalText = GetNumber(*i->second);
950                 } else if (i->first == "additionalTextGap") {
951                         mprops.additionalTextGap = GetNumber(*i->second);
952                 } else {
953                         throw Error("unknown MenuProperties property: " + i->first);
954                 }
955         }
956 }
957
958 void Interpreter::ReadMonster(Monster &m, const PropertyList &props) {
959         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
960                 if (i->first == "name") {
961                         m.SetName(GetString(*i->second));
962                 } else if (i->first == "sprite") {
963                         m.SetSprite(GetSprite(*i->second));
964                 } else if (i->first == "level") {
965                         m.SetLevel(GetNumber(*i->second));
966                 } else if (i->first == "maxHealth") {
967                         m.SetMaxHealth(GetNumber(*i->second));
968                 } else if (i->first == "health") {
969                         m.SetHealth(GetNumber(*i->second));
970                 } else if (i->first == "maxMana") {
971                         m.SetMaxMana(GetNumber(*i->second));
972                 } else if (i->first == "mana") {
973                         m.SetMana(GetNumber(*i->second));
974                 } else if (i->first == "stats") {
975                         battle::Stats stats;
976                         ReadStats(stats, *GetPropertyList(*i->second));
977                         m.SetStats(stats);
978                 } else if (i->first == "attackAnimation") {
979                         m.SetAttackAnimation(GetAnimation(*i->second));
980                 } else if (i->first == "meleeAnimation") {
981                         m.SetMeleeAnimation(GetAnimation(*i->second));
982                 } else {
983                         throw Error("unknown Monster property: " + i->first);
984                 }
985         }
986 }
987
988 void Interpreter::ReadPartyLayout(PartyLayout &p, const PropertyList &props) {
989         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
990                 if (i->first == "positions") {
991                         const vector<Value *> &positions(GetValueArray(*i->second));
992                         for (vector<Value *>::const_iterator j(positions.begin()), end(positions.end()); j != end; ++j) {
993                                 p.AddPosition(GetVector(**j));
994                         }
995                 } else {
996                         throw Error("unknown PartyLayout property: " + i->first);
997                 }
998         }
999 }
1000
1001 void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) {
1002         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
1003                 if (i->first == "sprite") {
1004                         a.SetSprite(GetSprite(*i->second));
1005                 } else if (i->first == "frametime") {
1006                         a.SetFrameTime(GetNumber(*i->second));
1007                 } else if (i->first == "repeat") {
1008                         a.SetRepeat(GetBoolean(*i->second));
1009                 } else if (i->first == "framecount") {
1010                         a.SetNumFrames(GetNumber(*i->second));
1011                 } else if (i->first == "col") {
1012                         a.SetCol(GetNumber(*i->second));
1013                 } else if (i->first == "row") {
1014                         a.SetRow(GetNumber(*i->second));
1015                 } else {
1016                         throw Error("unknown SimpleAnimation property: " + i->first);
1017                 }
1018         }
1019 }
1020
1021 void Interpreter::ReadSpell(Spell &s, const PropertyList &props) {
1022         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
1023                 if (i->first == "name") {
1024                         s.SetName(GetString(*i->second));
1025                 } else if (i->first == "cost") {
1026                         s.SetCost(GetNumber(*i->second));
1027                 } else if (i->first == "battle") {
1028                         if (GetBoolean(*i->second)) {
1029                                 s.SetUsableInBattle();
1030                         }
1031                 } else if (i->first == "targets") {
1032                         s.GetTargetingMode() = *GetTargetingMode(*i->second);
1033                 } else {
1034                         throw Error("unknown Spell property: " + i->first);
1035                 }
1036         }
1037 }
1038
1039 void Interpreter::ReadSprite(Sprite &s, const PropertyList &props) {
1040         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
1041                 if (i->first == "image") {
1042                         s.SetSurface(GetImage(*i->second));
1043                 } else if (i->first == "size") {
1044                         s.SetSize(GetVector(*i->second));
1045                 } else if (i->first == "offset") {
1046                         s.SetOffset(GetVector(*i->second));
1047                 } else {
1048                         throw Error("unknown Sprite property: " + i->first);
1049                 }
1050         }
1051 }
1052
1053 void Interpreter::ReadStats(Stats &s, const PropertyList &props) {
1054         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
1055                 if (i->first == "atp") {
1056                         s.SetAttack(GetNumber(*i->second));
1057                 } else if (i->first == "dfp") {
1058                         s.SetDefense(GetNumber(*i->second));
1059                 } else if (i->first == "str") {
1060                         s.SetStrength(GetNumber(*i->second));
1061                 } else if (i->first == "agl") {
1062                         s.SetAgility(GetNumber(*i->second));
1063                 } else if (i->first == "int") {
1064                         s.SetIntelligence(GetNumber(*i->second));
1065                 } else if (i->first == "gut") {
1066                         s.SetGut(GetNumber(*i->second));
1067                 } else if (i->first == "mgr") {
1068                         s.SetMagicResistance(GetNumber(*i->second));
1069                 } else {
1070                         throw Error("unknown Stats property: " + i->first);
1071                 }
1072         }
1073 }
1074
1075 void Interpreter::ReadTargetingMode(TargetingMode &t, const PropertyList &props) {
1076         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
1077                 if (i->first == "ally") {
1078                         if (GetBoolean(*i->second)) {
1079                                 t.TargetAlly();
1080                         } else {
1081                                 t.TargetEnemy();
1082                         }
1083                 } else if (i->first == "enemy") {
1084                         if (GetBoolean(*i->second)) {
1085                                 t.TargetEnemy();
1086                         } else {
1087                                 t.TargetAlly();
1088                         }
1089                 } else if (i->first == "all") {
1090                         if (GetBoolean(*i->second)) {
1091                                 t.TargetAll();
1092                         }
1093                 } else if (i->first == "multiple") {
1094                         if (GetBoolean(*i->second)) {
1095                                 t.TargetMultiple();
1096                         }
1097                 } else if (i->first == "single") {
1098                         if (GetBoolean(*i->second)) {
1099                                 t.TargetSingle();
1100                         }
1101                 } else {
1102                         throw Error("unknown TargetingMode property: " + i->first);
1103                 }
1104         }
1105 }
1106
1107 }