Fair point. There's a number of people there that might be worth contacting.
Announcement
Collapse
No announcement yet.
AI : Army Movement
Collapse
X
-
I found this in world.h
does this help anything?Code:void CalcChokePoints();
Comment
-
Well this is the declaration the function that calculates the choke points, at least its name suggests this. To check wheather the choke points are calculated correctly, we have to check the implementation in the according *.cpp source file. Actual what I had in my was to add a field to strategy.txt that like the good settle bonus that contains a bonus for settling at choke points.Originally posted by E
I found this in world.h
does this help anything?Code:void CalcChokePoints();
The task to do here are to add that flag to strategies.txt in a manner such that it has a default value so that it hasn't to be added to strategies.txt and the default value shouldn't overwrite explicitly set values when strategies are merged.
Then you have to find the code that uses this settle good bonus and you have to add in the same way like this good bonus the choke point settle bonus.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
-
I cheked that file quickly (gs/world/WrldCont.cpp).
The computation seems to be done on neighbours only. There are several passes, but only neighbours are cheked. (I don't know what values you get when there is an isthmus.)
The result is a map of (0,1) for land and water. Thus it's binary, either you are a choke point or not. There's no way of knowing whether it's a 2-direction or 3-direction chokepoint for instance, and the land masses aren't considered because the algorithm only checks neighbours.
It would be simple to change that by removing the chokepoints from the map, computing the size of the landmasses separated by the landpoints, and giving a weight to the chokepoint as a function of that...
But then I'm not going to do it so I'd better keep lurking.
Good luck to you all.Clash of Civilization team member
(a civ-like game whose goal is low micromanagement and good AI)
web site http://clash.apolyton.net/frame/index.shtml and forum here on apolyton)
Comment
-
At least it seems to be not a problem in respect to backwards compatibility, as it looks like that choke points are recalculated after every reload, at least the stuff is not explicitly stored, so we can use more numbers then 256 to measure their quality, but even with 256 quality classes we should be able to distinguish them.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
-
-
sekel, I hope you stick to it, a lot of people have shown interest but unfortunately few have contributed
Comment
-
OK, I nailed down the problem that caused these massive slow downs. It is this operator> from Squad_Strength:
For now I just disabled Calvitix code, however I think that neither the original nor Calvitix' code are right. The original code evaluates this greater variable and returns it finally. In the middle it evaluates some other variables that aren't used. Calvitix just sets this greater variable afterwards it has been evaluated to false and evaluates it again. He also ignores the other greater variables evaluated before.Code:bool Squad_Strength::operator> (const Squad_Strength &squad_strength) const { bool greater = (m_attack_str > squad_strength.m_attack_str) || (m_defense_str > squad_strength.m_defense_str) || (m_transport > squad_strength.m_transport); bool greater_defenders = (m_defenders > squad_strength.m_defenders ); bool greater_ranged = (m_ranged > squad_strength.m_ranged); bool greater_ranged_str = (m_ranged_str > squad_strength.m_ranged_str ); bool greater_value = (m_value > squad_strength.m_value); bool greater_agents = (m_agent_count > squad_strength.m_agent_count); #if 0 && !defined (ACTIVISION_ORIGINAL) // Calvitix // Removed by Martin Gühmann // Causes a severe slow down on maps with more than one continent. // Needs therefore be reconsidered. That is also true for the // original code, only the greater variable is used. greater = false; // Attack difference sint16 attack_cpr = (m_attack_str - squad_strength.m_attack_str); // Defense difference sint16 defense_cpr = (m_defense_str - squad_strength.m_defense_str); // ranged difference sint16 ranged_cpr = (m_ranged_str - squad_strength.m_ranged_str); // value difference sint16 value_cpr = (m_value - squad_strength.m_value); sint16 ranged_nb = (m_ranged - squad_strength.m_ranged); sint16 defenders_nb = (m_defenders - squad_strength.m_defenders); sint16 transport_nb = (m_transport - squad_strength.m_transport); // the addition of all differences has to be greater than 0 // it is certainly better than only testing attack or defense // but can be improved (for exemple, by applying a ratio on the greater score if ((attack_cpr + defense_cpr + ranged_cpr + value_cpr) > 0) greater = true; // To be compatible with the original operator, test the // nb of transport too if (m_transport > 0 && transport_nb > 0) greater = true; // test the nb of agent too if (m_agent_count > 0 && squad_strength.m_agent_count > 0) { greater = greater || greater_agents; //when only agent count is as criterion : (for special units for example) if (m_attack_str + m_defense_str + m_ranged_str + m_value == 0) { greater = greater_agents; } } #endif return greater; }
However there seems to be something wrong with this, maybe it lies inside of this operator or the problem is finally caused outside of the operator.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
-
Did you try replacing the end by
if ((attack_cpr + defense_cpr + ranged_cpr + value_cpr) > 0)
return greater;
// To be compatible with the original operator, test the
// nb of transport too
if (m_transport > 0 && transport_nb > 0)
return true;
// test the nb of agent too
if (m_agent_count > 0 && squad_strength.m_agent_count > 0)
{
//when only agent count is as criterion : (for special units for example)
if (m_attack_str + m_defense_str + m_ranged_str + m_value == 0)
{
return greater_agents;
}
}
return false; // or 0 or FALSE I don't know the relevant defines
?
The logic is exactly the same but you don't do useless computations. That and putting the original code in a #ifdef/#else so you don't use the other useless variables?
(back to lurker mode).Clash of Civilization team member
(a civ-like game whose goal is low micromanagement and good AI)
web site http://clash.apolyton.net/frame/index.shtml and forum here on apolyton)
Comment
-
Well I came up with this code, it is a cleaner version. And it seems to help the AI. However it still causes a slow down that spontaniously disappeared. It is less severe but it is still there.
Otherwise my test game ran fine, the AI filled the whole map with cities, I saw sea activity, maybe some more coordinated activity for oversea invasion would be good. But maybe the AI should first conquer its neighbors. Unfortunatly I cannot continue the game the game had to crash during saving the autosave, that left me with a autosavegame of 9kb and that is definitely to small for a save game, and I have no idea what happened as I don't have a crash.txt of that event. ANother thing I saw is that the AI doesn't attack cities without defenders.Code:bool Squad_Strength::operator> (const Squad_Strength &squad_strength) const { // To be compatible with the original operator, test the // nb of transport too sint16 transport_nb = (m_transport - squad_strength.m_transport); if(m_transport > 0 && transport_nb > 0) return true; // Attack difference sint16 attack_cpr = (m_attack_str - squad_strength.m_attack_str); // Defense difference sint16 defense_cpr = (m_defense_str - squad_strength.m_defense_str); // ranged difference sint16 ranged_cpr = (m_ranged_str - squad_strength.m_ranged_str); // value difference sint16 value_cpr = (m_value - squad_strength.m_value); // the addition of all differences has to be greater than 0 // it is certainly better than only testing attack or defense // but can be improved (for exemple, by applying a ratio on the greater score if((attack_cpr + defense_cpr + ranged_cpr + value_cpr) > 0) return true; // test the nb of agent too if(m_agent_count > 0 && squad_strength.m_agent_count > 0){ //when only agent count is as criterion : (for special units for example) if (m_attack_str + m_defense_str + m_ranged_str + m_value == 0){ return (m_agent_count > squad_strength.m_agent_count); } } return false; }
The difference is that false is of type bool, it has the same size as a char of 1 byte IIRC. BOOL is a typedef of int and that is bigger bool. BOOL needs 4 byte, and FALSE is just 0 also an int. I know you can also see it as a short.Originally posted by LDiCesare
return false; // or 0 or FALSE I don't know the relevant defines
The main difference is the size, and the operator should return a bool therefore false is more appropiate. However you can also use FALSE that is then casted to false, but using false directly is cleaner code.
Well I don't thing that the logic is the same, in your version and also in my version, once the transport thing is true, the operator returns true, in Calvitix version the return value could still change, however I think that our logic is the better logic as it restores the compatibility with the transport stuff, Calvitix version doesn't do this. I think that the slowdown is caused by the outcome of the operator not by the number of steps it does.Originally posted by LDiCesare
The logic is exactly the same but you don't do useless computations.
For the original version I can clearly say that this could happen:
(A > B) == true
(B > A) == true
And instance if attack strength of A is bigger than of B, and if defence strength B is bigger than of A. That's a kind of logic that worries me. I didn't check whether this could happen to the new version as well, but I doubt that this should be possible.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
-
Well after some more testing it seems to be that the problem even with my version of the operator occurs. It seems to be that it is a problem with missing transports, and unreachable positions. For now I would consider this code as expreimental.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
-
OK here is another version of that operator, it should now be correct and assymetrical, well except for the case A == B, then it should return false as well as for B == A.
I modified the final squad size test, so that it only returns true if the size of the first squad is bigger than the size of the other squad, if the values of both are 0. That means two squads are equal in strength if their values are equal irrespective of their size. Or are equal if these values are all in both squads 0 and their size is equal.Code:bool Squad_Strength::operator> (const Squad_Strength &squad_strength) const { // To be compatible with the original operator, test the // nb of transport too sint16 transport_nb = (m_transport - squad_strength.m_transport); if(m_transport > 0 && transport_nb > 0) return true; // Attack difference sint16 attack_cpr = (m_attack_str - squad_strength.m_attack_str); // Defense difference sint16 defense_cpr = (m_defense_str - squad_strength.m_defense_str); // ranged difference sint16 ranged_cpr = (m_ranged_str - squad_strength.m_ranged_str); // value difference sint16 value_cpr = (m_value - squad_strength.m_value); // The addition of all differences has to be greater than 0 // it is certainly better than only testing attack or defense // but can be improved (for exemple, by applying a ratio on the greater score if((attack_cpr + defense_cpr + ranged_cpr + value_cpr) > 0) return true; // Test the nb of agent too if(m_agent_count > 0 && squad_strength.m_agent_count > 0){ //If only agent count is a criterion : (for special units for example) if(m_attack_str + m_defense_str + m_ranged_str + m_value == 0 && squad_strength.m_attack_str + squad_strength.m_defense_str + squad_strength.m_ranged_str + squad_strength.m_value == 0 ){ return (m_agent_count > squad_strength.m_agent_count); } } return false; } #endif
I tested this operator against the original operator in a late game. The AI turn times seem to be equal, however this doesn't indicate that the sorting results during the game create the same length of AI turn tedium.
However I don't think that this operator is the real problem of the AI slowness. I think it has still to do something with the AI transport capacity. As AIs without the need of transporting a lot of units are much faster and aren't a problem.
Well any comments about this version of the operator. Seems it be fine. Is it error free, has it the claimed assymetry?
Some other notes about the AI, if an AI has no idea what it should do with its units it puts them on their roads, you see a lot of units sleeping on their roads. Of course that are all single units and the tiles aren't filled to the tile limit of 12 units. An easy goal for an attacker and something that is another possible AI turn time slow down.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
-
What about this:
Obviously transport squads should be always bigger, so only if the transport strength of both squads is equal, then the values should be tested.Code:bool Squad_Strength::operator> (const Squad_Strength &squad_strength) const { // Transport squads should always be always bigger: if(m_transport > squad_strength.m_transport) return true; else if(m_transport < squad_strength.m_transport) return false; // Attack difference sint16 attack_cpr = (m_attack_str - squad_strength.m_attack_str); // Defense difference sint16 defense_cpr = (m_defense_str - squad_strength.m_defense_str); // ranged difference sint16 ranged_cpr = (m_ranged_str - squad_strength.m_ranged_str); // value difference sint16 value_cpr = (m_value - squad_strength.m_value); // The addition of all differences has to be greater than 0 // it is certainly better than only testing attack or defense // but can be improved (for exemple, by applying a ratio on the greater score if((attack_cpr + defense_cpr + ranged_cpr + value_cpr) > 0) return true; // Test the nb of agent too if(m_agent_count > 0 && squad_strength.m_agent_count > 0){ //If only agent count is a criterion : (for special units for example) if(m_attack_str + m_defense_str + m_ranged_str + m_value == 0 && squad_strength.m_attack_str + squad_strength.m_defense_str + squad_strength.m_ranged_str + squad_strength.m_value == 0 ){ return (m_agent_count > squad_strength.m_agent_count); } } return false; }
By the way I didn't understand for what this nb_transport variable is and why Calvitix checks whether m_transport > 0 and transport_nb > 0, the first check should be included in the second one.
-MartinCiv2 military advisor: "No complaints, Sir!"
Comment
Comment