]> git.localhorst.tv Git - l2e.git/blob - src/loader/Interpreter.cpp
d5a61a669a9bd177c023325cfec12031664395d1
[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 "../graphics/ComplexAnimation.h"
15 #include "../graphics/Font.h"
16 #include "../graphics/Frame.h"
17 #include "../graphics/SimpleAnimation.h"
18 #include "../graphics/Sprite.h"
19
20 #include <algorithm>
21 #include <cstring>
22 #include <SDL_image.h>
23
24 using battle::Hero;
25 using battle::Monster;
26 using battle::PartyLayout;
27 using battle::Stats;
28 using graphics::Animation;
29 using graphics::Font;
30 using graphics::Frame;
31 using graphics::ComplexAnimation;
32 using graphics::SimpleAnimation;
33 using graphics::Sprite;
34 using geometry::Vector;
35 using std::make_pair;
36 using std::map;
37 using std::set;
38 using std::string;
39 using std::vector;
40
41 namespace loader {
42
43 Interpreter::~Interpreter() {
44         for (vector<ComplexAnimation *>::const_iterator i(complexAnimations.begin()), end(complexAnimations.end()); i != end; ++i) {
45                 delete *i;
46         }
47         for (vector<Hero *>::const_iterator i(heroes.begin()), end(heroes.end()); i != end; ++i) {
48                 delete *i;
49         }
50         for (vector<Font *>::const_iterator i(fonts.begin()), end(fonts.end()); i != end; ++i) {
51                 delete *i;
52         }
53         for (vector<Frame *>::const_iterator i(frames.begin()), end(frames.end()); i != end; ++i) {
54                 delete *i;
55         }
56         for (vector<SDL_Surface *>::const_iterator i(images.begin()), end(images.end()); i != end; ++i) {
57                 SDL_FreeSurface(*i);
58         }
59         for (vector<Monster *>::const_iterator i(monsters.begin()), end(monsters.end()); i != end; ++i) {
60                 delete *i;
61         }
62         for (vector<PartyLayout *>::const_iterator i(partyLayouts.begin()), end(partyLayouts.end()); i != end; ++i) {
63                 delete *i;
64         }
65         for (vector<SimpleAnimation *>::const_iterator i(simpleAnimations.begin()), end(simpleAnimations.end()); i != end; ++i) {
66                 delete *i;
67         }
68         for (vector<Sprite *>::const_iterator i(sprites.begin()), end(sprites.end()); i != end; ++i) {
69                 delete *i;
70         }
71         for (vector<const char *>::const_iterator i(strings.begin()), end(strings.end()); i != end; ++i) {
72                 delete *i;
73         }
74 }
75
76
77 Animation *Interpreter::GetAnimation(const std::string &name) {
78         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
79         if (i != parsedDefinitions.end()) {
80                 if (i->second.type == COMPLEX_ANIMATION) {
81                         return complexAnimations[i->second.index];
82                 } else if (i->second.type == SIMPLE_ANIMATION) {
83                         return simpleAnimations[i->second.index];
84                 } else {
85                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Animation");
86                 }
87         } else {
88                 throw Error("access to undefined Animation " + name);
89         }
90 }
91
92 bool Interpreter::GetBoolean(const std::string &name) const {
93         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
94         if (i != parsedDefinitions.end()) {
95                 if (i->second.type == BOOLEAN) {
96                         return booleans[i->second.index];
97                 } else {
98                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Boolean");
99                 }
100         } else {
101                 throw Error("access to undefined Boolean " + name);
102         }
103 }
104
105 Font *Interpreter::GetFont(const std::string &name) {
106         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
107         if (i != parsedDefinitions.end()) {
108                 if (i->second.type == FONT) {
109                         return fonts[i->second.index];
110                 } else {
111                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Font");
112                 }
113         } else {
114                 throw Error("access to undefined Font " + name);
115         }
116 }
117
118 Frame *Interpreter::GetFrame(const std::string &name) {
119         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
120         if (i != parsedDefinitions.end()) {
121                 if (i->second.type == FRAME) {
122                         return frames[i->second.index];
123                 } else {
124                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Frame");
125                 }
126         } else {
127                 throw Error("access to undefined Frame " + name);
128         }
129 }
130
131 Hero *Interpreter::GetHero(const std::string &name) {
132         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
133         if (i != parsedDefinitions.end()) {
134                 if (i->second.type == HERO) {
135                         return heroes[i->second.index];
136                 } else {
137                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Hero");
138                 }
139         } else {
140                 throw Error("access to undefined Hero " + name);
141         }
142 }
143
144 Monster *Interpreter::GetMonster(const std::string &name) {
145         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
146         if (i != parsedDefinitions.end()) {
147                 if (i->second.type == MONSTER) {
148                         return monsters[i->second.index];
149                 } else {
150                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Monster");
151                 }
152         } else {
153                 throw Error("access to undefined Monster " + name);
154         }
155 }
156
157 int Interpreter::GetNumber(const std::string &name) const {
158         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
159         if (i != parsedDefinitions.end()) {
160                 if (i->second.type == NUMBER) {
161                         return numbers[i->second.index];
162                 } else {
163                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Number");
164                 }
165         } else {
166                 throw Error("access to undefined Number " + name);
167         }
168 }
169
170 PartyLayout *Interpreter::GetPartyLayout(const std::string &name) {
171         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
172         if (i != parsedDefinitions.end()) {
173                 if (i->second.type == PARTY_LAYOUT) {
174                         return partyLayouts[i->second.index];
175                 } else {
176                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to PartyLayout");
177                 }
178         } else {
179                 throw Error("access to undefined PartyLayout " + name);
180         }
181 }
182
183 Sprite *Interpreter::GetSprite(const std::string &name) {
184         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
185         if (i != parsedDefinitions.end()) {
186                 if (i->second.type == SPRITE) {
187                         return sprites[i->second.index];
188                 } else {
189                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Sprite");
190                 }
191         } else {
192                 throw Error("access to undefined Sprite " + name);
193         }
194 }
195
196 const char *Interpreter::GetString(const std::string &name) const {
197         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
198         if (i != parsedDefinitions.end()) {
199                 if (i->second.type == STRING) {
200                         return strings[i->second.index];
201                 } else {
202                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to String");
203                 }
204         } else {
205                 throw Error("access to undefined String " + name);
206         }
207 }
208
209 Vector<int> Interpreter::GetVector(const std::string &name) const {
210         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
211         if (i != parsedDefinitions.end()) {
212                 if (i->second.type == VECTOR) {
213                         return vectors[i->second.index];
214                 } else {
215                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Vector");
216                 }
217         } else {
218                 throw Error("access to undefined Vector " + name);
219         }
220 }
221
222
223 void Interpreter::ReadSource() {
224         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
225                 ReadDefinition(source.GetDefinition(*i));
226         }
227 }
228
229 void Interpreter::ReadDefinition(const Definition &dfn) {
230         if (parsedDefinitions.find(dfn.Identifier()) != parsedDefinitions.end()) {
231                 return;
232         }
233         if (dfn.HasLiteralValue()) {
234                 ReadLiteral(dfn);
235         } else {
236                 ReadObject(dfn);
237         }
238 }
239
240 void Interpreter::ReadLiteral(const Definition &dfn) {
241         switch (dfn.GetLiteral()->GetType()) {
242                 case Literal::ARRAY_VALUES:
243                         valueArrays.push_back(dfn.GetLiteral()->GetValues());
244                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VALUE_ARRAY, valueArrays.size() - 1)));
245                         break;
246                 case Literal::ARRAY_PROPS:
247                         propertyListArrays.push_back(dfn.GetLiteral()->GetPropertyLists());
248                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PROPERTY_LIST_ARRAY, propertyListArrays.size() - 1)));
249                         break;
250                 case Literal::BOOLEAN:
251                         booleans.push_back(dfn.GetLiteral()->GetBoolean());
252                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, BOOLEAN, booleans.size() - 1)));
253                         break;
254                 case Literal::COLOR:
255                         throw Error("unhandled literal: color");
256                         break;
257                 case Literal::NUMBER:
258                         numbers.push_back(dfn.GetLiteral()->GetNumber());
259                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, NUMBER, numbers.size() - 1)));
260                         break;
261                 case Literal::STRING:
262                         {
263                                 char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
264                                 std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
265                                 str[dfn.GetLiteral()->GetString().size()] = '\0';
266                                 strings.push_back(str);
267                         }
268                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, STRING, strings.size() - 1)));
269                         break;
270                 case Literal::VECTOR:
271                         vectors.push_back(Vector<int>(dfn.GetLiteral()->GetX(), dfn.GetLiteral()->GetY()));
272                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VECTOR, vectors.size() - 1)));
273                         break;
274                 case Literal::OBJECT:
275                         ReadObject(dfn);
276                         break;
277         }
278 }
279
280 Animation *Interpreter::GetAnimation(const Value &v) {
281         if (v.IsLiteral()) {
282                 if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
283                         ComplexAnimation *a(new ComplexAnimation);
284                         ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
285                         complexAnimations.push_back(a);
286                         return a;
287                 } else {
288                         SimpleAnimation *a(new SimpleAnimation);
289                         ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
290                         simpleAnimations.push_back(a);
291                         return a;
292                 }
293         } else {
294                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
295                 return GetAnimation(v.GetIdentifier());
296         }
297 }
298
299 bool Interpreter::GetBoolean(const Value &v) {
300         if (v.IsLiteral()) {
301                 return v.GetLiteral().GetBoolean();
302         } else {
303                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
304                 return GetBoolean(v.GetIdentifier());
305         }
306 }
307
308 Font *Interpreter::GetFont(const Value &v) {
309         if (v.IsLiteral()) {
310                 Font *f(new Font);
311                 ReadFont(*f, *v.GetLiteral().GetProperties());
312                 return f;
313         } else {
314                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
315                 return GetFont(v.GetIdentifier());
316         }
317 }
318
319 Frame *Interpreter::GetFrame(const Value &v) {
320         if (v.IsLiteral()) {
321                 Frame *f(new Frame);
322                 ReadFrame(*f, *v.GetLiteral().GetProperties());
323                 return f;
324         } else {
325                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
326                 return GetFrame(v.GetIdentifier());
327         }
328 }
329
330 SDL_Surface *Interpreter::GetImage(const Value &v) {
331         const char *file(GetString(v));
332         SDL_Surface *image(IMG_Load(file));
333         images.push_back(image);
334         return image;
335 }
336
337 int Interpreter::GetNumber(const Value &v) {
338         if (v.IsLiteral()) {
339                 return v.GetLiteral().GetNumber();
340         } else {
341                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
342                 return GetNumber(v.GetIdentifier());
343         }
344 }
345
346 PartyLayout *Interpreter::GetPartyLayout(const Value &v) {
347         if (v.IsLiteral()) {
348                 PartyLayout *l(new PartyLayout);
349                 ReadPartyLayout(*l, *v.GetLiteral().GetProperties());
350                 return l;
351         } else {
352                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
353                 return GetPartyLayout(v.GetIdentifier());
354         }
355 }
356
357 const PropertyList *Interpreter::GetPropertyList(const Value &v) {
358         if (v.IsLiteral()) {
359                 return v.GetLiteral().GetProperties();
360         } else {
361                 throw Error("cannot reference property lists");
362         }
363 }
364
365 const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
366         if (v.IsLiteral()) {
367                 return v.GetLiteral().GetPropertyLists();
368         } else {
369                 throw Error("cannot reference property list arrays");
370         }
371 }
372
373 Sprite *Interpreter::GetSprite(const Value &v) {
374         if (v.IsLiteral()) {
375                 Sprite *s(new Sprite);
376                 ReadSprite(*s, *v.GetLiteral().GetProperties());
377                 return s;
378         } else {
379                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
380                 return GetSprite(v.GetIdentifier());
381         }
382 }
383
384 const char *Interpreter::GetString(const Value &v) {
385         if (v.IsLiteral()) {
386                 return v.GetLiteral().GetString().c_str();
387         } else {
388                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
389                 return GetString(v.GetIdentifier());
390         }
391 }
392
393 Vector<int> Interpreter::GetVector(const Value &v) {
394         if (v.IsLiteral()) {
395                 return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
396         } else {
397                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
398                 return GetVector(v.GetIdentifier());
399         }
400 }
401
402 const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
403         if (v.IsLiteral()) {
404                 return v.GetLiteral().GetValues();
405         } else {
406                 throw Error("cannot reference value arrays");
407         }
408 }
409
410
411 void Interpreter::ReadObject(const Definition &dfn) {
412         if (dfn.TypeName() == "ComplexAnimation") {
413                 ComplexAnimation *animation(new ComplexAnimation);
414                 int index(complexAnimations.size());
415                 complexAnimations.push_back(animation);
416                 ReadComplexAnimation(*animation, *dfn.GetProperties());
417                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COMPLEX_ANIMATION, index)));
418         } else if (dfn.TypeName() == "Font") {
419                 Font *font(new Font);
420                 int index(fonts.size());
421                 fonts.push_back(font);
422                 ReadFont(*font, *dfn.GetProperties());
423                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FONT, index)));
424         } else if (dfn.TypeName() == "Frame") {
425                 Frame *frame(new Frame);
426                 int index(frames.size());
427                 frames.push_back(frame);
428                 ReadFrame(*frame, *dfn.GetProperties());
429                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FRAME, index)));
430         } else if (dfn.TypeName() == "Hero") {
431                 Hero *hero(new Hero);
432                 int index(heroes.size());
433                 heroes.push_back(hero);
434                 ReadHero(*hero, *dfn.GetProperties());
435                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, HERO, index)));
436         } else if (dfn.TypeName() == "Monster") {
437                 Monster *monster(new Monster);
438                 int index(monsters.size());
439                 monsters.push_back(monster);
440                 ReadMonster(*monster, *dfn.GetProperties());
441                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MONSTER, index)));
442         } else if (dfn.TypeName() == "PartyLayout") {
443                 PartyLayout *layout(new PartyLayout);
444                 int index(partyLayouts.size());
445                 partyLayouts.push_back(layout);
446                 ReadPartyLayout(*layout, *dfn.GetProperties());
447                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PARTY_LAYOUT, index)));
448         } else if (dfn.TypeName() == "SimpleAnimation") {
449                 SimpleAnimation *animation(new SimpleAnimation);
450                 int index(simpleAnimations.size());
451                 simpleAnimations.push_back(animation);
452                 ReadSimpleAnimation(*animation, *dfn.GetProperties());
453                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SIMPLE_ANIMATION, index)));
454         } else if (dfn.TypeName() == "Sprite") {
455                 Sprite *sprite(new Sprite);
456                 int index(sprites.size());
457                 sprites.push_back(sprite);
458                 ReadSprite(*sprite, *dfn.GetProperties());
459                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPRITE, index)));
460         } else {
461                 throw Error("unhandled object type: " + dfn.TypeName());
462         }
463 }
464
465
466 void Interpreter::ReadComplexAnimation(ComplexAnimation &a, const PropertyList &props) {
467         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
468                 if (i->first == "sprite") {
469                         a.SetSprite(GetSprite(*i->second));
470                 } else if (i->first == "frametime") {
471                         a.SetFrameTime(GetNumber(*i->second));
472                 } else if (i->first == "repeat") {
473                         a.SetRepeat(GetBoolean(*i->second));
474                 } else if (i->first == "frames") {
475                         const vector<PropertyList *> &values(GetPropertyListArray(*i->second));
476                         for (vector<PropertyList *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
477                                 ComplexAnimation::FrameProp frame;
478                                 ReadComplexAnimationFrame(frame, **i);
479                                 a.AddFrame(frame);
480                         }
481                 } else {
482                         throw Error("unknown ComplexAnimation property: " + i->first);
483                 }
484         }
485 }
486
487 void Interpreter::ReadComplexAnimationFrame(ComplexAnimation::FrameProp &f, const PropertyList &props) {
488         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
489                 if (i->first == "column") {
490                         f.col = GetNumber(*i->second);
491                 } else if (i->first == "row") {
492                         f.row = GetNumber(*i->second);
493                 } else if (i->first == "disposition") {
494                         f.disposition = GetVector(*i->second);
495                 } else {
496                         throw Error("unknown ComplexAnimationFrame property: " + i->first);
497                 }
498         }
499 }
500
501 void Interpreter::ReadFont(Font &f, const PropertyList &props) {
502         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
503                 if (i->first == "sprite") {
504                         f.SetSprite(GetSprite(*i->second));
505                 } else if (i->first == "columnoffset") {
506                         f.SetColOffset(GetNumber(*i->second));
507                 } else if (i->first == "rowoffset") {
508                         f.SetRowOffset(GetNumber(*i->second));
509                 } else {
510                         throw Error("unknown Font property: " + i->first);
511                 }
512         }
513 }
514
515 void Interpreter::ReadFrame(Frame &f, const PropertyList &props) {
516         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
517                 if (i->first == "image") {
518                         f.SetSurface(GetImage(*i->second));
519                 } else if (i->first == "border") {
520                         f.SetBorderSize(GetVector(*i->second));
521                 } else if (i->first == "repeat") {
522                         f.SetRepeatSize(GetVector(*i->second));
523                 } else if (i->first == "offset") {
524                         f.SetOffset(GetVector(*i->second));
525                 } else {
526                         throw Error("unknown Frame property: " + i->first);
527                 }
528         }
529 }
530
531 void Interpreter::ReadHero(Hero &h, const PropertyList &props) {
532         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
533                 if (i->first == "name") {
534                         h.SetName(GetString(*i->second));
535                 } else if (i->first == "sprite") {
536                         h.SetSprite(GetSprite(*i->second));
537                 } else if (i->first == "level") {
538                         h.SetLevel(GetNumber(*i->second));
539                 } else if (i->first == "maxHealth") {
540                         h.SetMaxHealth(GetNumber(*i->second));
541                 } else if (i->first == "health") {
542                         h.SetHealth(GetNumber(*i->second));
543                 } else if (i->first == "maxMana") {
544                         h.SetMaxMana(GetNumber(*i->second));
545                 } else if (i->first == "mana") {
546                         h.SetMana(GetNumber(*i->second));
547                 } else if (i->first == "ip") {
548                         h.SetIP(GetNumber(*i->second));
549                 } else if (i->first == "stats") {
550                         battle::Stats stats;
551                         ReadStats(stats, *GetPropertyList(*i->second));
552                         h.SetStats(stats);
553                 } else if (i->first == "attackAnimation") {
554                         h.SetAttackAnimation(GetAnimation(*i->second));
555                 } else if (i->first == "spellAnimation") {
556                         h.SetSpellAnimation(GetAnimation(*i->second));
557                 } else if (i->first == "meleeAnimation") {
558                         h.SetMeleeAnimation(GetAnimation(*i->second));
559                 } else {
560                         throw Error("unknown Hero property: " + i->first);
561                 }
562         }
563 }
564
565 void Interpreter::ReadMonster(Monster &m, const PropertyList &props) {
566         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
567                 if (i->first == "name") {
568                         m.SetName(GetString(*i->second));
569                 } else if (i->first == "sprite") {
570                         m.SetSprite(GetSprite(*i->second));
571                 } else if (i->first == "level") {
572                         m.SetLevel(GetNumber(*i->second));
573                 } else if (i->first == "maxHealth") {
574                         m.SetMaxHealth(GetNumber(*i->second));
575                 } else if (i->first == "health") {
576                         m.SetHealth(GetNumber(*i->second));
577                 } else if (i->first == "maxMana") {
578                         m.SetMaxMana(GetNumber(*i->second));
579                 } else if (i->first == "mana") {
580                         m.SetMana(GetNumber(*i->second));
581                 } else if (i->first == "stats") {
582                         battle::Stats stats;
583                         ReadStats(stats, *GetPropertyList(*i->second));
584                         m.SetStats(stats);
585                 } else if (i->first == "attackAnimation") {
586                         m.SetAttackAnimation(GetAnimation(*i->second));
587                 } else if (i->first == "meleeAnimation") {
588                         m.SetMeleeAnimation(GetAnimation(*i->second));
589                 } else {
590                         throw Error("unknown Monster property: " + i->first);
591                 }
592         }
593 }
594
595 void Interpreter::ReadPartyLayout(PartyLayout &p, const PropertyList &props) {
596         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
597                 if (i->first == "positions") {
598                         const vector<Value *> &positions(GetValueArray(*i->second));
599                         for (vector<Value *>::const_iterator j(positions.begin()), end(positions.end()); j != end; ++j) {
600                                 p.AddPosition(GetVector(**j));
601                         }
602                 } else {
603                         throw Error("unknown PartyLayout property: " + i->first);
604                 }
605         }
606 }
607
608 void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) {
609         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
610                 if (i->first == "sprite") {
611                         a.SetSprite(GetSprite(*i->second));
612                 } else if (i->first == "frametime") {
613                         a.SetFrameTime(GetNumber(*i->second));
614                 } else if (i->first == "repeat") {
615                         a.SetRepeat(GetBoolean(*i->second));
616                 } else if (i->first == "framecount") {
617                         a.SetNumFrames(GetNumber(*i->second));
618                 } else if (i->first == "col") {
619                         a.SetCol(GetNumber(*i->second));
620                 } else if (i->first == "row") {
621                         a.SetRow(GetNumber(*i->second));
622                 } else {
623                         throw Error("unknown SimpleAnimation property: " + i->first);
624                 }
625         }
626 }
627
628 void Interpreter::ReadSprite(Sprite &s, const PropertyList &props) {
629         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
630                 if (i->first == "image") {
631                         s.SetSurface(GetImage(*i->second));
632                 } else if (i->first == "size") {
633                         s.SetSize(GetVector(*i->second));
634                 } else if (i->first == "offset") {
635                         s.SetOffset(GetVector(*i->second));
636                 } else {
637                         throw Error("unknown Sprite property: " + i->first);
638                 }
639         }
640 }
641
642 void Interpreter::ReadStats(Stats &s, const PropertyList &props) {
643         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
644                 if (i->first == "atp") {
645                         s.SetAttack(GetNumber(*i->second));
646                 } else if (i->first == "dfp") {
647                         s.SetDefense(GetNumber(*i->second));
648                 } else if (i->first == "str") {
649                         s.SetStrength(GetNumber(*i->second));
650                 } else if (i->first == "agl") {
651                         s.SetAgility(GetNumber(*i->second));
652                 } else if (i->first == "int") {
653                         s.SetIntelligence(GetNumber(*i->second));
654                 } else if (i->first == "gut") {
655                         s.SetGut(GetNumber(*i->second));
656                 } else if (i->first == "mgr") {
657                         s.SetMagicResistance(GetNumber(*i->second));
658                 } else {
659                         throw Error("unknown Stats property: " + i->first);
660                 }
661         }
662 }
663
664 }