void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &literal) {
switch (literal.GetType()) {
case Literal::ARRAY_VALUES:
- throw Error("named value arrays are not supported, sorry");
- break;
case Literal::ARRAY_PROPS:
- throw Error("named property list arrays are not supported, sorry");
+ case Literal::ARRAY_IDENTS:
+ throw Error("named arrays are not supported, sorry");
break;
case Literal::BOOLEAN:
new (object) bool(literal.GetBoolean());
int typeId(0), id(0);
switch (v.GetLiteral().GetType()) {
case Literal::ARRAY_VALUES:
- throw Error("cannot copy value arrays, sorry");
- break;
case Literal::ARRAY_PROPS:
- throw Error("cannot copy property list arrays, sorry");
+ case Literal::ARRAY_IDENTS:
+ throw Error("cannot copy arrays, sorry");
break;
case Literal::BOOLEAN:
{
char *dest(object + fd.Offset());
if (fd.IsAggregate()) {
int arraySize(i->second->GetLiteral().ArraySize());
- char *aggregate(alloc.Alloc(fieldType.Size() * arraySize));
- char *iter(aggregate);
+ char *aggregate;
if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) {
+ aggregate = alloc.Alloc(fieldType.Size() * arraySize);
+ char *iter = aggregate;
const vector<PropertyList *> &list(i->second->GetLiteral().GetPropertyLists());
for (vector<PropertyList *>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) {
fieldType.Construct(iter);
ReadObject(fieldType.TypeId(), -1, iter, **j);
}
- } else {
+ } else if (i->second->GetLiteral().GetType() == Literal::ARRAY_VALUES) {
+ aggregate = alloc.Alloc(fieldType.Size() * arraySize);
+ char *iter = aggregate;
const vector<Value *> &list(i->second->GetLiteral().GetValues());
for (vector<Value *>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) {
fieldType.Construct(iter);
ReadLiteral(fieldType.TypeId(), -1, iter, (*j)->GetLiteral());
}
+ } else {
+ aggregate = alloc.Alloc(sizeof(char *) * arraySize);
+ char *iter = aggregate;
+ const vector<string> &list(i->second->GetLiteral().GetIdentifiers());
+ for (vector<string>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += sizeof(void *)) {
+ if (source.IsDefined(*j)) {
+ *reinterpret_cast<void **>(iter)
+ = GetObject(fd.TypeId(), *j);
+ } else {
+ Postpone(typeId, id, fd.Offset() + (iter - aggregate), *j, fd.TypeId(), false);
+ }
+ }
}
if (fd.IsReferenced()) {
std::memcpy(dest, &aggregate, sizeof(char *));
}
+Literal::Literal(const string &typeName, const vector<string> &ids)
+: props(0)
+, typeName(typeName)
+, identifiers(ids)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(ARRAY_IDENTS) {
+
+}
+
Literal::Literal(bool b)
: props(0)
, typeName("Boolean")
}
}
+const vector<string> &Literal::GetIdentifiers() const {
+ if (type == ARRAY_IDENTS) {
+ return identifiers;
+ } else {
+ throw runtime_error("tried to access identifiers of non-array literal");
+ }
+}
+
bool Literal::GetBoolean() const {
if (type == BOOLEAN) {
return b;
case loader::Literal::ARRAY_PROPS:
out << "array of property lists";
break;
+ case loader::Literal::ARRAY_IDENTS:
+ out << "array of identifiers";
+ break;
case loader::Literal::BOOLEAN:
out << "boolean, " << (l.GetBoolean() ? "true" : "false");
break;
enum Type {
ARRAY_VALUES,
ARRAY_PROPS,
+ ARRAY_IDENTS,
BOOLEAN,
COLOR,
NUMBER,
};
public:
+ /// array of values
explicit Literal(const std::vector<Value *> &);
+ /// array of objects
Literal(const std::string &, const std::vector<PropertyList *> &);
+ /// array of identifiers
+ Literal(const std::string &, const std::vector<std::string> &);
+ /// boolean
explicit Literal(bool);
+ /// color
Literal(int r, int g, int b, int a = 255);
+ /// number
explicit Literal(int number);
+ /// path string
Literal(const std::string &dir, const std::string &path);
+ /// string
Literal(const std::string &);
+ /// vector
Literal(int x, int y);
+ /// object
Literal(const std::string &typeName, PropertyList *properties);
+ /// script
explicit Literal(const std::vector<ScriptToken *> &);
~Literal();
private:
public:
Type GetType() const { return type; }
- bool IsArray() const { return GetType() == ARRAY_VALUES || GetType() == ARRAY_PROPS; }
+ bool IsArray() const { return GetType() == ARRAY_VALUES || GetType() == ARRAY_PROPS || GetType() == ARRAY_IDENTS; }
bool IsObject() const { return GetType() == OBJECT; }
- int ArraySize() const { return GetType() == ARRAY_VALUES ? GetValues().size() : GetPropertyLists().size(); }
+ int ArraySize() const { return GetType() == ARRAY_VALUES ? GetValues().size()
+ : (GetType() == ARRAY_PROPS ? GetPropertyLists().size() : GetIdentifiers().size()); }
const std::vector<Value *> &GetValues() const;
const std::vector<PropertyList *> &GetPropertyLists() const;
+ const std::vector<std::string> &GetIdentifiers() const;
bool GetBoolean() const;
int GetRed() const;
int GetGreen() const;
std::string typeName, str;
std::vector<Value *> values;
std::vector<PropertyList *> propertyLists;
+ std::vector<std::string> identifiers;
std::vector<ScriptToken *> script;
int i1, i2, i3, i4;
bool b;
Token probe(GetToken());
if (probe.type == Token::TYPE_NAME) {
- vector<PropertyList *> values;
- while (t.type != Token::BRACKET_CLOSE) {
- PropertyList *value(ParsePropertyList());
- values.push_back(value);
+ t = GetToken();
+ tok.Putback(t);
+ if (t.type == Token::ANGLE_BRACKET_OPEN) {
+ vector<PropertyList *> values;
+ while (t.type != Token::BRACKET_CLOSE) {
+ PropertyList *value(ParsePropertyList());
+ values.push_back(value);
- t = GetToken();
- if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) {
- throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
+ t = GetToken();
+ if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
+ }
+ }
+ return new Literal(probe.str, values);
+ } else {
+ vector<string> values;
+ while (t.type != Token::BRACKET_CLOSE) {
+ string value(ParseIdentifier());
+ values.push_back(value);
+
+ t = GetToken();
+ if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
+ }
}
+ return new Literal(probe.str, values);
}
- return new Literal(probe.str, values);
} else {
tok.Putback(probe);
/// Add monsters. This will cause the entity to be Hostile() and result in a
/// battle scene with given monsters when touched.
- void SetMonsters(battle::Monster *m, int num) { monsters = m; numMonsters = num; }
- battle::Monster *MonstersBegin() { return monsters; }
- battle::Monster *MonstersEnd() { return monsters + numMonsters; }
+ void SetMonsters(battle::Monster **m, int num) { monsters = m; numMonsters = num; }
+ battle::Monster **MonstersBegin() { return monsters; }
+ battle::Monster **MonstersEnd() { return monsters + numMonsters; }
/// Get an entity that should follow in this one's steps or 0 if none.
Entity *Follower() { return follower; }
const graphics::Animation *animation;
const graphics::Sprite *sprite;
battle::PartyLayout *partyLayout;
- battle::Monster *monsters;
+ battle::Monster **monsters;
int numMonsters;
graphics::AnimationRunner runner;
geometry::Vector<int> spriteOffset;
battleState->AddHero(*game->state->party[i]);
}
}
- for (battle::Monster *monster((*e)->MonstersBegin()); monster != (*e)->MonstersEnd(); ++monster) {
- battleState->AddMonster(*monster);
+ for (battle::Monster **monster((*e)->MonstersBegin()); monster != (*e)->MonstersEnd(); ++monster) {
+ battleState->AddMonster(**monster);
}
ColorFade *fadeIn(new ColorFade(this, 0, 500, true));
repeat: true
},
position: <2, 1>,
- partyLayout: monstersLayout
- // TODO: monsters
+ partyLayout: monstersLayout,
+ monsters: [ Monster
+ lizard,
+ lizard
+ ]
},
{
sprite: Sprite {