mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
// /////////////////////////////
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user