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