Luarules <-> AI, part 1 of 0: resources

Luarules <-> AI, part 1 of 0: resources

Here is where ideas can be collected for the skirmish AI in development

Moderators: hoijui, Moderators

User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Luarules <-> AI, part 1 of 0: resources

Post by lurker »

AIs need to get more info about games that don't exactly follow TA. Let's go.
AIs will need access to the cob storage vars in this draft, and their array size will need to be expanded.

Resources draft 1:
[code]
{
    COBTeamVars[ALLY_VAR_COUNT-1] = lua resource 1 storage or -1 if inapplicable
    COBTeamVars[ALLY_VAR_COUNT-2] = lua resource 1 amount or -1 if inapplicable
    COBTeamVars[ALLY_VAR_COUNT-3] = lua resource 1 income or -1 if inapplicable
    COBTeamVars[ALLY_VAR_COUNT-4] = lua resource 1 drain or -1 if inapplicable
} repeat for all lua resources

{
    COBTeamVars[UNIT_VAR_COUNT-1] = lua resource 1 storage or -1 if inapplicable
    COBTeamVars[UNIT_VAR_COUNT-2] = lua resource 1 amount or -1 if inapplicable
    COBUnitVars[UNIT_VAR_COUNT-3] = lua resource 1 income or -1 if inapplicable
    COBUnitVars[UNIT_VAR_COUNT-4] = lua resource 1 drain or -1 if inapplicable
} repeat for all lua resources

[modinfo] {
    [resources] {
        useEnergy = 1|0;
        useMetal = 1|0;
        luaResourceCount = int;
        resourcename1 = string;
        resourcename2 = string;
        ...
    }
}

[UnitDef] {
    [customparams] {
        //these can stretch the truth to be semi-accurate when it's complex
        //assume any not present are 0
        [resource name 1]store = float;
        [resource name 1]cost = float;
        [resource name 1]make = float;
        [resource name 1]use = float;
        [resource name 1]upkeep = float;
        //repeat for all lua resources
    }
}

[WeaponDef] {
    [customparams] {
        //assume 0 if not present
        [resource name 1]cost = float;
        //repeat for all lua resources
    }
}[/code]


Some sample interpretations (please point out anything wrong):
If amount is inapplicable you're probably looking at a direct feed resource, like power.
If storage is inapplicable but you do have an amount then you can hold as much as you want.
If a unit has storage it might be ammo for weapons (check them) or it could be a harvester of some sort. (It should likely have an automatic harvesting gadget that takes over, and should lie and say that it has income of the resource in the unitdef.)
If you want some units that cost refined_materials and see that refined_materials are generated by a building, make that building.

<3 nonbreaking spaces
Last edited by lurker on 18 Nov 2008, 18:05, edited 1 time in total.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Luarules <-> AI, part 1 of 0: resources

Post by hoijui »

nice you start something lurker :-)

soo.. as I have no idea about mods, some questions:

1. All you wrote here, is not yet available, but if this draft were accepted, game devs would add it to files in their mod, from where we could read it and feed it to the AIs. Is that the idea?

2. The first two blocks (repeat for all lua resources), are in separate files (eg resources.lua)?

Energy and metal are still special cases. I guess that is not possible to circumvent, for backwards compatibility reasons and cause the engine expects these two resources.
But from the AIs point of few, we could remove this. In about this fashion:

Code: Select all

AICallback {

	int getNumResources();
	const char* getResourceName(int resourceIndex);
	float getResourceIncome(int resourceIndex);
	float getResourceStorage(int resourceIndex);
	...
}
Energy could be resourceIndex=0 and metal resourceIndex=1 eg.

It would be no problem for current AIs of course, cause we just had to adapt the Legacy C++ compatibility layer to use the new functions, eg:

Code: Select all

LegacyAICallback {
	float GetMetalIncome() {
		static METAL_RESOURCE_INDEX = -1;
		if (METAL_RESOURCE_INDEX) {
			int size = getNumResources();
			for (int i=0; i < size; ++i) {
				if (strcmp(getResourceName(i), "Metal") == 0) {
					METAL_RESOURCE_INDEX = i;
					break;
				}
			}
		}
		return getResourceIncome(METAL_RESOURCE_INDEX);
	}
}

