mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
- Improved the AI for attacking in presence of Lightmine Field (logic developed by nefigah).
This commit is contained in:
@@ -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))
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user