#include "../graphics/SimpleAnimation.h"
#include "../graphics/Sprite.h"
+#include <algorithm>
#include <SDL_image.h>
using battle::Hero;
using graphics::SimpleAnimation;
using graphics::Sprite;
using geometry::Vector;
+using std::make_pair;
using std::map;
using std::set;
using std::string;
namespace loader {
+Interpreter::~Interpreter() {
+ for (vector<Animation *>::const_iterator i(animations.begin()), end(animations.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<SDL_Surface *>::const_iterator i(images.begin()), end(images.end()); i != end; ++i) {
+ SDL_FreeSurface(*i);
+ }
+}
+
+
+bool Interpreter::ParsedDefinition::IsCompatible(DynamicType with) const {
+ return type == with
+ || (with == ANIMATION
+ && (type == COMPLEX_ANIMATION || type == SIMPLE_ANIMATION));
+}
+
+
Animation *Interpreter::GetAnimation(const std::string &name) {
- map<string, Animation *>::const_iterator i(animations.find(name));
- if (i != animations.end()) {
- return i->second;
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.IsCompatible(ANIMATION)) {
+ return animations[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Animation");
+ }
} else {
throw Error("access to undefined Animation " + name);
}
}
Hero *Interpreter::GetHero(const std::string &name) {
- map<string, Hero *>::const_iterator i(heroes.find(name));
- if (i != heroes.end()) {
- return i->second;
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.IsCompatible(HERO)) {
+ return &heroes[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Hero");
+ }
} else {
throw Error("access to undefined Hero " + name);
}
}
Monster *Interpreter::GetMonster(const std::string &name) {
- map<string, Monster *>::const_iterator i(monsters.find(name));
- if (i != monsters.end()) {
- return i->second;
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.IsCompatible(MONSTER)) {
+ return &monsters[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Monster");
+ }
} else {
throw Error("access to undefined Monster " + name);
}
}
int Interpreter::GetNumber(const std::string &name) const {
- map<string, int>::const_iterator i(numbers.find(name));
- if (i != numbers.end()) {
- return i->second;
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.IsCompatible(NUMBER)) {
+ return numbers[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Number");
+ }
} else {
throw Error("access to undefined Number " + name);
}
}
Sprite *Interpreter::GetSprite(const std::string &name) {
- map<string, Sprite *>::const_iterator i(sprites.find(name));
- if (i != sprites.end()) {
- return i->second;
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.IsCompatible(SPRITE)) {
+ return &sprites[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Sprite");
+ }
} else {
throw Error("access to undefined Sprite " + name);
}
throw Error("unhandled literal: color");
break;
case Literal::NUMBER:
- numbers[dfn.Identifier()] = dfn.GetLiteral()->GetNumber();
+ numbers.push_back(dfn.GetLiteral()->GetNumber());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, NUMBER, numbers.size() - 1)));
break;
case Literal::STRING:
throw Error("unhandled literal: string");
if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
ComplexAnimation *a(new ComplexAnimation);
ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
+ animations.push_back(a);
return a;
} else {
SimpleAnimation *a(new SimpleAnimation);
ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
+ animations.push_back(a);
return a;
}
- } else if (animations.count(v.GetIdentifier())) {
- return animations[v.GetIdentifier()];
- } else if (source.IsDefined(v.GetIdentifier())) {
- ReadDefinition(source.GetDefinition(v.GetIdentifier()));
- if (animations.count(v.GetIdentifier())) {
- return animations[v.GetIdentifier()];
- } else {
- throw Error("cannot use " + source.GetDefinition(v.GetIdentifier()).Identifier() + " " + v.GetIdentifier() + " as animation");
- }
} else {
- throw Error("use of undefined Animation " + v.GetIdentifier());
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetAnimation(v.GetIdentifier());
}
}
SDL_Surface *Interpreter::GetImage(const Value &v) {
const char *file(GetString(v));
- return IMG_Load(file);
+ SDL_Surface *image(IMG_Load(file));
+ images.push_back(image);
+ return image;
}
int Interpreter::GetNumber(const Value &v) {
if (v.IsLiteral()) {
return v.GetLiteral().GetNumber();
- } else if (numbers.count(v.GetIdentifier())) {
- return numbers[v.GetIdentifier()];
} else {
ReadDefinition(source.GetDefinition(v.GetIdentifier()));
- if (numbers.count(v.GetIdentifier())) {
- return numbers[v.GetIdentifier()];
- } else {
- throw Error("use of undefined Number " + v.GetIdentifier());
- }
+ return GetNumber(v.GetIdentifier());
}
}
Sprite *s(new Sprite);
ReadSprite(*s, *v.GetLiteral().GetProperties());
return s;
- } else if (sprites.count(v.GetIdentifier())) {
- return sprites[v.GetIdentifier()];
} else {
ReadDefinition(source.GetDefinition(v.GetIdentifier()));
- if (sprites.count(v.GetIdentifier())) {
- return sprites[v.GetIdentifier()];
- } else {
- throw Error("use of undefined Sprite " + v.GetIdentifier());
- }
+ return GetSprite(v.GetIdentifier());
}
}
void Interpreter::ReadObject(const Definition &dfn) {
if (dfn.TypeName() == "Hero") {
- Hero *h(new Hero);
- ReadHero(*h, *dfn.GetProperties());
- heroes[dfn.Identifier()] = h;
+ heroes.push_back(Hero());
+ ReadHero(heroes.back(), *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, HERO, heroes.size() - 1)));
} else if (dfn.TypeName() == "Monster") {
- Monster *m(new Monster);
- ReadMonster(*m, *dfn.GetProperties());
- monsters[dfn.Identifier()] = m;
+ monsters.push_back(Monster());
+ ReadMonster(monsters.back(), *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MONSTER, monsters.size() - 1)));
} else if (dfn.TypeName() == "Sprite") {
- Sprite *s(new Sprite);
- ReadSprite(*s, *dfn.GetProperties());
- sprites[dfn.Identifier()] = s;
+ sprites.push_back(Sprite());
+ ReadSprite(sprites.back(), *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPRITE, sprites.size() - 1)));
} else {
- throw Error("unhandled object: " + dfn.TypeName());
+ throw Error("unhandled object type: " + dfn.TypeName());
}
}
#include "../graphics/ComplexAnimation.h"
#include <map>
-#include <set>
#include <stdexcept>
#include <string>
#include <vector>
public:
Interpreter(const ParsedSource &source) : source(source) { }
- ~Interpreter() { }
+ ~Interpreter();
private:
Interpreter(const Interpreter &);
Interpreter &operator =(const Interpreter &);
private:
const ParsedSource &source;
- std::set<std::string> parsedDefinitions;
-
- std::map<std::string, graphics::Animation *> animations;
- std::map<std::string, battle::Hero *> heroes;
- std::map<std::string, battle::Monster *> monsters;
- std::map<std::string, int> numbers;
- std::map<std::string, graphics::Sprite *> sprites;
+ enum DynamicType {
+ ANIMATION,
+ COMPLEX_ANIMATION,
+ HERO,
+ MONSTER,
+ NUMBER,
+ SIMPLE_ANIMATION,
+ SPRITE,
+ };
+ struct ParsedDefinition {
+ ParsedDefinition(const Definition *dfn, DynamicType type, int index)
+ : dfn(dfn), type(type), index(index) { }
+ bool IsCompatible(DynamicType with) const;
+ const Definition *dfn;
+ DynamicType type;
+ int index;
+ };
+ std::map<std::string, ParsedDefinition> parsedDefinitions;
+
+ std::vector<graphics::Animation *> animations;
+ std::vector<battle::Hero> heroes;
+ std::vector<SDL_Surface *> images;
+ std::vector<battle::Monster> monsters;
+ std::vector<int> numbers;
+ std::vector<graphics::Sprite> sprites;
};