Question About AI_searchRange

NP300

Prince
Joined
May 18, 2004
Messages
402
Location
North America
Hi all,

As has been pointed out in this thread, the AI cheats and can see far beyond what it is supposed to be able to see.

In the case of naval units, this cheating has long been very noticeable to me and breaks the illusion of an AI that plays by the same rules. It becomes annoying when the AI always seems to be able to find your ships, and always just happens to head right to them. In the case of land units, I have not found it to be very noticeable.

To correct this, I have been experimenting with a change in my Random Invisibility modcomp, which uses BetterBTSAI. I made the AI_searchRange to be based on visibilityRange(), as opposed to baseMoves().

Here is my code for the naval unit AI_searchRange:

Code:
return (iRange * visibilityRange());

And the original code:

Code:
return (iRange * baseMoves());

It seems to work fairly well, and the illusion is no longer broken. Now my question is if this may be having any unintended consequences in other places. I wonder if this would prevent an AI sea unit from attacking a unit that the AI Civ can see, but which is outside of the particular unit's visibility range. For instance let's say there is a hostile French transport right by an English city; and let's further say the English have a destroyer 7 tiles away. The English can see the French transport, but this transport is outside of the destroyer's visibility range. Will my change in the code prevent the destroyer from attacking? Will it make any difference?

I looked in CvUnitAI.cpp and it appears that the settings for iRange range from 1 to 5. 3-5 seem to only be used for things like escorting settlers and evacuations. But iRange=2 does seem to be used to make attack decisions.

So for those who know the AI code well: Is my change having some significant unintended consequences? Thanks.
 
I think you assessment is correct. The unit will not look far enough to attack visible units that are outside that particular unit's visibility range. Actually it goes a bit farther than that... no units that base their search ranges on this function would look any farther than their visibility range for a number of different activities such as pillaging, founding cities, etc. I think it would be better to have it simply check if the tile is visible or not in the loop relating to this behavior. But also, as someone pointed out in the thread you posted, the AI has no memory. So if I see a ship sail into view and then sail out the next turn, I know roughly where it should be. What might be even better is to give the AI a probability of going in the correct direction if the tile is NOT visible.
 
I'd rather have ships get a visibility range (on sea squares) boost equal to their remaining movement range, plus their 'base' sight range, restricted to squares they can move to if it is beyond the 'base' sight range. (and this only applies to fleets that aren't in port)

This places the AI and the human on a level playing field, without making the AI hopeless at tracking down ships at sea.

As a side benefit, fleets out of port patrolling the edges of your continent could see incoming fleets before they unload troops.
 
I think it would be better to have it simply check if the tile is visible or not in the loop relating to this behavior.

I think that is a better way but I'm not sure how to check for that.

But also, as someone pointed out in the thread you posted, the AI has no memory. So if I see a ship sail into view and then sail out the next turn, I know roughly where it should be. What might be even better is to give the AI a probability of going in the correct direction if the tile is NOT visible.

I think that is pretty easy to do. You could add a random number to extend the iRange by 1, say half the time. The end result would be indistinguishable to the human player—it would appear as if the AI can track him down some of the time, and fails the other half.

I thought of keeping iVisibilityRange, but adding a random factor to let the AI see farther some of the time. That way the illusion of a fog of war for the AI could be preserved without letting the AI hunt you down 100% of the time as if it knew where all the units are.
 
This places the AI and the human on a level playing field, without making the AI hopeless at tracking down ships at sea.

The interesting thing is that I have played a game limiting the naval AI_searchRange, and I wouldn't say the AI was hopeless at sea. And it no longer felt as if the AI was omniscient.
 
I have to agree this is one area of the game where the AI's cheats really do break the illusion. In particular, their destroyers are going to seek and destroy everyone one of your privateers with frightening speed. If a privateer is 8 squares away from a destroyer there should be very little chance the destroyer can see it.

I worry that the change suggested in the OP will have unintended consequences that are more far reaching than has been indicated so far. Could it make it too easy to run away from the AI?
 
You could add a random number to extend the iRange by 1, say half the time.

For a temporary fix, I would set it to min( baseMoves() , visibilityRange()*2 ). If a human sees a ship leaving the field of vision of one of their ships, they can move a ship to the last known location, see the ship, and then move to attack that ship. The above code allows the AI to do the same thing.

Long-term, the AI should be given a better memory.
 
For a temporary fix, I would set it to min( baseMoves() , visibilityRange()*2 ). If a human sees a ship leaving the field of vision of one of their ships, they can move a ship to the last known location, see the ship, and then move to attack that ship. The above code allows the AI to do the same thing.
Again, the problem is that this function is tied into so much other stuff that is not dependent on visibility, like founding cities. If you were to do this, the AI settlers would only consider tiles that are twice as far as this current unit's visibility when deciding where to build a city.

However, one alternative is to go to each function that calls this search range function that you think should be limited by visibility range, and modify the code from:

iSearchRange = AI_searchRange(...);

to:

iSearchRange = std::min(AI_searchRange(...), (visibilityRange() * 2));

Long-term, the AI should be given a better memory.
Any memory would be good. Right now, the AI retains no information about what the map used to look like. They have a simple memory for diplomacy but virtually nothing else.

To All:

One of the other things we should ask ourselves is: Is this a cheat that really does the AI any good? I mean, doesn't it seem likely that if we give the AI a narrower set of things to focus on (like the enemy units it can see rather than the ones it can't) that it should perform better?
 
Again, the problem is that this function is tied into so much other stuff that is not dependent on visibility, like founding cities. If you were to do this, the AI settlers would only consider tiles that are twice as far as this current unit's visibility when deciding where to build a city.

In the mod I have been experimenting with, I only implented that change for naval units. The land units were unaffected. I thought it might cripple the land AI's war abilities too much. And besides, this cheating is not so noticeable on land. It is mostly noticeable at sea because of the great disparity between the visibility range and the base moves (ie: a Destroyer can see 3 tiles away at most, but it can have as many as 10 moves). I think the only case I find it noticeable with land AI is with gunships; they will target a small and poorly defended city way into your borders, when in some cases they might be better off assisting the main AI assault on your border city.

I did experiment with using a random factor for land unit AI_searchRange, but it didn't produce a very noticeable difference in AI behavior.

However, one alternative is to go to each function that calls this search range function that you think should be limited by visibility range, and modify the code from:

I had a look at the code to see if it would be possible to put a check to see if the tile is visible to the AI. From looking at it, it seems the change would have to be changed in many places. Because it seems that the AI uses iSearchRange, and then it loops through every single tile in the range. And the AI_searchRange is called many times; so modifications would be necessary in many places.

To All:

One of the other things we should ask ourselves is: Is this a cheat that really does the AI any good? I mean, doesn't it seem likely that if we give the AI a narrower set of things to focus on (like the enemy units it can see rather than the ones it can't) that it should perform better?

This is a very good thought. We could let the AI_searchRange see all over the map. And then the AI units might end up potentially targetting enemy units on the other side of the globe.

For land units, though, I think that allowing the AI to cheat a little bit in the AI_searchRange can enhance the illusion of intelligence. That way AI units will target cities that they can't see, but which a human would know to target; or target units that a human may not be able to see, but would reasonably surmise their location. I think this kind of cheating becomes a problem when there is a large disparity between the number of moves and the visibility range, as is the case with ships, and to more limited extent with gunships.
 
Yes, as long as you distinguish between naval units and non-naval units in the AI_searchRange function and have it return different values for each, you can make the changes there. Good point.
 
Back
Top Bottom