Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce AI deadlocks #284

Open
wants to merge 52 commits into
base: master
Choose a base branch
from
Open

Reduce AI deadlocks #284

wants to merge 52 commits into from

Conversation

Asdow
Copy link
Contributor

@Asdow Asdow commented Feb 11, 2024

Quite a bit of changes done, with mostly trying to fix the passive AI and reduce AI deadlocks. Actual AI behavior should be mostly the same as before.

Also some additional AI logging

Asdow added 30 commits August 16, 2023 23:07
Logging AI decisions shows that this conditional would constantly cancel AI actions during regular gameplay. A special case like this should not affect normal AI routines and I'd rather disable this for now to prevent it from masking other problems with AI decisions.
Clutters logs and slows down game less when logging is on.
!AimingGun(pSoldier) would always evaluate to true and there are no hits to CrowDecideAction in the entire solution even in commented out code
Originally placed in DecideAction(green/yellow/red/black) functions separately
Canceling current AI actions at the start of soldier's turn prevents a lot of ai deadlocks. The status RED & BLACK actions are supposed re-evaluate the situation every turn anyways
We can't do anything with negative action points either.
aiData.bRTPCombat is never initialized and is always 0 when valid values should be

#define RTP_COMBAT_AGGRESSIVE		1
#define RTP_COMBAT_CONSERVE			2
#define RTP_COMBAT_REFRAIN			3
It's already handled before a call to this function, and TurnBasedHandleNPCAI() is only called when pSoldier's action is AI_ACTION_NONE
Less clutter in the AI logs if, for example one is only interested in BLACK status decisions
Several actions would sometimes get stuck in a forever loop, where they would not be executed, since no proper path for executing the actions is found.

Originally TurnBasedHandleNPCAI() would only be called if aidata.bAction was AI_ACTION_NONE.
Now we'll call it if an action is not already in progress, and will be executed if the action is affordable.
Asdow added 21 commits February 4, 2024 16:10
Several actions tended to get stuck in an invalid state, where it was completed, but aiData.bActionInProgress was still TRUE resulting in an AI deadlock.

If such a situation is found, Actiondone is now called, preventing the deadlock
With aiData.bAction = AI_ACTION_NONE and aiData.bNextAction = AI_ACTION_END_TURN, the npc turn is correctly ended in the next call to TurnBasedHandleNPCAI()
Calling InternalGoAsFarAsPossibleTowards() with target's gridno means AI doesn't take into account eg. nearby friendlies resulting in them bunching up and  making a beeline straight at whoever they're trying to attack.
We'll first at least attempt to find a cover spot near said target, if it doesn't work, only then head straight at them.
when in water. If our current or last action was AI_ACTION_SEEK_OPPONENT.

The AI tends to flipflop between jumping into water, swimming a certain distance and then "panic" because they're in the water and then try to reach the closest land tile. Which is often right where they entered the water. Adding a bit of decision momentum with this change should help with that.
when in water. If our current or last action was AI_ACTION_SEEK_OPPONENT.

The AI tends to flipflop between jumping into water, swimming a certain distance and then "panic" because they're in the water and then try to reach the closest land tile. Which is often right where they entered the water. Adding a bit of decision momentum with this change should help with that.
Calling InternalGoAsFarAsPossibleTowards() with target's gridno means AI doesn't take into account eg. nearby friendlies resulting in them bunching up and  making a beeline straight at whoever they're trying to attack.
We'll first at least attempt to find a cover spot near said target, if it doesn't work, only then head straight at them.
Allow at least considering throwing smoke for cover even if pSoldier has used some AP from its initial amount.
Lot of actions are liable to deadlock if this is not done
Functionality for rendering pathfinding and cover values in tactical was behind defunct #ifdefs.
It's now compiled always, but only enabled if cheat level is BEDUG_CHEAT_LEVEL.
Unified rendering the debug info into one function, instead of several nearly identical ones.
Ctrl + Shift + Z cycles through the different debug modes.

Now it should be fairly easy to add more info modes like these two in the future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant