mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
- Separated vehicle crewing logic between "canPay" and "canPlay"
This commit is contained in:
@@ -32,7 +32,6 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.ai.ability.ProtectAi;
|
||||
import forge.card.CardType;
|
||||
import forge.card.MagicColor;
|
||||
@@ -45,7 +44,6 @@ import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
@@ -504,7 +502,6 @@ public class ComputerUtil {
|
||||
// Used for Crewing vehicles, ideally we sort by useless creatures. Can't Attack/Defender
|
||||
int totalPower = 0;
|
||||
final Card activate = sa.getHostCard();
|
||||
int vehicleValue = 0;
|
||||
|
||||
CardCollection all = new CardCollection(ai.getCardsIn(ZoneType.Battlefield));
|
||||
all.removeAll(exclude);
|
||||
@@ -513,9 +510,6 @@ public class ComputerUtil {
|
||||
|
||||
if (sa.hasParam("Crew")) {
|
||||
typeList = CardLists.getNotKeyword(typeList, "CARDNAME can't crew Vehicles.");
|
||||
Card vehicle = CardFactory.copyCard(sa.getHostCard(), true);
|
||||
AnimateAi.becomeAnimated(vehicle, false, sa);
|
||||
vehicleValue = ComputerUtilCard.evaluateCreature(vehicle);
|
||||
}
|
||||
|
||||
// is this needed?
|
||||
@@ -524,14 +518,15 @@ public class ComputerUtil {
|
||||
if (tap) {
|
||||
typeList.remove(activate);
|
||||
}
|
||||
CardLists.sortByPowerAsc(typeList);
|
||||
ComputerUtilCard.sortByEvaluateCreature(typeList);
|
||||
Collections.reverse(typeList);
|
||||
|
||||
final CardCollection tapList = new CardCollection();
|
||||
|
||||
// Very very rudimentary
|
||||
// Accumulate from "worst" creature
|
||||
for (Card next : typeList) {
|
||||
int pow = next.getNetPower();
|
||||
if (pow <= 0 || ComputerUtilCard.evaluateCreature(next) > vehicleValue) {
|
||||
if (pow <= 0) {
|
||||
continue;
|
||||
}
|
||||
totalPower += pow;
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package forge.ai;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.game.GameActionUtil;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CounterType;
|
||||
@@ -296,8 +301,39 @@ public class ComputerUtilCost {
|
||||
if (cost == null) {
|
||||
return true;
|
||||
}
|
||||
boolean isVehicle = source.hasStartOfKeyword("Crew");
|
||||
for (final CostPart part : cost.getCostParts()) {
|
||||
if (part instanceof CostTapType) {
|
||||
/*
|
||||
* Only crew with creatures weaker than vehicle
|
||||
*
|
||||
* Possible improvements:
|
||||
* - block against evasive (flyers, intimidate, etc.)
|
||||
* - break board stall by racing with evasive vehicle
|
||||
*/
|
||||
if (isVehicle) {
|
||||
for (SpellAbility sa : source.getSpellAbilities()) {
|
||||
if (sa.getApi() == ApiType.Animate) {
|
||||
Card vehicle = CardFactory.copyCard(sa.getHostCard(), true);
|
||||
AnimateAi.becomeAnimated(vehicle, false, sa);
|
||||
final int vehicleValue = ComputerUtilCard.evaluateCreature(vehicle);
|
||||
String type = part.getType();
|
||||
String totalP = type.split("withTotalPowerGE")[1];
|
||||
type = type.replace("+withTotalPowerGE" + totalP, "");
|
||||
CardCollection exclude = CardLists.getValidCards(
|
||||
new CardCollection(ai.getCardsIn(ZoneType.Battlefield)), type.split(";"),
|
||||
source.getController(), source, sa);
|
||||
exclude = CardLists.filter(exclude, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return ComputerUtilCard.evaluateCreature(c) >= vehicleValue;
|
||||
}
|
||||
}); // exclude creatures >= vehicle
|
||||
return ComputerUtil.chooseTapTypeAccumulatePower(ai, type, sa, true,
|
||||
Integer.parseInt(totalP), exclude) != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,10 +137,12 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
if (sa.getConditions() != null && !sa.getConditions().areMet(sa) && sa.getSubAbility() == null) {
|
||||
return false; // what is this for?
|
||||
}
|
||||
|
||||
if (!game.getStack().isEmpty() && game.getStack().peekAbility().getApi() == ApiType.Sacrifice) {
|
||||
return true; // interrupt sacrifice
|
||||
}
|
||||
if (!ComputerUtilCost.checkTapTypeCost(aiPlayer, sa.getPayCosts(), source)) {
|
||||
return false; // prevent crewing with equal or better creatures
|
||||
}
|
||||
if (null == tgt) {
|
||||
final List<Card> defined = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
||||
boolean bFlag = false;
|
||||
|
||||
Reference in New Issue
Block a user