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