- Improved the AI for attacking in presence of Lightmine Field (logic developed by nefigah).

This commit is contained in:
Agetian
2017-06-13 16:03:42 +00:00
parent 2cc5a47336
commit 5f9efe9192
3 changed files with 62 additions and 8 deletions

View File

@@ -544,7 +544,13 @@ public class AiAttackController {
return; return;
} }
boolean playAggro = false;
if (ai.getController().isAI()) {
playAggro = ((PlayerControllerAi) ai.getController()).getAi().getProperty(AiProps.PLAY_AGGRO).equals("true");
}
final boolean bAssault = this.doAssault(ai); final boolean bAssault = this.doAssault(ai);
final boolean lightmineField = ComputerUtilCard.isPresentOnBattlefield(ai.getGame(), "Lightmine Field");
// Determine who will be attacked // Determine who will be attacked
GameEntity defender = this.chooseDefender(combat, bAssault); GameEntity defender = this.chooseDefender(combat, bAssault);
List<Card> attackersLeft = new ArrayList<Card>(this.attackers); List<Card> attackersLeft = new ArrayList<Card>(this.attackers);
@@ -590,6 +596,38 @@ public class AiAttackController {
if (attackersLeft.isEmpty()) { if (attackersLeft.isEmpty()) {
return; return;
} }
// Lightmine Field: make sure the AI doesn't wipe out its own creatures
if (lightmineField) {
CardCollection attSorted = new CardCollection(attackersLeft);
CardCollection attUnsafe = new CardCollection();
CardLists.sortByToughnessDesc(attSorted);
int i = 0;
int refPowerValue = 0; // Aggro profiles do not account for the possible blockers' power, conservative profiles do.
if (!playAggro && this.blockers.size() > 0) {
// Conservative play: check to ensure that the card can't be killed off while damaged
// TODO: currently sorting a copy of this.blockers, but it looks safe to operate on this.blockers directly?
// Also, this should ideally somehow account for double blocks, unblockability, etc. Difficult to do without
// running simulations.
CardCollection blkSorted = new CardCollection(this.blockers);
CardLists.sortByPowerDesc(blkSorted);
refPowerValue = blkSorted.get(0).getCurrentPower();
}
for (Card cre : attSorted) {
i++;
if (i + refPowerValue >= cre.getCurrentToughness()) {
attUnsafe.add(cre);
} else {
continue;
}
}
attackersLeft.removeAll(attUnsafe);
}
if (bAssault) { if (bAssault) {
if (LOG_AI_ATTACKS) if (LOG_AI_ATTACKS)
System.out.println("Assault"); System.out.println("Assault");
@@ -824,15 +862,11 @@ public class AiAttackController {
// end see how long until unblockable attackers will be fatal // end see how long until unblockable attackers will be fatal
// ***************** // *****************
// decide on attack aggression based on a comparison of forces, life // decide on attack aggression based on a comparison of forces, life
// totals and other considerations // totals and other considerations
// some bad "magic numbers" here, TODO replace with nice descriptive // some bad "magic numbers" here, TODO replace with nice descriptive
// variable names // variable names
boolean playAggro = false;
if (ai.getController().isAI()) {
playAggro = ((PlayerControllerAi) ai.getController()).getAi().getProperty(AiProps.PLAY_AGGRO).equals("true");
}
if (ratioDiff > 0 && doAttritionalAttack) { if (ratioDiff > 0 && doAttritionalAttack) {
this.aiAggression = 5; // attack at all costs this.aiAggression = 5; // attack at all costs
} else if ((ratioDiff >= 1 && this.attackers.size() > 1 && (humanLifeToDamageRatio < 2 || outNumber > 0)) } else if ((ratioDiff >= 1 && this.attackers.size() > 1 && (humanLifeToDamageRatio < 2 || outNumber > 0))

View File

@@ -1584,4 +1584,7 @@ public class ComputerUtilCard {
return false; return false;
} }
public static boolean isPresentOnBattlefield(final Game game, final String cardName) {
return !CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals(cardName)).isEmpty();
}
} }

View File

@@ -73,6 +73,12 @@ public class CardLists {
return a.getNetToughness() - b.getNetToughness(); return a.getNetToughness() - b.getNetToughness();
} }
}; };
public static final Comparator<Card> ToughnessComparatorInv = new Comparator<Card>() {
@Override
public int compare(final Card a, final Card b) {
return b.getNetToughness() - a.getNetToughness();
}
};
public static final Comparator<Card> PowerComparator = new Comparator<Card>() { public static final Comparator<Card> PowerComparator = new Comparator<Card>() {
@Override @Override
public int compare(final Card a, final Card b) { public int compare(final Card a, final Card b) {
@@ -104,18 +110,29 @@ public class CardLists {
*/ */
public static void sortByCmcDesc(final List<Card> list) { public static void sortByCmcDesc(final List<Card> list) {
Collections.sort(list, CmcComparatorInv); Collections.sort(list, CmcComparatorInv);
} // sortCMC } // sortByCmcDesc
/** /**
* <p> * <p>
* sortAttackLowFirst. * sortByToughnessAsc
* </p> * </p>
* *
* @param list * @param list
*/ */
public static void sortByToughnessAsc(final List<Card> list) { public static void sortByToughnessAsc(final List<Card> list) {
Collections.sort(list, ToughnessComparator); Collections.sort(list, ToughnessComparator);
} // sortAttackLowFirst() } // sortByToughnessAsc()
/**
* <p>
* sortByToughnessDesc
* </p>
*
* @param list
*/
public static void sortByToughnessDesc(final List<Card> list) {
Collections.sort(list, ToughnessComparatorInv);
} // sortByToughnessDesc()
/** /**
* <p> * <p>