- Defensive damage assignment for Banding and Defensive Formation

This commit is contained in:
Agetian
2023-07-02 18:46:35 +03:00
parent 7c2e3d2a47
commit 3eb1f70351
2 changed files with 38 additions and 28 deletions

View File

@@ -2023,6 +2023,8 @@ public class ComputerUtilCombat {
* distributeAIDamage. * distributeAIDamage.
* </p> * </p>
* *
* @param self
* a {@link forge.game.player.Player} object.
* @param attacker * @param attacker
* a {@link forge.game.card.Card} object. * a {@link forge.game.card.Card} object.
* @param block * @param block
@@ -2031,16 +2033,18 @@ public class ComputerUtilCombat {
* @param defender * @param defender
* @param overrideOrder overriding combatant order * @param overrideOrder overriding combatant order
*/ */
public static Map<Card, Integer> distributeAIDamage(final Card attacker, final CardCollectionView block, final CardCollectionView remaining, int dmgCanDeal, GameEntity defender, boolean overrideOrder) { public static Map<Card, Integer> distributeAIDamage(final Player self, final Card attacker, final CardCollectionView block, final CardCollectionView remaining, int dmgCanDeal, GameEntity defender, boolean overrideOrder) {
// TODO: Distribute defensive Damage (AI controls how damage is dealt to own cards) for Banding and Defensive Formation // TODO: Distribute defensive Damage (AI controls how damage is dealt to own cards) for Banding and Defensive Formation
Map<Card, Integer> damageMap = Maps.newHashMap(); Map<Card, Integer> damageMap = Maps.newHashMap();
Combat combat = attacker.getGame().getCombat(); Combat combat = attacker.getGame().getCombat();
boolean isAttacking = defender != null; boolean isAttacking = defender != null;
// TODO: is this enough to determine the fact that we're legally assigning combat damage to our creatures?
boolean isAttackingMe = isAttacking && combat.getDefenderPlayerByAttacker(attacker).equals(self); // Banding, Defensive Formation - the AI assigns combat damage to itself
final boolean hasTrample = attacker.hasKeyword(Keyword.TRAMPLE); final boolean hasTrample = attacker.hasKeyword(Keyword.TRAMPLE);
if (combat != null && remaining != null && hasTrample && attacker.isAttacking()) { if (combat != null && remaining != null && hasTrample && attacker.isAttacking() && !isAttackingMe) {
// if attacker has trample and some of its blockers are also blocking others it's generally a good idea // if attacker has trample and some of its blockers are also blocking others it's generally a good idea
// to assign those without trample first so we can maximize the damage to the defender // to assign those without trample first so we can maximize the damage to the defender
for (final Card c : remaining) { for (final Card c : remaining) {
@@ -2061,7 +2065,7 @@ public class ComputerUtilCombat {
final Card blocker = block.getFirst(); final Card blocker = block.getFirst();
int dmgToBlocker = dmgCanDeal; int dmgToBlocker = dmgCanDeal;
if (hasTrample && isAttacking) { // otherwise no entity to deliver damage via trample if (hasTrample && isAttacking && !isAttackingMe) { // otherwise no entity to deliver damage via trample
dmgToBlocker = getEnoughDamageToKill(blocker, dmgCanDeal, attacker, true); dmgToBlocker = getEnoughDamageToKill(blocker, dmgCanDeal, attacker, true);
if (dmgCanDeal < dmgToBlocker) { if (dmgCanDeal < dmgToBlocker) {
@@ -2078,6 +2082,7 @@ public class ComputerUtilCombat {
damageMap.put(blocker, dmgToBlocker); damageMap.put(blocker, dmgToBlocker);
} // 1 blocker } // 1 blocker
else { else {
if (!isAttackingMe) {
// Does the attacker deal lethal damage to all blockers // Does the attacker deal lethal damage to all blockers
//Blocking Order now determined after declare blockers //Blocking Order now determined after declare blockers
Card lastBlocker = null; Card lastBlocker = null;
@@ -2098,13 +2103,18 @@ public class ComputerUtilCombat {
} }
} // for } // for
if (dmgCanDeal > 0 ) { // if any damage left undistributed, if (dmgCanDeal > 0) { // if any damage left undistributed,
if (hasTrample && isAttacking) // if you have trample, deal damage to defending entity if (hasTrample && isAttacking) // if you have trample, deal damage to defending entity
damageMap.put(null, dmgCanDeal); damageMap.put(null, dmgCanDeal);
else if (lastBlocker != null) { // otherwise flush it into last blocker else if (lastBlocker != null) { // otherwise flush it into last blocker
damageMap.put(lastBlocker, dmgCanDeal + damageMap.get(lastBlocker)); damageMap.put(lastBlocker, dmgCanDeal + damageMap.get(lastBlocker));
} }
} }
} else {
// In the event of Banding or Defensive Formation, assign max damage to a single blocker to lose
// as little as possible
damageMap.put(block.getFirst(), dmgCanDeal);
}
} }
return damageMap; return damageMap;
} }

View File

@@ -106,7 +106,7 @@ public class PlayerControllerAi extends PlayerController {
@Override @Override
public Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, CardCollectionView remaining, int damageDealt, GameEntity defender, boolean overrideOrder) { public Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, CardCollectionView remaining, int damageDealt, GameEntity defender, boolean overrideOrder) {
return ComputerUtilCombat.distributeAIDamage(attacker, blockers, remaining, damageDealt, defender, overrideOrder); return ComputerUtilCombat.distributeAIDamage(player, attacker, blockers, remaining, damageDealt, defender, overrideOrder);
} }
@Override @Override