Improve enemy move selection AI
parent
ca778e07d5
commit
012158e7ff
|
@ -1297,9 +1297,38 @@ export class StatChangeAttr extends MoveEffectAttr {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||||
// TODO: Add awareness of level limits
|
let ret = 0;
|
||||||
const levels = this.getLevels(user);
|
let moveLevels = this.getLevels(user);
|
||||||
return (levels * 4) + (levels > 0 ? -2 : 2);
|
for (let stat of this.stats) {
|
||||||
|
let levels = moveLevels;
|
||||||
|
if (levels > 0)
|
||||||
|
levels = Math.min(target.summonData.battleStats[stat] + levels, 6) - target.summonData.battleStats[stat];
|
||||||
|
else
|
||||||
|
levels = Math.max(target.summonData.battleStats[stat] + levels, -6) - target.summonData.battleStats[stat];
|
||||||
|
let noEffect = false;
|
||||||
|
switch (stat) {
|
||||||
|
case BattleStat.ATK:
|
||||||
|
if (this.selfTarget)
|
||||||
|
noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL);
|
||||||
|
break;
|
||||||
|
case BattleStat.DEF:
|
||||||
|
if (!this.selfTarget)
|
||||||
|
noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL);
|
||||||
|
break;
|
||||||
|
case BattleStat.SPATK:
|
||||||
|
if (this.selfTarget)
|
||||||
|
noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL);
|
||||||
|
break;
|
||||||
|
case BattleStat.SPDEF:
|
||||||
|
if (!this.selfTarget)
|
||||||
|
noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (noEffect)
|
||||||
|
continue;
|
||||||
|
ret += (levels * 4) + (levels > 0 ? -2 : 2);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1325,7 +1354,7 @@ export class HalfHpStatMaxAttr extends StatChangeAttr {
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
||||||
return new Promise<boolean>(resolve => {
|
return new Promise<boolean>(resolve => {
|
||||||
const damage = user.damage(Math.floor(user.getMaxHp() / 2), true);
|
const damage = user.damageAndUpdate(Math.floor(user.getMaxHp() / 2), HitResult.OTHER, false, true);
|
||||||
if (damage)
|
if (damage)
|
||||||
user.scene.damageNumberHandler.add(user, damage);
|
user.scene.damageNumberHandler.add(user, damage);
|
||||||
user.updateInfo().then(() => {
|
user.updateInfo().then(() => {
|
||||||
|
@ -1339,6 +1368,8 @@ export class HalfHpStatMaxAttr extends StatChangeAttr {
|
||||||
getCondition(): MoveConditionFunc {
|
getCondition(): MoveConditionFunc {
|
||||||
return (user, target, move) => user.getHpRatio() > 0.5 && user.summonData.battleStats[this.stats[0]] < 6;
|
return (user, target, move) => user.getHpRatio() > 0.5 && user.summonData.battleStats[this.stats[0]] < 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add benefit score that considers HP cut
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CutHpStatBoostAttr extends StatChangeAttr {
|
export class CutHpStatBoostAttr extends StatChangeAttr {
|
||||||
|
|
|
@ -2363,7 +2363,7 @@ export class EnemyPokemon extends Pokemon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.aiType = AiType.SMART_RANDOM;
|
this.aiType = boss || this.hasTrainer() ? AiType.SMART : AiType.SMART_RANDOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
initBattleInfo(): void {
|
initBattleInfo(): void {
|
||||||
|
@ -2461,17 +2461,21 @@ export class EnemyPokemon extends Pokemon {
|
||||||
for (let mt of moveTargets[move.id]) {
|
for (let mt of moveTargets[move.id]) {
|
||||||
const target = this.scene.getField()[mt];
|
const target = this.scene.getField()[mt];
|
||||||
let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1);
|
let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1);
|
||||||
if (move instanceof AttackMove) {
|
if (move.name.endsWith(' (N)'))
|
||||||
|
targetScore = -20;
|
||||||
|
else if (move instanceof AttackMove) {
|
||||||
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove);
|
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove);
|
||||||
if (target.isPlayer() !== this.isPlayer()) {
|
if (target.isPlayer() !== this.isPlayer()) {
|
||||||
targetScore *= effectiveness;
|
targetScore *= effectiveness;
|
||||||
if (this.isOfType(moveType))
|
if (this.isOfType(moveType))
|
||||||
targetScore *= 1.5;
|
targetScore *= 1.5;
|
||||||
} else {
|
} else if (effectiveness) {
|
||||||
targetScore /= effectiveness;
|
targetScore /= effectiveness;
|
||||||
if (this.isOfType(moveType))
|
if (this.isOfType(moveType))
|
||||||
targetScore /= 1.5;
|
targetScore /= 1.5;
|
||||||
}
|
}
|
||||||
|
if (!targetScore)
|
||||||
|
targetScore = -20;
|
||||||
}
|
}
|
||||||
targetScores.push(targetScore);
|
targetScores.push(targetScore);
|
||||||
}
|
}
|
||||||
|
@ -2494,6 +2498,10 @@ export class EnemyPokemon extends Pokemon {
|
||||||
if (this.aiType === AiType.SMART_RANDOM) {
|
if (this.aiType === AiType.SMART_RANDOM) {
|
||||||
while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5)
|
while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5)
|
||||||
r++;
|
r++;
|
||||||
|
} else if (this.aiType === AiType.SMART) {
|
||||||
|
while (r < sortedMovePool.length - 1 && (moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) >= 0
|
||||||
|
&& this.scene.randBattleSeedInt(100) < Math.round((moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) * 50))
|
||||||
|
r++;
|
||||||
}
|
}
|
||||||
console.log(movePool.map(m => m.getName()), moveScores, r, sortedMovePool.map(m => m.getName()));
|
console.log(movePool.map(m => m.getName()), moveScores, r, sortedMovePool.map(m => m.getName()));
|
||||||
return { move: sortedMovePool[r].moveId, targets: moveTargets[sortedMovePool[r].moveId] };
|
return { move: sortedMovePool[r].moveId, targets: moveTargets[sortedMovePool[r].moveId] };
|
||||||
|
|
Loading…
Reference in New Issue