Page 4 of 4
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 13:24
by imbaczek
the way i see how it could work:
Code: Select all
1. load unitdef definition from python/lua/xml/whatever.
2. generate UnitDef class (e.g. UnitDef.gen.h)
3. generate Lua bindings (this currently lives in LuaDefs.h and LuaUnitDefs.cpp)
4. generate AI binding functions (currently in over 9000 files if i'm not mistaken)
it's really rather straightforward to emit the unitdef with proper definition, e.g. if you have
then generation of UnitDef.gen.h would be like:
Code: Select all
for each member of unitdef:
if member.type is string:
write("\tstd::string %s;\n", member.name)
this is the simplest case, but you get the idea. the writer should actually be extensible so you can add custom types easily, etc.
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 15:09
by Auswaschbar
imbaczek wrote:the way i see how it could work:
Code: Select all
1. load unitdef definition from python/lua/xml/whatever.
2. generate UnitDef class (e.g. UnitDef.gen.h)
3. generate Lua bindings (this currently lives in LuaDefs.h and LuaUnitDefs.cpp)
4. generate AI binding functions (currently in over 9000 files if i'm not mistaken)
What do we need step 1 for if we could just write the class by hand and let the compiler / preprocessor generate lua / AI bindings?
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 17:18
by imbaczek
if you can make the preprocessor and compiler to do that... i know i wouldn't bother.
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 17:37
by Tobi
An easy (but incredibly ugly and hacky IMO) way is to make a list of fields in a file "UnitDefFields.inc" like this:
Code: Select all
UNITDEF_FIELD(std::string, humanName)
UNITDEF_FIELD(int, maxHealth)
//etc...
and to then have UnitDef.h like this:
Code: Select all
#define UNITDEF_FIELD(type,name) \
type name;
struct UnitDef {
#include "UnitDefFields.inc"
};
#undef UNITDEF_FIELD
But TBH I wouldn't be happy to see this kind of dirty hacks in the engine. And no, I don't consider template metaprogramming tricks to be any better..
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 17:44
by Auswaschbar
Tobi wrote:An easy (but incredibly ugly and hacky IMO) way is to make a list of fields in a file "UnitDefFields.inc" like this:
Code: Select all
UNITDEF_FIELD(std::string, humanName)
UNITDEF_FIELD(int, maxHealth)
//etc...
and to then have UnitDef.h like this:
Code: Select all
#define UNITDEF_FIELD(type,name) \
type name;
struct UnitDef {
#include "UnitDefFields.inc"
};
#undef UNITDEF_FIELD
But TBH I wouldn't be happy to see this kind of dirty hacks in the engine. And no, I don't consider template metaprogramming tricks to be any better..
Whats the advantage of you example over
Code: Select all
struct UnitDef {
std::string humanName;
int maxHealth;
};
And, tbh, the whole unitdef-thing (hey, lets add all variables a unit of any mod might ever need in one class) is screwed and not suiting for a project which claims to be a flexible engine.
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 19:42
by Tobi
You missed the point entirely, the suggested idea was to generate not only UnitDef, but also the AI and Lua interface,
without having to parse C++ sourcecode using an extra tool.
E.g. add this:
Code: Select all
#define UNITDEF_FIELD(type, name) \
type CSomeAIClass::Get##name(int unitDefID) { \
return unitdefHandler->GetUnitDefByID(unitDefID)->name; \
}
And, tbh, the whole unitdef-thing (hey, lets add all variables a unit of any mod might ever need in one class) is screwed and not suiting for a project which claims to be a flexible engine.
You missed the point here again, the point ("a" point, it has multiple) is NOT to add all members of all mods ever made as hardcoded variables inside the engine, the point of the thread is to design a generic solution so both engine and mod variables get similar treatment in in particular Lua and AI interfaces.
Anyway, just putting a comment in UnitDef.h still seems best solution to me, possibly combined by a small script integrated in build system that fails if there's a mismatch between UnitDef members and AI/Lua interface.
All the code generation or property system designs in this thread seem overcomplicated to me.
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 20:25
by AF
In relation to the original comment on variables in unitdef that dont tell you what theyre for ro where in the code they're used, doxygen should be suitable, so its best worked into any autogeneration found
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 04 May 2009, 22:10
by imbaczek
the checking script would have to parse C++...
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 05 May 2009, 01:47
by Tobi
For checking a parser can be much more crude usually, in my experience.
(It doesn't matter if the script skips some properties, if -for example- it reads 90% of the UnitDef properties correctly then it would already reduce the amount of times someone forgets to add a property to Lua/AI interface with 90%.)
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 05 May 2009, 03:41
by aegis
YAML?
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 05 May 2009, 08:53
by hoijui
hmm...
this making a comment and checking with a script if the property is added to Lua and AI interface...
it is simple, but would help in only one aspect: we would more likely be exporting all props that are meant to be exported.
it would not make management and accessing properties more unified eg.
also... i see it happening like this:
somoene adds a property, compiles spring, and uses it, not even noticing the wrarnings, and someone later an other dev would have to go through the wranings and try to find out if the prop is usefull for Lua and/or AI, and add code to export it. i would not like to be that dev.
otherwise, the guy adding the property would have to add a line somewhere that contains everything needed anyway (eg name, type, description, flags (AI | LUA | ...)).
i still think having something like a WorldObjectWithProperties solution is the best way to go. it is not hacky at all, has all the pros, and .. if its not the speed, then i dont know what contra.
it would be like this:
UnitDef.cpp:
Code: Select all
UnitDef::UnitDef() {
this.addProperty(PROP_IDX_NAME, "name", "EMPTY", AI_EXPORT | LUA_EXPORT, "The name of this type of unit");
this.addProperty(PROP_IDX_MODEL, "modelId" 0, LUA_EXPORT, "The graphical representation of this unit type");
...
}
in the mod:
Code: Select all
...
unitDef[x].addProperty(hyperSpaceSpeed, 1000, AI_EXPORT | LUA_EXPORT, "The of this unit tpe when flying in hyper-space");
...
in an AI:
Code: Select all
...
unitDef[x].listAllProperties();
...
output:
Code: Select all
name, "spaceFighter", AI_EXPORT | LUA_EXPORT, "The name of this type of unit"
hyperSpaceSpeed, 1000, AI_EXPORT | LUA_EXPORT, "The of this unit tpe when flying in hyper-space"
the details in this example are not correct (like property indices and name handling and such). its just meant as an intro to the idea in general.
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 05 May 2009, 11:39
by imbaczek
i'm not convinced that anything that results in more than a single memory access is a good idea, *defs are used everywhere and it may be too expensive to make reading them more complex...
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 05 May 2009, 12:57
by hoijui
as tobi pointed out, this method can be used with a single memory access only aswell.
eg:
Code: Select all
const int UNITDEF_PROP_IDX_MAXSPEED = 9;
...
int maxSpeed = unitDef[x].properties[UNITDEF_PROP_IDX_MAXSPEED];
// optimized by the compiler (?)
Re: Luarules <-> AI, part 1 of 0: resources
Posted: 05 May 2009, 13:40
by imbaczek
possible.
i'm starting to get confused what the cons and pros of this change would be. i could use some convincing that it's really needed.