FLWL / aoe2-ai-module

Library to extend AI scripting capabilities in Age of Empires 2.
GNU Lesser General Public License v2.1
16 stars 6 forks source link

Functions #10

Open Overconfidence opened 3 years ago

Overconfidence commented 3 years ago

Hi, tried to figure out how to get the fact.CcPlayersBuildingCount(playerNumber=1) command working (built houses around the enemy tc), but I got a value of 0 as a result. In the unpack_result(result_list.results[NUMBER], fact.GoalResult).result command, I only havee to change the NUMBER value to get different results, or do I have to change other thing as well, depending on what I'm checking for (vills, military, etc.)?

Another thing that puzzles me is how to change the parameters of the action.UpGetFact function to check what the AI has. I tried to look at the code and figure out which parameters does what, and what attributes do the return values have, but it left me as confused as I was when I started.

FLWL commented 3 years ago

Hi, you also have to interpret the result as the correct type, in your case like: unpack_result(result_list.results[NUMBER], fact.CcPlayersBuildingCountResult).result. The name for the result class is just the name of the command + Result appended to the end.

To work with Up commands, classical AI scripting experience is useful. You can check airef: https://airef.github.io/commands/commands-index.html to read up on that. This module just makes those commands accessible. action.UpGetFact in the module is the same as up-get-fact there and so on. The parameter names are also quite similar, even more so in the new 0.2.0 version of the module for DE build 43210 that I released a few days ago.

Overconfidence commented 3 years ago

Hi, managed to figure out most of the things in the new 0.2.0 version, thank you. But there are 2 thing that I can't really understand, the first is the following bit of code: action.UpFindLocal(inGoalUnitId=510, inConstCount=10), action.UpGetSearchState(outGoalState=500), fact.Goal(inConstGoalId=500), If I understend the above code it "selects" up to 10 units which id is equal to the value stored in the inGoalUnitId 510. However when I tried to set the value in inGoalUnitId 510 to the id of champion, the fact.GoalResult didn't give back 10, even though the ai had many champions on the map. The second one is this part: fact.UpSearchObjectIdList(inConstSearchSource=1), action.UpSetTargetObject(inConstSearchSource=1, inConstIndex=0), fact.UpObjectData(inConstObjectData=1), I tried to figure out what they do (checked them on airef), but didn't understand what they accomplish. My other question is, can we give commands to the ai, such as build something specific, or command the selected units, or is it something that's yet to be implemented?

FLWL commented 3 years ago

Yes, I did some testing and could reproduce your results. Seems like you have to search for upgraded units by either their base ID (in your case 74, known as militiaman) or their line (in your case -296, known as militiaman-line, from https://airef.github.io/parameters/parameters-details.html#UnitId). I'll have to look into it further to see why.

fact.UpSearchObjectIdList(inConstSearchSource=1) is a custom fact added by the module, its not on airef. There is a brief description on the project's Wiki: https://github.com/FLWL/aoe2-ai-module/wiki/Documentation%23-Expert-Facts#protos.expert.fact.UpSearchObjectIdList. It returns a list of object map entity IDs that are in the search-local list (populated by UpFindLocal) specified by inConstSearchSource=1 (see https://airef.github.io/parameters/parameters-details.html#SearchSource).

action.UpSetTargetObject(inConstSearchSource=1, inConstIndex=0) sets the target object to the first object in the search-local list. Target object is internal to the game engine. This tells UpObjectData what object to operate on.

fact.UpObjectData(inConstObjectData=1) gets the object-data-type property of the current target object (see https://airef.github.io/parameters/parameters-details.html#ObjectData).

All facts and actions on the airef are available. For example you can build a house with action.Build(inConstBuildingId=70). For directly controlling units, you have to check out the DUC guides and construct the commands yourself (https://airef.github.io/duc/duc-index.html).

Overconfidence commented 3 years ago

Thank you for the explanation. Just a heads up, I think the new update broke the dll, whenever I try to start a new game with the dll injected I get a CDT (steam is offline).

FLWL commented 3 years ago

Yeah, it breaks due to hardcoded memory addresses in the aimodule/misc/Configuration.h file. I'll look at it soon and see if I can make the module find them dynamically so it wouldn't break with every update.

Overconfidence commented 3 years ago

Hi, reverted back the game to an earlier update, where the dll worked, to check out some commands. What I found is, that when I give the ai the command to build a building (without checking how much res it has) the game crashes. After that I tried to check for available res, but the ai didn't completed the command, even when it had enough res. Here is a little code checking for res: test = [fact.CanAffordBuilding(inConstBuildingId=70), fact.Goal(inConstGoalId=111)] result_list = expert_api.ExecuteCommandList(pack_commands(2, test))
if(unpack_result(result_list.results[1],fact.GoalResult).result > 0): cmdlist.append(action.Build(inConstBuildingId=70)) Is there a more straightforward way to give a build command to the ai where it can check if it can complete the command?

FLWL commented 3 years ago

fact.CanAffordBuilding returns the result directly by itself, there is no need for fact.Goal there. if(unpack_result(result_list.results[0], fact.CanAffordBuildingResult).result == True) would be the appropriate check.

That said, I have never had action.Build crash on me like that and it really shouldn't. In fact, the module actually makes a fact.CanBuildWithEscrow check internally before placing the action.Build command just in case. This seems like either a random crash (I've noticed a few, they're hard to debug), or a more general issue/mismatch between the module and the game. Hard to say. You could also try using the dev branch/release.

Overconfidence commented 3 years ago

If it's not to complecated, would it be possible to make the ai "afk" like it used to be, when you update the dll file?

FLWL commented 3 years ago

What do you mean by that? The closest I know you can get to an afking AI is to load a dummy AI .per file with 1 meaningless rule, but even then the built in gathering and exploring mechanisms in the game will make your units do stuff. It might be possible to avoid this by changing some strategic numbers. It has always been this way.

Overconfidence commented 3 years ago

Does it mean that I can't specify how much vills should gather which resources? Sorry for the late reply, university is a bit rough, and I also found other parts of my project to little bit put off the question of afk AI.

Overconfidence commented 3 years ago

Hi, I'm progressing nicely on my project, managed to get the ai to afk, but when I try to send the scout to explore, or vills to gather res, I get the following error messages: 1. test_cmdlist.append(action.UpSendScout(101, 0)) TypeError: init() takes 1 positional argument but 3 were given 2. test_cmdlist.append(action.UpRetaskGatherers(0, 0, 1)) TypeError: init() takes 1 positional argument but 4 were given

I tried to figure out what's the problem, and how to fix it by checking the functions on the airef website, but I didn't find a solution. Do you have any idea how can I fix it, or where should I look for a solution?