scry now uses player controllers to learn player's choice, method player.scry() moved to ScryEffect

Human uses GuiChoice.order to arrange cards to be put on top or bottom of library (that means less popping windows)
AI has a method in ComputerUtil to learn where to put a given card.
This commit is contained in:
Maxmtg
2013-03-16 10:04:39 +00:00
parent 92caa7514d
commit 4acffc60cd
8 changed files with 92 additions and 90 deletions

View File

@@ -1,12 +1,19 @@
package forge.card.ability.effects;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import forge.Card;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.player.Player;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
public class ScryEffect extends SpellAbilityEffect {
@@ -42,7 +49,38 @@ public class ScryEffect extends SpellAbilityEffect {
for (final Player p : tgtPlayers) {
if ((tgt == null) || p.canBeTargetedBy(sa)) {
p.scry(num);
scry(p, num);
}
}
}
/**
* <p>
* scry.
* </p>
*
* @param numScry
* a int.
*/
public final void scry(Player p, int numScry) {
final List<Card> topN = new ArrayList<Card>();
final PlayerZone library = p.getZone(ZoneType.Library);
numScry = Math.min(numScry, library.size());
for (int i = 0; i < numScry; i++) {
topN.add(library.get(i));
}
ImmutablePair<List<Card>, List<Card>> lists = p.getController().arrangeForScry(topN);
for(Card c : lists.getRight()) {
p.getGame().getAction().moveToBottomOfLibrary(c);
}
List<Card> toTop = lists.getLeft();
if ( null != toTop ) {
Collections.reverse(toTop); // the last card in list will become topmost in library, have to revert thus.
for(Card c : toTop) {
p.getGame().getAction().moveToLibrary(c);
}
}
}

View File

@@ -24,6 +24,7 @@ import java.util.Random;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.Card;
import forge.CardLists;
@@ -1223,4 +1224,19 @@ public class ComputerUtil {
return (handList.size() > AI_MULLIGAN_THRESHOLD) && hasLittleCmc0Cards;
}
public static boolean scryWillMoveCardToBottomOfLibrary(AIPlayer player, Card c) {
boolean bottom = false;
if (c.isBasicLand()) {
List<Card> bl = player.getCardsIn(ZoneType.Battlefield);
int nBasicLands = Iterables.size(Iterables.filter(bl, CardPredicates.Presets.BASIC_LANDS));
bottom = nBasicLands > 5; // if control more than 5 Basic land, probably don't need more
} else if (c.isCreature()) {
List<Card> cl = player.getCardsIn(ZoneType.Battlefield);
cl = CardLists.filter(cl, CardPredicates.Presets.CREATURES);
bottom = cl.size() > 5; // if control more than 5 Creatures, probably don't need more
}
return bottom;
}
}

View File

