Plan for enemy AI improvements
Right now, enemy AI is fairly crude. Each enemy can have three possible states:
- Normal
- Low Health (under 20%) (AKA "Desperation")
- Enemy is alone
"Alone" overrides "Desperation". Each of these states has five attack slots which can be selected from randomly. If the enemy is in a state which has no attacks, it falls back to the "Normal" (or Desperation) rather than doing nothing.
More advanced AI can currently only be simulated by using elemental spawning and invisible untargetable enemies
The Plan[edit]
Make additional AI states.
- Default (Replace current "Normal" AI set)
- First attack
- Never been attacked (need a "non-hostile" attack bit for cure spells)
- Self stat checks
- Stat X is < Y% (Replace current "Desperation" AI set)
- Stat X is > Y%
- Stat X is < Y
- Stat X is > Y
- Other stat checks
- any ally's stat X is < Y%
- any ally's stat X is > Y%
- any foe's stat X is < Y%
- any foe's stat X is > Y%
- Who-is-present checks
- Formation contains < X allies (Replace current "Alone" AI set)
- Formation contains > X allies
- Formation contains < X foes
- Formation contains > X foes
- Specific hero X is present
- Specific enemy X is present
- Specific hero X is not present
- Specific enemy X is not present
- Global state checks
- Tag X is ON
- Tag X is OFF
- global variable X < Y
- global variable X > Y
- Battler state bitset checks
- Battler State is ON
- Battler State is OFF
- Battlescript returns true (only after battlescripting is implemented)
All of these except "Default" should be optional. The user should be able to arrange them in any priority, and to use more than one of a type (for example, several different stat-is-less-than AI sets for one enemy) Perhaps an enemy could have 10 or 20 AI slots, and the author could just select an "AI type" for each slot.
Each AI slot will point to an attack list. The attack list should be at least 5 attacks long, but maybe it could be longer. I think it makes sense to store attack lists in a separate file. All current attack lists can be auto-converted and given names like "Slime Normal" "Slime Desperation" and "Slime Alone" when updating old games.
Attack lists should have:
- A text name (not displayed in game, just for the editor)
- A list of attacks
- There should be an option to make a "Do nothing" entry that causes the enemy to waste a turn rather than falling back on another AI state
- A list type:
- Random (Same as the current lists)
- Sequential (use first attack first, second attack second, loop at the end)
Counterattacks[edit]
A simple implementation of enemy counterattacking is already in place. Adding all the features suggested here should probably be preceded by converting the enemy data into a RELOAD based format.
All the above applies to attacks that the enemy may choose to do when its turn comes. We should also implement counterattacks that happen instantly in response to being attacked.
Counterattacks should have a condition that determines whether or not they are triggered:
- Hit by any attack
- Hit by attack of element X (done)
- Hit by non-elemental attack
- Hit by an attack that damages stat X (done)
- Missed by an attack
- Harmed by poison
Counterattacks should be able to check a stat to see whether or not they should happen. The "Counter" stat would be the default for these, but since this feature is optional, this would not break any existing games
- Random using stat as a percent
- Random using a fixed percent
There should also be some counterattack bitsets like:
- Ignore own attacks
- Ignore ally attacks
- Ignore foe attacks (hero attacks)
- Ignore non-hostile attacks (see non-hostile attack bitset mentioned above)
- Ignore hostile attacks (see non-hostile attack bitset mentioned above)
- Ignore killing attacks
- Ignore non-killing attacks
note1[edit]
Note that counterattacks triggered by killing attacks are a little tricky, since that means the counterattacker must remain alive just long enough so that their stats can be used in the attack calculations
note2[edit]
Also note that a chain attack with several hits should only trigger ONE counterattack, immediately after the entire chain completes, even if the counterattack was triggered by an earlier part of the chain. If two different counterattacks on one enemy are triggered by a single chain, maybe it should just use the most recent one? probably a bad idea.
Misc.[edit]
There is currently a bitset that causes an enemy to be Ignored for "Alone" AI. It would be nice to add an additional bitset "Always count self when checking for Aloneness" that could override it. This would require "Alone" checks to be aware of which enemy is asking if they are alone.