improved AI targetting

This commit is contained in:
BetaSteward 2011-03-31 23:34:16 -04:00
parent 6ea73a6726
commit aed200bc11
13 changed files with 129 additions and 105 deletions

View file

@ -566,9 +566,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
@Override @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) if (targets.size() == 0)
return super.chooseTarget(cards, target, source, game); return super.chooseTarget(outcome, cards, target, source, game);
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: targets) { for (UUID targetId: targets) {
target.addTarget(targetId, source, game); target.addTarget(targetId, source, game);
@ -583,9 +583,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
@Override @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) if (targets.size() == 0)
return super.choose(cards, target, game); return super.choose(outcome, cards, target, game);
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: targets) { for (UUID targetId: targets) {
target.add(targetId, game); target.add(targetId, game);

View file

@ -363,13 +363,19 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
else { else {
card = pickWorstCard(cards, null); 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; return card;
} }
cards.remove(card); cards.remove(card);
} }
return null; return null;
} }
@Override @Override
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
@ -768,33 +774,35 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
} }
@Override @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"); logger.debug("chooseTarget");
//TODO: improve this while (!target.doneChosing()) {
//return first match if (cards.isEmpty()) {
if (!target.doneChosing()) { if (!target.isRequired())
for (Card card: cards.getCards(target.getFilter(), game)) { return false;
target.addTarget(card.getId(), source, game); return true;
if (target.doneChosing()) }
return true; Card card = pickTarget(new ArrayList<Card>(cards.getCards(target.getFilter(), game)), outcome, target, source, game);
if (card != null) {
target.addTarget(card.getId(), source, game);
} }
return false;
} }
return true; return true;
} }
@Override @Override
public boolean choose(Cards cards, TargetCard target, Game game) { public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
logger.debug("choose"); logger.debug("choose");
//TODO: improve this while (!target.doneChosing()) {
//return first match if (cards.isEmpty()) {
if (!target.doneChosing()) { if (!target.isRequired())
for (Card card: cards.getCards(target.getFilter(), game)) { return false;
target.add(card.getId(), game); return true;
if (target.doneChosing()) }
return true; Card card = pickTarget(new ArrayList<Card>(cards.getCards(target.getFilter(), game)), outcome, target, null, game);
if (card != null) {
target.add(card.getId(), game);
} }
return false;
} }
return true; return true;
} }
@ -884,6 +892,77 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
match.submitDeck(playerId, deck); match.submitDeck(playerId, deck);
} }
public static Deck buildDeck(List<Card> cardPool, final List<Constants.ColoredManaSymbol> colors) {
Deck deck = new Deck();
List<Card> sortedCards = new ArrayList<Card>(cardPool);
Collections.sort(sortedCards, new Comparator<Card>() {
@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 @Override
public void construct(Tournament tournament, Deck deck) { public void construct(Tournament tournament, Deck deck) {
if (deck.getCards().size() < 40) { if (deck.getCards().size() < 40) {
@ -894,66 +973,7 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
} }
chosenColors = chooseDeckColorsIfPossible(); chosenColors = chooseDeckColorsIfPossible();
} }
List<Card> sortedCards = new ArrayList<Card>(deck.getSideboard()); deck = buildDeck(new ArrayList<Card>(deck.getSideboard()), chosenColors);
Collections.sort(sortedCards, new Comparator<Card>() {
@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);
}
}
} }
tournament.submitDeck(playerId, deck); tournament.submitDeck(playerId, deck);
} }

View file

