mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 17:58:01 +00:00
Merge branch 'master' into 'master'
Improved London Mulligan AI See merge request core-developers/forge!1844
This commit is contained in:
@@ -552,11 +552,45 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public CardCollectionView londonMulliganReturnCards(final Player mulliganingPlayer, int cardsToReturn) {
|
||||
// TODO This is awful. Don't do this.
|
||||
// TODO This is better than it was before, but still suboptimal (but fast).
|
||||
// Maybe score a bunch of hands based on projected hand size and return the "duds"
|
||||
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
|
||||
CardCollection hand = new CardCollection(player.getCardsIn(ZoneType.Hand));
|
||||
CardCollection landsInHand = CardLists.filter(hand, Presets.LANDS);
|
||||
int numLandsInHand = landsInHand.size();
|
||||
int numLandsDesired = (mulliganingPlayer.getStartingHandSize() - cardsToReturn) / 2;
|
||||
|
||||
return CardCollection.getView(hand.subList(0, cardsToReturn));
|
||||
CardCollection toReturn = new CardCollection();
|
||||
for (int i = 0; i < cardsToReturn; i++) {
|
||||
// If we're flooding with lands, get rid of the worst land we have
|
||||
if (numLandsInHand > 0 && numLandsInHand > numLandsDesired) {
|
||||
CardCollection producingLands = CardLists.filter(landsInHand, Presets.LANDS_PRODUCING_MANA);
|
||||
CardCollection nonProducingLands = CardLists.filter(landsInHand, Predicates.not(Presets.LANDS_PRODUCING_MANA));
|
||||
Card worstLand = nonProducingLands.isEmpty() ? ComputerUtilCard.getWorstLand(producingLands)
|
||||
: ComputerUtilCard.getWorstLand(nonProducingLands);
|
||||
toReturn.add(worstLand);
|
||||
continue;
|
||||
}
|
||||
|
||||
// See if we'd scry something to the bottom in this situation. If we want to, probably get rid of it.
|
||||
CardCollection scryBottom = new CardCollection();
|
||||
for (Card c : hand) {
|
||||
// Lands are evaluated separately above, factoring in the number of cards to be returned to the library
|
||||
if (!c.isLand() && !toReturn.contains(c) && !willPutCardOnTop(c)) {
|
||||
scryBottom.add(c);
|
||||
}
|
||||
}
|
||||
if (!scryBottom.isEmpty()) {
|
||||
CardLists.sortByCmcDesc(scryBottom);
|
||||
toReturn.add(scryBottom.getFirst()); // assume the max CMC one is worse since we're not guaranteed to have lands for it
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we don't want to scry anything to the bottom, remove the worst card that we have in order to satisfy
|
||||
// the requirement
|
||||
toReturn.add(ComputerUtilCard.getWorstAI(hand));
|
||||
}
|
||||
|
||||
return CardCollection.getView(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
Name:Goatnap
|
||||
ManaCost:2 R
|
||||
Types:Sorcery
|
||||
A:SP$ GainControl | Cost$ 2 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | Untap$ True | LoseControl$ EOT | SubAbility$ DBPumpHaste | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. If that creature is a, it also gets +3/+0 until end of turn.
|
||||
SVar:DBPumpHaste:DB$ Pump | Defined$ Targeted | KW$ Haste | SubAbility$ DBPump
|
||||
A:SP$ GainControl | Cost$ 2 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | Untap$ True | AddKWs$ Haste | LoseControl$ EOT | SubAbility$ DBPump | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. If that creature is a, it also gets +3/+0 until end of turn.
|
||||
SVar:DBPump:DB$ Pump | Defined$ Targeted | NumAtt$ 3 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X
|
||||
SVar:X:Targeted$Valid Goat
|
||||
Oracle:Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. If that creature is a goat, it also gets +3/+0 until end of turn.
|
||||
|
||||
Reference in New Issue
Block a user