Preliminary handling for AI_FLAG_ASSUME_POWERFUL_STATUS, not actually yet called.

This commit is contained in:
surskitty 2025-07-10 23:38:08 -04:00
parent cb606cee6a
commit 3ee93c69ec
6 changed files with 114 additions and 1 deletions

View File

@ -147,6 +147,10 @@ AI has full knowledge of player moves, abilities, and hold items, and can use th
## `AI_FLAG_ASSUME_STAB`
A significantly more restricted version of `AI_FLAG_OMNISCIENT`, the AI only knows the player's STAB moves, as their existence would be reasonable to assume in almost any case.
## `AI_FLAG_ASSUME_POWERFUL_STATUS`
A more restricted version of `AI_FLAG_OMNISCIENT`. The AI has a _chance_ to know if the player has certain iconic status moves, plus also Fake Out and fixed percentage moves like Super Fang.
## `AI_FLAG_SMART_MON_CHOICES`
Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled.

View File

@ -61,6 +61,8 @@ bool32 IsAiVsAiBattle(void);
bool32 BattlerHasAi(u32 battlerId);
bool32 IsAiBattlerAware(u32 battlerId);
bool32 IsAiBattlerAssumingStab(void);
bool32 IsAiBattlerAssumingPowerfulStatus(void);
bool32 ShouldRecordStatusMove(u32 move);
void ClearBattlerMoveHistory(u32 battlerId);
void RecordLastUsedMoveBy(u32 battlerId, u32 move);
void RecordAllMoves(u32 battler);

View File

@ -76,6 +76,11 @@
// AI_FLAG_ASSUME_STAB settings
#define ASSUME_STAB_SEES_ABILITY FALSE // Flag also gives omniscience for player's ability. Can use AI_FLAG_WEIGH_ABILITY_PREDICTION instead for smarter prediction without omniscience.
// AI_FLAG_ASSUME_POWERFUL_STATUS settings
#define ASSUME_POWERFUL_STATUS_HIGH_ODDS 95 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore
#define ASSUME_POWERFUL_STATUS_MEDIUM_ODDS 75 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect
#define ASSUME_POWERFUL_STATUS_LOW_ODDS 50 // Chance for AI to see niche moves a pokemon may have but probably won't, like Trick Room or Speed Swap
// AI_FLAG_SMART_SWITCHING settings
#define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise

View File

@ -34,8 +34,9 @@
#define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT
#define AI_FLAG_SMART_TERA (1 << 27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available).
#define AI_FLAG_ASSUME_STAB (1 << 28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT.
#define AI_FLAG_ASSUME_POWERFUL_STATUS (1 << 29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT.
#define AI_FLAG_COUNT 29
#define AI_FLAG_COUNT 30
// Flags at and after 32 need different formatting, as in
// #define AI_FLAG_PLACEHOLDER ((u64)1 << 32)

View File

@ -544,6 +544,17 @@ void RecordMovesBasedOnStab(u32 battler)
}
}
void RecordPowerfulStatusMoves(u32 battler)
{
u32 i;
for (i = 0; i < MAX_MON_MOVES; i++)
{
u32 playerMove = gBattleMons[battler].moves[i];
if (ShouldRecordStatusMove(playerMove))
RecordKnownMove(battler, playerMove);
}
}
void SetBattlerAiData(u32 battler, struct AiLogicData *aiData)
{
u32 ability, holdEffect;

View File

@ -249,6 +249,96 @@ void SaveBattlerData(u32 battlerId)
gAiThinkingStruct->saved[battlerId].types[1] = gBattleMons[battlerId].types[1];
}
bool32 ShouldRecordStatusMove(u32 move)
{
u32 rand = Random() % 100;
if (rand >= ASSUME_POWERFUL_STATUS_HIGH_ODDS)
return FALSE;
switch (GetMoveEffect(move))
{
// variable odds by additional effect
case EFFECT_NON_VOLATILE_STATUS:
if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP)
return TRUE;
else if (rand < ASSUME_POWERFUL_STATUS_MEDIUM_ODDS)
return TRUE;
break;
// High odds
case EFFECT_AURORA_VEIL:
case EFFECT_CHILLY_RECEPTION:
case EFFECT_CONVERSION:
case EFFECT_FIRST_TURN_ONLY:
case EFFECT_FOLLOW_ME:
case EFFECT_INSTRUCT:
case EFFECT_JUNGLE_HEALING:
case EFFECT_REVIVAL_BLESSING:
case EFFECT_SHED_TAIL:
case EFFECT_STICKY_WEB:
return TRUE;
// Medium odds
case EFFECT_AFTER_YOU:
case EFFECT_DEFOG:
case EFFECT_ENCORE:
case EFFECT_HAZE:
case EFFECT_HEAL_BELL:
case EFFECT_HEALING_WISH:
case EFFECT_LIFE_DEW:
case EFFECT_MEMENTO:
case EFFECT_PARTING_SHOT:
case EFFECT_PROTECT:
case EFFECT_RESTORE_HP:
case EFFECT_ROAR:
case EFFECT_TAUNT:
case EFFECT_TAILWIND:
case EFFECT_TELEPORT:
case EFFECT_TRICK:
// defoggables / screens and hazards
case EFFECT_LIGHT_SCREEN:
case EFFECT_REFLECT:
case EFFECT_SPIKES:
case EFFECT_STEALTH_ROCK:
case EFFECT_TOXIC_SPIKES:
// field status
case EFFECT_HAIL:
case EFFECT_RAIN_DANCE:
case EFFECT_SANDSTORM:
case EFFECT_SNOWSCAPE:
case EFFECT_SUNNY_DAY:
case EFFECT_TRICK_ROOM:
case EFFECT_ELECTRIC_TERRAIN:
case EFFECT_GRASSY_TERRAIN:
case EFFECT_MISTY_TERRAIN:
case EFFECT_PSYCHIC_TERRAIN:
if (rand < ASSUME_POWERFUL_STATUS_MEDIUM_ODDS)
return TRUE;
break;
// Low odds
case EFFECT_COURT_CHANGE:
case EFFECT_DOODLE:
case EFFECT_ENTRAINMENT:
case EFFECT_FIXED_PERCENT_DAMAGE:
case EFFECT_GASTRO_ACID:
case EFFECT_GUARD_SPLIT:
case EFFECT_IMPRISON:
case EFFECT_PERISH_SONG:
case EFFECT_POWER_SPLIT:
case EFFECT_QUASH:
case EFFECT_ROLE_PLAY:
case EFFECT_SKILL_SWAP:
case EFFECT_SPEED_SWAP:
case EFFECT_WORRY_SEED:
if (rand < ASSUME_POWERFUL_STATUS_LOW_ODDS)
return TRUE;
break;
default:
break;
}
return FALSE;
}
static bool32 ShouldFailForIllusion(u32 illusionSpecies, u32 battlerId)
{
u32 i, j;