@ -514,9 +514,9 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
} }
@Override @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) if (targets.size() == 0)
return super.chooseTarget(cards, target, source, game); return super.chooseTarget(outcome, cards, target, source, game);
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: targets) { for (UUID targetId: targets) {
target.addTarget(targetId, source, game); target.addTarget(targetId, source, game);
@ -531,9 +531,9 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
} }
@Override @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) if (targets.size() == 0)
return super.choose(cards, target, game); return super.choose(outcome, cards, target, game);
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: targets) { for (UUID targetId: targets) {
target.add(targetId, game); target.add(targetId, game);

View file

@ -236,7 +236,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
} }
@Override @Override
public boolean choose(Cards cards, TargetCard target, Game game) { public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
while (!abort) { while (!abort) {
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired());
waitForResponse(); waitForResponse();
@ -253,7 +253,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
} }
@Override @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) { while (!abort) {
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired());
waitForResponse(); waitForResponse();

View file

@ -100,7 +100,7 @@ class DuressEffect extends OneShotEffect<DuressEffect> {
Player you = game.getPlayer(source.getControllerId()); Player you = game.getPlayer(source.getControllerId());
if (you != null) { if (you != null) {
TargetCard target = new TargetCard(Zone.PICK, filter); 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); Card card = player.getHand().get(target.getFirstTarget(), game);
if (card != null) { if (card != null) {
return player.discard(card, source, game); return player.discard(card, source, game);

View file

@ -110,7 +110,7 @@ class CultivateEffect extends OneShotEffect<CultivateEffect> {
if (target.getTargets().size() == 2) { if (target.getTargets().size() == 2) {
TargetCard target2 = new TargetCard(Zone.PICK, filter); TargetCard target2 = new TargetCard(Zone.PICK, filter);
target2.setRequired(true); target2.setRequired(true);
player.choose(revealed, target2, game); player.choose(Outcome.Benefit, revealed, target2, game);
Card card = revealed.get(target2.getFirstTarget(), game); Card card = revealed.get(target2.getFirstTarget(), game);
card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId()); card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId());
revealed.remove(card); revealed.remove(card);

View file

@ -103,7 +103,7 @@ class InquisitionOfKozilekEffect extends OneShotEffect<InquisitionOfKozilekEffec
Player you = game.getPlayer(source.getControllerId()); Player you = game.getPlayer(source.getControllerId());
if (you != null) { if (you != null) {
TargetCard target = new TargetCard(Zone.PICK, filter); 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); Card card = player.getHand().get(target.getFirstTarget(), game);
if (card != null) { if (card != null) {
return player.discard(card, source, game); return player.discard(card, source, game);

View file

@ -110,7 +110,7 @@ class SeaGateOracleEffect extends OneShotEffect<SeaGateOracleEffect> {
TargetCard target = new TargetCard(Zone.PICK, filter); TargetCard target = new TargetCard(Zone.PICK, filter);
target.setRequired(true); target.setRequired(true);
player.lookAtCards(cards, game); player.lookAtCards(cards, game);
player.choose(cards, target, game); player.choose(Outcome.Benefit, cards, target, game);
card = cards.get(target.getFirstTarget(), game); card = cards.get(target.getFirstTarget(), game);
if (card != null) { if (card != null) {
card.moveToZone(Zone.HAND, source.getId(), game, false); card.moveToZone(Zone.HAND, source.getId(), game, false);

View file

@ -90,7 +90,7 @@ class SeeBeyondEffect extends OneShotEffect<SeeBeyondEffect> {
if (player.getHand().size() > 0) { if (player.getHand().size() > 0) {
TargetCard target = new TargetCard(Zone.HAND, filter); TargetCard target = new TargetCard(Zone.HAND, filter);
target.setRequired(true); 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); Card card = player.getHand().get(target.getFirstTarget(), game);
if (card != null) { if (card != null) {
player.removeFromHand(card, game); player.removeFromHand(card, game);

View file

@ -97,7 +97,7 @@ class HalimarDepthsEffect extends OneShotEffect<HalimarDepthsEffect> {
TargetCard target2 = new TargetCard(Zone.PICK, filter2); TargetCard target2 = new TargetCard(Zone.PICK, filter2);
target2.setRequired(true); target2.setRequired(true);
while (cards.size() > 1) { while (cards.size() > 1) {
player.choose(cards, target2, game); player.choose(Outcome.Detriment, cards, target2, game);
Card card = cards.get(target2.getFirstTarget(), game); Card card = cards.get(target2.getFirstTarget(), game);
cards.remove(card); cards.remove(card);
card.moveToZone(Zone.LIBRARY, source.getId(), game, true); card.moveToZone(Zone.LIBRARY, source.getId(), game, true);

View file

@ -71,20 +71,24 @@ public class ScryEffect extends OneShotEffect<ScryEffect> {
game.setZone(card.getId(), Zone.PICK); game.setZone(card.getId(), Zone.PICK);
} }
TargetCard target1 = new TargetCard(Zone.PICK, filter1); 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); Card card = cards.get(target1.getFirstTarget(), game);
cards.remove(card); if (card != null) {
card.moveToZone(Zone.LIBRARY, source.getId(), game, false); cards.remove(card);
card.moveToZone(Zone.LIBRARY, source.getId(), game, false);
}
target1.clearChosen(); target1.clearChosen();
} }
if (cards.size() > 1) { if (cards.size() > 1) {
TargetCard target2 = new TargetCard(Zone.PICK, filter2); TargetCard target2 = new TargetCard(Zone.PICK, filter2);
target2.setRequired(true); target2.setRequired(true);
while (cards.size() > 1) { while (cards.size() > 1) {
player.choose(cards, target2, game); player.choose(Outcome.Benefit, cards, target2, game);
Card card = cards.get(target2.getFirstTarget(), game); Card card = cards.get(target2.getFirstTarget(), game);
cards.remove(card); if (card != null) {
card.moveToZone(Zone.LIBRARY, source.getId(), game, true); cards.remove(card);
card.moveToZone(Zone.LIBRARY, source.getId(), game, true);
}
target2.clearChosen(); target2.clearChosen();
} }
} }

View file

@ -144,9 +144,9 @@ public interface Player extends MageItem, Copyable<Player> {
public abstract void priority(Game game); 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);
public abstract boolean choose(Outcome outcome, Target target, Game game, Map<String, Serializable> options); public abstract boolean choose(Outcome outcome, Target target, Game game, Map<String, Serializable> 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(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 chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game);
public abstract boolean chooseMulligan(Game game); public abstract boolean chooseMulligan(Game game);
public abstract boolean chooseUse(Outcome outcome, String message, Game game); public abstract boolean chooseUse(Outcome outcome, String message, Game game);

View file

@ -70,13 +70,13 @@ public class TargetCardInLibrary extends TargetCard<TargetCardInLibrary> {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
while (!isChosen() && !doneChosing()) { while (!isChosen() && !doneChosing()) {
chosen = targets.size() >= minNumberOfTargets; 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; return chosen;
} }
chosen = targets.size() >= minNumberOfTargets; chosen = targets.size() >= minNumberOfTargets;
} }
while (!doneChosing()) { 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; break;
} }
} }