From aed200bc11e09f10891880a3f2c1053fbafbe741 Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Thu, 31 Mar 2011 23:34:16 -0400 Subject: [PATCH] improved AI targetting --- .../src/mage/player/ai/ComputerPlayer6.java | 8 +- .../java/mage/player/ai/ComputerPlayer.java | 178 ++++++++++-------- .../src/mage/player/ai/ComputerPlayer2.java | 8 +- .../src/mage/player/human/HumanPlayer.java | 4 +- Mage.Sets/src/mage/sets/magic2010/Duress.java | 2 +- .../src/mage/sets/magic2011/Cultivate.java | 2 +- .../InquisitionOfKozilek.java | 2 +- .../sets/riseoftheeldrazi/SeaGateOracle.java | 2 +- .../mage/sets/riseoftheeldrazi/SeeBeyond.java | 2 +- .../mage/sets/worldwake/HalimarDepths.java | 2 +- .../abilities/effects/common/ScryEffect.java | 16 +- Mage/src/mage/players/Player.java | 4 +- .../target/common/TargetCardInLibrary.java | 4 +- 13 files changed, 129 insertions(+), 105 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index 89815a2ac0..ed96192549 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -566,9 +566,9 @@ public class ComputerPlayer6 extends ComputerPlayer implements } @Override - public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { + public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { if (targets.size() == 0) - return super.chooseTarget(cards, target, source, game); + return super.chooseTarget(outcome, cards, target, source, game); if (!target.doneChosing()) { for (UUID targetId: targets) { target.addTarget(targetId, source, game); @@ -583,9 +583,9 @@ public class ComputerPlayer6 extends ComputerPlayer implements } @Override - public boolean choose(Cards cards, TargetCard target, Game game) { + public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) { if (targets.size() == 0) - return super.choose(cards, target, game); + return super.choose(outcome, cards, target, game); if (!target.doneChosing()) { for (UUID targetId: targets) { target.add(targetId, game); diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 13986c6f6a..8eb6816a40 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -363,13 +363,19 @@ public class ComputerPlayer> extends PlayerImpl i else { card = pickWorstCard(cards, null); } - if (target.canTarget(card.getId(), source, game)) { + if (source != null) { + if (target.canTarget(card.getId(), source, game)) { + return card; + } + } + else { return card; } cards.remove(card); } return null; } + @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { if (logger.isDebugEnabled()) @@ -768,33 +774,35 @@ public class ComputerPlayer> extends PlayerImpl i } @Override - public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { + public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { logger.debug("chooseTarget"); - //TODO: improve this - //return first match - if (!target.doneChosing()) { - for (Card card: cards.getCards(target.getFilter(), game)) { - target.addTarget(card.getId(), source, game); - if (target.doneChosing()) - return true; + while (!target.doneChosing()) { + if (cards.isEmpty()) { + if (!target.isRequired()) + return false; + return true; + } + Card card = pickTarget(new ArrayList(cards.getCards(target.getFilter(), game)), outcome, target, source, game); + if (card != null) { + target.addTarget(card.getId(), source, game); } - return false; } return true; } @Override - public boolean choose(Cards cards, TargetCard target, Game game) { + public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) { logger.debug("choose"); - //TODO: improve this - //return first match - if (!target.doneChosing()) { - for (Card card: cards.getCards(target.getFilter(), game)) { - target.add(card.getId(), game); - if (target.doneChosing()) - return true; + while (!target.doneChosing()) { + if (cards.isEmpty()) { + if (!target.isRequired()) + return false; + return true; + } + Card card = pickTarget(new ArrayList(cards.getCards(target.getFilter(), game)), outcome, target, null, game); + if (card != null) { + target.add(card.getId(), game); } - return false; } return true; } @@ -884,6 +892,77 @@ public class ComputerPlayer> extends PlayerImpl i match.submitDeck(playerId, deck); } + public static Deck buildDeck(List cardPool, final List colors) { + Deck deck = new Deck(); + List sortedCards = new ArrayList(cardPool); + Collections.sort(sortedCards, new Comparator() { + @Override + public int compare(Card o1, Card o2) { + Integer score1 = RateCard.rateCard(o1, colors); + Integer score2 = RateCard.rateCard(o2, colors); + return score2.compareTo(score1); + } + }); + int cardNum = 0; + while (deck.getCards().size() < 23 && sortedCards.size() > cardNum) { + Card card = sortedCards.get(cardNum); + if (!card.getSupertype().contains("Basic")) { + deck.getCards().add(card); + deck.getSideboard().remove(card); + } + cardNum++; + } + // add basic lands + // TODO: compensate for non basic lands + Mana mana = new Mana(); + for (Card card: deck.getCards()) { + mana.add(card.getManaCost().getMana()); + } + double total = mana.getBlack() + mana.getBlue() + mana.getGreen() + mana.getRed() + mana.getWhite(); + if (mana.getGreen() > 0) { + int numGreen = (int) Math.round(mana.getGreen() / total * 17); + for (int i = 0; i < numGreen; i++) { + Card land = Sets.findCard("Forest", true); + deck.getCards().add(land); + } + } + if (mana.getBlack() > 0) { + int numBlack = (int) Math.round(mana.getBlack() / total * 17); + for (int i = 0; i < numBlack; i++) { + Card land = Sets.findCard("Swamp", true); + deck.getCards().add(land); + } + } + if (mana.getBlue() > 0) { + int numBlue = (int) Math.round(mana.getBlue() / total * 17); + for (int i = 0; i < numBlue; i++) { + Card land = Sets.findCard("Island", true); + deck.getCards().add(land); + } + } + if (mana.getWhite() > 0) { + int numWhite = (int) Math.round(mana.getWhite() / total * 17); + for (int i = 0; i < numWhite; i++) { + Card land = Sets.findCard("Plains", true); + deck.getCards().add(land); + } + } + if (mana.getRed() > 0) { + int numRed = (int) Math.round(mana.getRed() / total * 17); + for (int i = 0; i < numRed; i++) { + Card land = Sets.findCard("Mountain", true); + deck.getCards().add(land); + } + } + while (deck.getCards().size() < 40) { + //TODO: improve this + Card land = Sets.findCard("Forest", true); + deck.getCards().add(land); + } + + return deck; + } + @Override public void construct(Tournament tournament, Deck deck) { if (deck.getCards().size() < 40) { @@ -894,66 +973,7 @@ public class ComputerPlayer> extends PlayerImpl i } chosenColors = chooseDeckColorsIfPossible(); } - List sortedCards = new ArrayList(deck.getSideboard()); - Collections.sort(sortedCards, new Comparator() { - @Override - public int compare(Card o1, Card o2) { - Integer score1 = RateCard.rateCard(o1, chosenColors); - Integer score2 = RateCard.rateCard(o2, chosenColors); - return score2.compareTo(score1); - } - }); - int cardNum = 0; - while (deck.getCards().size() < 23 && sortedCards.size() > cardNum) { - Card card = sortedCards.get(cardNum); - if (!card.getSupertype().contains("Basic")) { - deck.getCards().add(card); - deck.getSideboard().remove(card); - } - cardNum++; - } - // add basic lands - // TODO: compensate for non basic lands - Mana mana = new Mana(); - for (Card card: deck.getCards()) { - mana.add(card.getManaCost().getMana()); - } - double total = mana.getBlack() + mana.getBlue() + mana.getGreen() + mana.getRed() + mana.getWhite(); - if (mana.getGreen() > 0) { - int numGreen = (int) Math.round(mana.getGreen() / total * 17); - for (int i = 0; i < numGreen; i++) { - Card land = Sets.findCard("Forest", true); - deck.getCards().add(land); - } - } - if (mana.getBlack() > 0) { - int numBlack = (int) Math.round(mana.getBlack() / total * 17); - for (int i = 0; i < numBlack; i++) { - Card land = Sets.findCard("Swamp", true); - deck.getCards().add(land); - } - } - if (mana.getBlue() > 0) { - int numBlue = (int) Math.round(mana.getBlue() / total * 17); - for (int i = 0; i < numBlue; i++) { - Card land = Sets.findCard("Island", true); - deck.getCards().add(land); - } - } - if (mana.getWhite() > 0) { - int numWhite = (int) Math.round(mana.getWhite() / total * 17); - for (int i = 0; i < numWhite; i++) { - Card land = Sets.findCard("Plains", true); - deck.getCards().add(land); - } - } - if (mana.getRed() > 0) { - int numRed = (int) Math.round(mana.getRed() / total * 17); - for (int i = 0; i < numRed; i++) { - Card land = Sets.findCard("Mountain", true); - deck.getCards().add(land); - } - } + deck = buildDeck(new ArrayList(deck.getSideboard()), chosenColors); } tournament.submitDeck(playerId, deck); } diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java index 60fd7d0be7..65ba13978e 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java @@ -514,9 +514,9 @@ public class ComputerPlayer2 extends ComputerPlayer implements } @Override - public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { + public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { if (targets.size() == 0) - return super.chooseTarget(cards, target, source, game); + return super.chooseTarget(outcome, cards, target, source, game); if (!target.doneChosing()) { for (UUID targetId: targets) { target.addTarget(targetId, source, game); @@ -531,9 +531,9 @@ public class ComputerPlayer2 extends ComputerPlayer implements } @Override - public boolean choose(Cards cards, TargetCard target, Game game) { + public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) { if (targets.size() == 0) - return super.choose(cards, target, game); + return super.choose(outcome, cards, target, game); if (!target.doneChosing()) { for (UUID targetId: targets) { target.add(targetId, game); diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 493f08c59d..00f2515fe8 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -236,7 +236,7 @@ public class HumanPlayer extends PlayerImpl { } @Override - public boolean choose(Cards cards, TargetCard target, Game game) { + public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) { while (!abort) { game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); waitForResponse(); @@ -253,7 +253,7 @@ public class HumanPlayer extends PlayerImpl { } @Override - public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { + public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { while (!abort) { game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); waitForResponse(); diff --git a/Mage.Sets/src/mage/sets/magic2010/Duress.java b/Mage.Sets/src/mage/sets/magic2010/Duress.java index 25023693db..8b332b79f0 100644 --- a/Mage.Sets/src/mage/sets/magic2010/Duress.java +++ b/Mage.Sets/src/mage/sets/magic2010/Duress.java @@ -100,7 +100,7 @@ class DuressEffect extends OneShotEffect { Player you = game.getPlayer(source.getControllerId()); if (you != null) { TargetCard target = new TargetCard(Zone.PICK, filter); - if (you.choose(player.getHand(), target, game)) { + if (you.choose(Outcome.Benefit, player.getHand(), target, game)) { Card card = player.getHand().get(target.getFirstTarget(), game); if (card != null) { return player.discard(card, source, game); diff --git a/Mage.Sets/src/mage/sets/magic2011/Cultivate.java b/Mage.Sets/src/mage/sets/magic2011/Cultivate.java index 531460ab0e..bb65a7a5f5 100644 --- a/Mage.Sets/src/mage/sets/magic2011/Cultivate.java +++ b/Mage.Sets/src/mage/sets/magic2011/Cultivate.java @@ -110,7 +110,7 @@ class CultivateEffect extends OneShotEffect { if (target.getTargets().size() == 2) { TargetCard target2 = new TargetCard(Zone.PICK, filter); target2.setRequired(true); - player.choose(revealed, target2, game); + player.choose(Outcome.Benefit, revealed, target2, game); Card card = revealed.get(target2.getFirstTarget(), game); card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId()); revealed.remove(card); diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/InquisitionOfKozilek.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/InquisitionOfKozilek.java index 6ff2509669..20a9ec9cb2 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/InquisitionOfKozilek.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/InquisitionOfKozilek.java @@ -103,7 +103,7 @@ class InquisitionOfKozilekEffect extends OneShotEffect { TargetCard target = new TargetCard(Zone.PICK, filter); target.setRequired(true); player.lookAtCards(cards, game); - player.choose(cards, target, game); + player.choose(Outcome.Benefit, cards, target, game); card = cards.get(target.getFirstTarget(), game); if (card != null) { card.moveToZone(Zone.HAND, source.getId(), game, false); diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java index 0e15afba98..724e44ebf4 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java @@ -90,7 +90,7 @@ class SeeBeyondEffect extends OneShotEffect { if (player.getHand().size() > 0) { TargetCard target = new TargetCard(Zone.HAND, filter); target.setRequired(true); - player.choose(player.getHand(), target, game); + player.choose(Outcome.Detriment, player.getHand(), target, game); Card card = player.getHand().get(target.getFirstTarget(), game); if (card != null) { player.removeFromHand(card, game); diff --git a/Mage.Sets/src/mage/sets/worldwake/HalimarDepths.java b/Mage.Sets/src/mage/sets/worldwake/HalimarDepths.java index d5aa551cfc..50376eb835 100644 --- a/Mage.Sets/src/mage/sets/worldwake/HalimarDepths.java +++ b/Mage.Sets/src/mage/sets/worldwake/HalimarDepths.java @@ -97,7 +97,7 @@ class HalimarDepthsEffect extends OneShotEffect { TargetCard target2 = new TargetCard(Zone.PICK, filter2); target2.setRequired(true); while (cards.size() > 1) { - player.choose(cards, target2, game); + player.choose(Outcome.Detriment, cards, target2, game); Card card = cards.get(target2.getFirstTarget(), game); cards.remove(card); card.moveToZone(Zone.LIBRARY, source.getId(), game, true); diff --git a/Mage/src/mage/abilities/effects/common/ScryEffect.java b/Mage/src/mage/abilities/effects/common/ScryEffect.java index d4a9a7a586..487368da47 100644 --- a/Mage/src/mage/abilities/effects/common/ScryEffect.java +++ b/Mage/src/mage/abilities/effects/common/ScryEffect.java @@ -71,20 +71,24 @@ public class ScryEffect extends OneShotEffect { game.setZone(card.getId(), Zone.PICK); } TargetCard target1 = new TargetCard(Zone.PICK, filter1); - while (cards.size() > 0 && player.choose(cards, target1, game)) { + while (cards.size() > 0 && player.choose(Outcome.Detriment, cards, target1, game)) { Card card = cards.get(target1.getFirstTarget(), game); - cards.remove(card); - card.moveToZone(Zone.LIBRARY, source.getId(), game, false); + if (card != null) { + cards.remove(card); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); + } target1.clearChosen(); } if (cards.size() > 1) { TargetCard target2 = new TargetCard(Zone.PICK, filter2); target2.setRequired(true); while (cards.size() > 1) { - player.choose(cards, target2, game); + player.choose(Outcome.Benefit, cards, target2, game); Card card = cards.get(target2.getFirstTarget(), game); - cards.remove(card); - card.moveToZone(Zone.LIBRARY, source.getId(), game, true); + if (card != null) { + cards.remove(card); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); + } target2.clearChosen(); } } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 880147878e..27cbecb378 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -144,9 +144,9 @@ public interface Player extends MageItem, Copyable { public abstract void priority(Game game); public abstract boolean choose(Outcome outcome, Target target, Game game); public abstract boolean choose(Outcome outcome, Target target, Game game, Map options); - public abstract boolean choose(Cards cards, TargetCard target, Game game); + public abstract boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game); public abstract boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game); - public abstract boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game); + public abstract boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game); public abstract boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game); public abstract boolean chooseMulligan(Game game); public abstract boolean chooseUse(Outcome outcome, String message, Game game); diff --git a/Mage/src/mage/target/common/TargetCardInLibrary.java b/Mage/src/mage/target/common/TargetCardInLibrary.java index 02676100f1..bb27c2de24 100644 --- a/Mage/src/mage/target/common/TargetCardInLibrary.java +++ b/Mage/src/mage/target/common/TargetCardInLibrary.java @@ -70,13 +70,13 @@ public class TargetCardInLibrary extends TargetCard { Player player = game.getPlayer(playerId); while (!isChosen() && !doneChosing()) { chosen = targets.size() >= minNumberOfTargets; - if (!player.choose(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { + if (!player.choose(outcome, new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { return chosen; } chosen = targets.size() >= minNumberOfTargets; } while (!doneChosing()) { - if (!player.choose(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { + if (!player.choose(outcome, new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { break; } }