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