About LUA (Unit-)Commands:
Is the problem with them, that they are only known to the engine after the AI is loaded?
If so, we could have an AI event CommandsChanged maybe. Or is the problem, that we can not provide a suitable native container for them, as they may have an arbitrary number and types of arguments? Or is it just that the engine does not know about mod specific commands, and therefore can not tell them to AIs?
Would mods publicize their custom commands to the engine for it to make them available to AIs, or would rather the engine read some files? (hmm, ok, not really a difference there :D)
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Luarules <-> AI, part 1 of 0: resources

Post by lurker »

hoijui wrote:1. All you wrote here, is not yet available, but if this draft were accepted, game devs would add it to files in their mod, from where we could read it and feed it to the AIs. Is that the idea?
Pretty much.
hoijui wrote:2. The first two blocks (repeat for all lua resources), are in separate files (eg resources.lua)?
No, those are live data in CCobInstance::globalVars, CCobInstance::teamVars, CCobInstance->unitVars. They're already exposed to both cob and lua; just needing AI bindings.
hoijui wrote:

Code: Select all

AICallback {

	int getNumResources();
	const char* getResourceName(int resourceIndex);
	float getResourceIncome(int resourceIndex);
	float getResourceStorage(int resourceIndex);
	...
}
Energy could be resourceIndex=0 and metal resourceIndex=1 eg.
This works if you want dedicated functions. The way I was thinking there would be different types of data stored in the cob vars that wouldn't need any engine support. If you do go with dedicated functions then dedicated storage and lua functions might be a good idea, but it can become harder for cob to access.


I didn't give much thought to unit commands yet, nor do I know what would be the best way to go about them. The only thing that came to me so far was using tokens to describe commands. 'point attack' 'area attack' 'area team help' 'randomly use this while attacking' 'similar to creating unit x free' 'similar to creating unit x for cost' 'free upgrade' 'upgrade for cost'
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Luarules <-> AI, part 1 of 0: resources

Post by hoijui »

lurker wrote:
hoijui wrote:

Code: Select all

AICallback {

	int getNumResources();
	const char* getResourceName(int resourceIndex);
	float getResourceIncome(int resourceIndex);
	float getResourceStorage(int resourceIndex);
	...
}
Energy could be resourceIndex=0 and metal resourceIndex=1 eg.
This works if you want dedicated functions. The way I was thinking there would be different types of data stored in the cob vars that wouldn't need any engine support. If you do go with dedicated functions then dedicated storage and lua functions might be a good idea, but it can become harder for cob to access.
... i have really no idea what you are talking about here :D
you mean AIs should read values directly from the mod VFS? :/
lurker wrote: I didn't give much thought to unit commands yet, nor do I know what would be the best way to go about them. The only thing that came to me so far was using tokens to describe commands. 'point attack' 'area attack' 'area team help' 'randomly use this while attacking' 'similar to creating unit x free' 'similar to creating unit x for cost' 'free upgrade' 'upgrade for cost'
hmm...
this is, how AIs could possibly get an idea what a command can be used for in a dynamic way, hm?
I was rather thinking on how we could make AIs to have access to Mod LUA commands at all.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Luarules <-> AI, part 1 of 0: resources

Post by AF »

The word cob has no business in these forums. Please exercise encapsulation.
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Re: Luarules <-> AI, part 1 of 0: resources

Post by imbaczek »

AI needs a two-way Lua interface so the AI can interrogate the mod about it's capabilities. Using COB values is a hack and IMHO an ugly one.

I'd suggest something that complements the current SendToAI (or whatever it's called):

CallModLua(funcname, args)

where args are a serialized dictionary, eg. using JSON notation or Lua table notation. Lua is good since the functions to access the table are already done in spring, so using an opaque void* should be enough in the AI. The interface should only export SetTable*(k, v)/GetTable*(k) family of functions.

when that's available, we could define a protocol, e.g. when AI is loaded, it calls

CallModLua("InitAI", {AI name, version, difficulty, etc})

which the mod sees as a call to

function InitAI(playerid, teamid, {AI name, version, difficulty, etc})

that sets up the cheats according to the difficulty level (levels should be defined somewhere else, like in the modinfo.tdf). InitAI could then return something, like supported functions, resource model, whatever.

other functions, like GetResources, GetPointsOfInterest(type), etc could be standardized by the community and defined by the mod itself without any engine changes. i hope you get the idea.

BTW my emphasis is on standardized by the community, all this could be made now with a defacto standard SendToAI protocol that AIs respected.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Luarules <-> AI, part 1 of 0: resources

Post by jK »