@@ -20,7 +20,6 @@ package forge.game.player;
import java.util.List;
import java.util.Random;
import com.google.common.collect.Iterables;
import forge.Card;
import forge.CardLists;
@@ -135,41 +134,6 @@ public class AIPlayer extends Player {
// /////////////////////////
/** {@inheritDoc} */
@Override
protected final void doScry(final List<Card> topN, final int n) {
int num = n;
for (int i = 0; i < num; i++) {
boolean bottom = false;
if (topN.get(i).isBasicLand()) {
List<Card> bl = this.getCardsIn(ZoneType.Battlefield);
int nBasicLands = Iterables.size(Iterables.filter(bl, CardPredicates.Presets.BASIC_LANDS));
bottom = nBasicLands > 5; // if control more than 5 Basic land,
// probably don't need more
} else if (topN.get(i).isCreature()) {
List<Card> cl = this.getCardsIn(ZoneType.Battlefield);
cl = CardLists.filter(cl, CardPredicates.Presets.CREATURES);
bottom = cl.size() > 5; // if control more than 5 Creatures,
// probably don't need more
}
if (bottom) {
final Card c = topN.get(i);
game.getAction().moveToBottomOfLibrary(c);
// topN.remove(c);
}
}
num = topN.size();
// put the rest on top in random order
for (int i = 0; i < num; i++) {
final Random rndm = MyRandom.getRandom();
final int r = rndm.nextInt(topN.size());
final Card c = topN.get(r);
game.getAction().moveToLibrary(c);
topN.remove(r);
}
}
/** {@inheritDoc} */
@Override
public final void sacrificePermanent(final String prompt, final List<Card> choices) {

View File

@@ -117,31 +117,6 @@ public class HumanPlayer extends Player {
Singletons.getModel().getMatch().getInput().setInputInterrupt(PlayerUtil.inputChainsDiscard());
}
/** {@inheritDoc} */
@Override
protected final void doScry(final List<Card> topN, final int n) {
int num = n;
for (int i = 0; i < num; i++) {
final Card c = GuiChoose.oneOrNone("Put on bottom of library.", topN);
if (c != null) {
topN.remove(c);
game.getAction().moveToBottomOfLibrary(c);
} else {
// no card chosen for the bottom
break;
}
}
num = topN.size();
for (int i = 0; i < num; i++) {
final Card c = GuiChoose.one("Put on top of library.", topN);
if (c != null) {
topN.remove(c);
game.getAction().moveToLibrary(c);
}
// no else - a card must have been chosen
}
}
/** {@inheritDoc} */
@Override
public final void sacrificePermanent(final String prompt, final List<Card> choices) {

View File

@@ -192,6 +192,10 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
this.setName(lobbyPlayer.getName());
}
public GameState getGame() { // I'll probably regret about this
return game;
}
public final PlayerStatistics getStats() {
return stats;
}
@@ -1844,35 +1848,7 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
// //////////////////////////////
// //////////////////////////////
/**
* <p>
* doScry.
* </p>
*
* @param topN
* a {@link forge.CardList} object.
* @param n
* a int.
*/
protected abstract void doScry(List<Card> topN, int n);
/**
* <p>
* scry.
* </p>
*
* @param numScry
* a int.
*/
public final void scry(int numScry) {
final List<Card> topN = new ArrayList<Card>();
final PlayerZone library = this.getZone(ZoneType.Library);
numScry = Math.min(numScry, library.size());
for (int i = 0; i < numScry; i++) {
topN.add(library.get(i));
}
this.doScry(topN, topN.size());
}
// /////////////////////////////

View File

@@ -3,6 +3,8 @@ package forge.game.player;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.tuple.ImmutablePair;
import forge.Card;
import forge.GameEntity;
import forge.card.spellability.SpellAbility;
@@ -104,4 +106,5 @@ public abstract class PlayerController {
/** Shows the card to this player*/
public abstract void reveal(String string, List<Card> cards, ZoneType zone, Player owner);
public abstract ImmutablePair<List<Card>, List<Card>> arrangeForScry(List<Card> topN);
}

View File

@@ -1,8 +1,12 @@
package forge.game.player;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.tuple.ImmutablePair;
import forge.Card;
import forge.GameEntity;
import forge.card.spellability.Spell;
@@ -228,4 +232,21 @@ public class PlayerControllerAi extends PlayerController {
// We don't know how to reveal cards to AI
}
@Override
public ImmutablePair<List<Card>, List<Card>> arrangeForScry(List<Card> topN) {
List<Card> toBottom = new ArrayList<Card>();
List<Card> toTop = new ArrayList<Card>();
for (Card c: topN) {
if (ComputerUtil.scryWillMoveCardToBottomOfLibrary(player, c))
toBottom.add(c);
else
toTop.add(c);
}
// put the rest on top in random order
Collections.shuffle(toTop);
return ImmutablePair.of(toTop, toBottom);
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
import javax.swing.JOptionPane;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import forge.Card;
import forge.GameEntity;
@@ -288,4 +289,12 @@ public class PlayerControllerHuman extends PlayerController {
message = String.format("Looking at %s's %s", owner, zone);
GuiChoose.oneOrNone(message, cards);
}
@Override
public ImmutablePair<List<Card>, List<Card>> arrangeForScry(List<Card> topN) {
List<Card> toBottom = GuiChoose.order("Select cards to be put on the bottom of your library", "Cards to put on the bottom", -1, topN, null, null);
topN.removeAll(toBottom);
List<Card> toTop = topN.isEmpty() ? null : GuiChoose.order("Arrange cards to be put on top of your library", "Cards arranged", 0, topN, null, null);
return ImmutablePair.of(toTop, toBottom);
}
}