imbaczek wrote:AI needs a two-way Lua interface so the AI can interrogate the mod about it's capabilities. Using COB values is a hack and IMHO an ugly one.
AFAIK AIs have access to Unit,Team,Ally and Game vars (those aren't in the wiki, but used by CA) -> no need for COB. Also there is the two-way callin/-out system (useful for events) named by you.
imbaczek wrote:BTW my emphasis is on standardized by the community, all this could be made now with a defacto standard SendToAI protocol that AIs respected.
Yeah, there are more than enough ways to interact with AI, it is just that AI devs aren't doing anything into that direction ...
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Luarules <-> AI, part 1 of 0: resources

Post by AF »

but we've been shooting cute glances with big shiny anime eyes in your direction looking all helpless for quite a while now, please lay down some palms so we can storm in with the heavy machinery!
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Luarules <-> AI, part 1 of 0: resources

Post by hoijui »

..i am more confused now
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Luarules <-> AI, part 1 of 0: resources

Post by lurker »

Forget about cob. The important thing is that these are global arrays that anything can access. Since resources update a lot I was thinking of a way to cut down on function calls but have the data in a friendly place for everyone. This proposal is for a community standard needing no engine support. Feel free to change it to use only calls back and forth or propose something else entirely.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Luarules <-> AI, part 1 of 0: resources

Post by AF »

tbh cob is something we only use because lua doesnt support animation yet. Anything in cob should be purely animation, anything more complex should eb done in lua even if its possible in cob
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Luarules <-> AI, part 1 of 0: resources

Post by lurker »

Version 2, with an api. Uses a theoretical ability for AIs to read some form of dictionary.
This is all from the point of view of LuaRules.

_G.Resources[teamid] = {
    monies = {
        storage = false;
        amount = 7000;
        income = 500;
        drain = 0;
    },
    power = {
        storage = false;
        amount = false;
        income = 1200;
        drain = 1100;
    },
}

function GetTeamResources(playerid, teamid)
    return _G.Resources[teamid] --already in the correct format
end

function GetUnitResources(playerid, teamid, unitid)
    local unit = _G.UnitResources[unitid]
    if unit == nil then return nil end
    local unitResources = {
        monies = {
            storage = false;
            amount = false;
            income = unit.moniesincome;
            drain = false;
        },
        power = {
            storage = false;
            amount = false;
            income = unit.energymake;
            drain = unit.energyuse;
        },
    }
    return unitResources
end

function GetResourceInfo()
    local useEnergy = 1
    local useMetal = 1
    local luaResources = {
        monies,
        power,
    }
    return useEnergy, useMetal, luaResources
end

function UnitDefHints()
    local hints = {
        unitDefID = {
            --these can stretch the truth to be semi-accurate when it's complex
            --assume any not present are 0
            [resource name 1]store = float;
            [resource name 1]cost = float;
            [resource name 1]make = float;
            [resource name 1]use = float;
            [resource name 1]upkeep = float;
            --repeat for all lua resources
        },
        unitDefID = { --etc.
        },
    }
    return hints
end

function WeaponDefHints()
    local hints = {
        weaponDefID = {
            [resource name 1]cost = float;
            --repeat for all lua resources
        },
    }
    return hints
}
end
Last edited by lurker on 18 Nov 2008, 18:20, edited 3 times in total.
User avatar
BrainDamage
Lobby Developer
Posts: 1164
Joined: 25 Sep 2006, 13:56

Re: Luarules <-> AI, part 1 of 0: resources

Post by BrainDamage »

no negative amount of res supported (ie debt) ?

you sure it's a good idea to have to create an additional resource to have to represent debt?
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Luarules <-> AI, part 1 of 0: resources

Post by lurker »

Good point. Since this is all lua-tastic now let's use false for inapplicable. Editing the post above you. It might be better to use nil in the end but false is clearer for now, and both evaluate to false.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Luarules <-> AI, part 1 of 0: resources

Post by jK »

LuaRules.cpp

Code: Select all

	lua_getglobal(L, "Spring");
	LuaPushNamedCFunc(L, "SetRulesInfoMap",       SetRulesInfoMap);
	LuaPushNamedCFunc(L, "SetUnitRulesParam",     SetUnitRulesParam);
	LuaPushNamedCFunc(L, "SetTeamRulesParam",     SetTeamRulesParam);
	LuaPushNamedCFunc(L, "SetGameRulesParam",     SetGameRulesParam);
	LuaPushNamedCFunc(L, "CreateUnitRulesParams", CreateUnitRulesParams);
	LuaPushNamedCFunc(L, "CreateTeamRulesParams", CreateTeamRulesParams);
	LuaPushNamedCFunc(L, "CreateGameRulesParams", CreateGameRulesParams);
	lua_pop(L, 1);
use them
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Luarules <-> AI, part 1 of 0: resources

Post by AF »

hmmm, can we send strings across the lua<-> AI divide or was that problem never solved? I remember looking at the signature for the new API addition when trepan added it and noticing it did not have allowances for anything but numerical values but i havent checked since.

AIs would need to search for a particular lua file and then load their own lua virtual machines in order to parse it. Currently no native AI has a lua runtime inside it yet, so if we can simplify this into a more message based system then that would be much better. Thus i think we should approach this form a networking point of view not a lua API view, because there are no function calls across the boundaries, just a collection of values sent to a specific AI like a broadcast from my understanding.

I also think this resource spec is not flexible enough because they all assume that they follow the normal system of TA in that its beneficial to gather as much resources as you can. What if we want a resource representing score where we want the value to be as small as possible?

For example, we might have to look after citizens, and we may represent their alarm as a resource we want as little of as possible encase they revolt.
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Luarules <-> AI, part 1 of 0: resources

Post by lurker »

Edit a couple months later to fix, had to read the code twice to understand it yay:

I couldn't find any documentation, so here is my best shot.


SetRulesInfoMap(table):
Wipes out the existing InfoMap before it starts.
map<string, string>& infoMap = luaRules->infoMap;
Takes a flat lua table, shoves it into this string to string std::map.



The next two use these these pairs of variables:
    lr->gameParamsMap and gameParamsMap
    team->modParams and modParamsMap
    unit->modParams and modParamsMap

CreateUnitRulesParams(unitid, table)
CreateTeamRulesParams(team, table)
CreateGameRulesParams(table)
    Wipes out the existing RulesParams before it starts.
    Takes a lua table with both named and unnamed float values.

    vector<float>& params
    The values go in here.

    map<string, int>& paramsMap
    The names go in here, with the int being the index of the float value.


SetUnitRulesParam(unitid, index, value)
SetTeamRulesParam(team, index, value)
SetGameRulesParam(key, value)
    Does not wipe out the existing members.

    If key is an int, params[index] = value if the vector already
    has a params[index]


    If key is a string, the value is stored in params, increasing the
    size if necessary. paramsMap[key] is the index in params where
    the value can be found.
Last edited by lurker on 18 Nov 2008, 19:17, edited 1 time in total.
User avatar
BrainDamage
Lobby Developer
Posts: 1164
Joined: 25 Sep 2006, 13:56

Re: Luarules <-> AI, part 1 of 0: resources

Post by BrainDamage »

lurker wrote:         income = 1200;
        drain = 1100;
is separated income and drain even necessary when using false as separate state?
can't they just be tied togheter in a single delta value which is income - drain? or is there any case when you'd want to know them separated? don't get get summed anyway in the resource pool?
AF wrote:I also think this resource spec is not flexible enough because they all assume that they follow the normal system of TA in that its beneficial to gather as much resources as you can.
point me where it's stated that
AF wrote:What if we want a resource representing score where we want the value to be as small as possible?
the ai will look at the value and try to minimize it?, or if you want, you can just have the resource always be negative, this way an improvement delta is positive (approaching 0) and a loss is negative ( going deeper on negative side), this way the logic you assumed is still respected
Last edited by BrainDamage on 18 Nov 2008, 19:06, edited 1 time in total.
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Luarules <-> AI, part 1 of 0: resources

Post by lurker »

AF wrote:stuff
I think that should change to a happier tune once you read the documentation I spent half an hour on :-)
AF wrote:For example, we might have to look after citizens, and we may represent their alarm as a resource we want as little of as possible encase they revolt.
I never said it was a complete spec; what are your ideas to show that? One way could be to mark them as 'get as much as possible', 'get enough to use', 'avoid', etc.
Edit: Yeah, I like the idea of the AI-exposed resource being negative.
Last edited by lurker on 18 Nov 2008, 19:06, edited 1 time in total.
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Re: Luarules <-> AI, part 1 of 0: resources

Post by imbaczek »

Brain Damage wrote:
lurker wrote:         income = 1200;
        drain = 1100;
is separated income and drain even necessary when using false as separate state?
can't they just be tied togheter in a single delta value which is income - drain? or is there any case when you'd want to know them separated? don't get get summed anyway in the resource pool?
you can turn stuff on/off.
Post Reply

Return to “AI”