mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
*Potential base for Partial Paris AI
This commit is contained in:
@@ -25,6 +25,8 @@ import forge.FThreads;
|
|||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.MatchController;
|
import forge.game.MatchController;
|
||||||
|
import forge.game.ai.ComputerUtil;
|
||||||
|
import forge.game.player.AIPlayer;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -47,6 +49,7 @@ public class InputPartialParisMulligan extends InputBase {
|
|||||||
private static final long serialVersionUID = -8112954303001155622L;
|
private static final long serialVersionUID = -8112954303001155622L;
|
||||||
|
|
||||||
private final MatchController match;
|
private final MatchController match;
|
||||||
|
private final GameState game;
|
||||||
|
|
||||||
private final List<Card> lastExiled = new ArrayList<Card>();
|
private final List<Card> lastExiled = new ArrayList<Card>();
|
||||||
private final List<Card> allExiled = new ArrayList<Card>();
|
private final List<Card> allExiled = new ArrayList<Card>();
|
||||||
@@ -54,6 +57,7 @@ public class InputPartialParisMulligan extends InputBase {
|
|||||||
public InputPartialParisMulligan(MatchController match0, Player humanPlayer) {
|
public InputPartialParisMulligan(MatchController match0, Player humanPlayer) {
|
||||||
super(humanPlayer);
|
super(humanPlayer);
|
||||||
match = match0;
|
match = match0;
|
||||||
|
game = match.getCurrentGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@@ -88,13 +92,36 @@ public class InputPartialParisMulligan extends InputBase {
|
|||||||
public final void selectButtonCancel() {
|
public final void selectButtonCancel() {
|
||||||
for(Card c : lastExiled)
|
for(Card c : lastExiled)
|
||||||
{
|
{
|
||||||
match.getCurrentGame().action.exile(c);
|
game.action.exile(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
player.drawCards(lastExiled.size()-1);
|
player.drawCards(lastExiled.size()-1);
|
||||||
allExiled.addAll(lastExiled);
|
allExiled.addAll(lastExiled);
|
||||||
lastExiled.clear();
|
lastExiled.clear();
|
||||||
|
|
||||||
|
final List<Card> aiAllExiled = new ArrayList<Card>();
|
||||||
|
for (Player p : game.getPlayers()) {
|
||||||
|
if (!(p instanceof AIPlayer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int ppcandidates = -1;
|
||||||
|
AIPlayer ai = (AIPlayer) p;
|
||||||
|
|
||||||
|
while (ComputerUtil.wantMulligan(ai) && ppcandidates != 0) {
|
||||||
|
List<Card> cand = ComputerUtil.getPartialParisCandidates(ai);
|
||||||
|
ppcandidates = cand.size();
|
||||||
|
if(ppcandidates != 0)
|
||||||
|
{
|
||||||
|
aiAllExiled.addAll(cand);
|
||||||
|
for(Card c : cand)
|
||||||
|
{
|
||||||
|
game.action.exile(c);
|
||||||
|
}
|
||||||
|
ai.drawCards(ppcandidates-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (player.getCardsIn(ZoneType.Hand).isEmpty()) {
|
if (player.getCardsIn(ZoneType.Hand).isEmpty()) {
|
||||||
this.end();
|
this.end();
|
||||||
} else {
|
} else {
|
||||||
@@ -104,8 +131,6 @@ public class InputPartialParisMulligan extends InputBase {
|
|||||||
|
|
||||||
final void end() {
|
final void end() {
|
||||||
|
|
||||||
final GameState game = match.getCurrentGame();
|
|
||||||
|
|
||||||
for(Card c : allExiled)
|
for(Card c : allExiled)
|
||||||
{
|
{
|
||||||
game.action.moveToLibrary(c);
|
game.action.moveToLibrary(c);
|
||||||
@@ -113,17 +138,28 @@ public class InputPartialParisMulligan extends InputBase {
|
|||||||
player.shuffle();
|
player.shuffle();
|
||||||
|
|
||||||
// Computer mulligan
|
// Computer mulligan
|
||||||
//TODO: How should AI approach Partial Paris?
|
final List<Card> aiAllExiled = new ArrayList<Card>();
|
||||||
/*
|
|
||||||
for (Player p : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
if (!(p instanceof AIPlayer)) {
|
if (!(p instanceof AIPlayer)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
int ppcandidates = -1;
|
||||||
AIPlayer ai = (AIPlayer) p;
|
AIPlayer ai = (AIPlayer) p;
|
||||||
while (ComputerUtil.wantMulligan(ai)) {
|
|
||||||
ai.doMulligan();
|
while (ComputerUtil.wantMulligan(ai) && ppcandidates != 0) {
|
||||||
|
List<Card> cand = ComputerUtil.getPartialParisCandidates(ai);
|
||||||
|
ppcandidates = cand.size();
|
||||||
|
if(ppcandidates != 0)
|
||||||
|
{
|
||||||
|
aiAllExiled.addAll(cand);
|
||||||
|
for(Card c : cand)
|
||||||
|
{
|
||||||
|
game.action.exile(c);
|
||||||
|
}
|
||||||
|
ai.drawCards(ppcandidates-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
// Human Leylines & Chancellors
|
// Human Leylines & Chancellors
|
||||||
ButtonUtil.reset();
|
ButtonUtil.reset();
|
||||||
@@ -158,7 +194,7 @@ public class InputPartialParisMulligan extends InputBase {
|
|||||||
if (GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) {
|
if (GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) {
|
||||||
List<Card> hand = new ArrayList<Card>(c0.getController().getCardsIn(ZoneType.Hand));
|
List<Card> hand = new ArrayList<Card>(c0.getController().getCardsIn(ZoneType.Hand));
|
||||||
for (Card c : hand) {
|
for (Card c : hand) {
|
||||||
match.getCurrentGame().getAction().exile(c);
|
game.getAction().exile(c);
|
||||||
}
|
}
|
||||||
c0.getController().drawCards(hand.size());
|
c0.getController().drawCards(hand.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ package forge.game.ai;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
@@ -30,7 +32,9 @@ import forge.CardLists;
|
|||||||
import forge.CardPredicates;
|
import forge.CardPredicates;
|
||||||
import forge.CardPredicates.Presets;
|
import forge.CardPredicates.Presets;
|
||||||
import forge.CardUtil;
|
import forge.CardUtil;
|
||||||
|
import forge.Color;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
|
import forge.card.MagicColor;
|
||||||
import forge.card.ability.AbilityUtils;
|
import forge.card.ability.AbilityUtils;
|
||||||
import forge.card.ability.ApiType;
|
import forge.card.ability.ApiType;
|
||||||
import forge.card.ability.effects.CharmEffect;
|
import forge.card.ability.effects.CharmEffect;
|
||||||
@@ -39,6 +43,7 @@ import forge.card.cost.Cost;
|
|||||||
import forge.card.cost.CostDiscard;
|
import forge.card.cost.CostDiscard;
|
||||||
import forge.card.cost.CostPart;
|
import forge.card.cost.CostPart;
|
||||||
import forge.card.cost.CostPayment;
|
import forge.card.cost.CostPayment;
|
||||||
|
import forge.card.spellability.AbilityManaPart;
|
||||||
import forge.card.spellability.AbilityStatic;
|
import forge.card.spellability.AbilityStatic;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
@@ -1227,6 +1232,67 @@ public class ComputerUtil {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Card> getPartialParisCandidates(AIPlayer ai) {
|
||||||
|
final List<Card> candidates = new ArrayList<Card>();
|
||||||
|
final List<Card> handList = ai.getCardsIn(ZoneType.Hand);
|
||||||
|
|
||||||
|
final List<Card> lands = CardLists.getValidCards(handList, "Card.Land", ai, null);
|
||||||
|
final List<Card> nonLands = CardLists.getValidCards(handList, "Card.nonLand", ai, null);
|
||||||
|
CardLists.sortByCmcDesc(nonLands);
|
||||||
|
|
||||||
|
if(lands.size() >= 3 && lands.size() <= 4)
|
||||||
|
return candidates;
|
||||||
|
|
||||||
|
if(lands.size() < 3)
|
||||||
|
{
|
||||||
|
//Not enough lands!
|
||||||
|
int tgtCandidates = Math.max(Math.abs(lands.size()-nonLands.size()), 3);
|
||||||
|
System.out.println("Partial Paris: " + ai.getName() + " lacks lands, aiming to exile " + tgtCandidates + " cards.");
|
||||||
|
|
||||||
|
for(int i=0;i<tgtCandidates;i++)
|
||||||
|
{
|
||||||
|
candidates.add(nonLands.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Too many lands!
|
||||||
|
//Init
|
||||||
|
Map<Color,List<Card>> numProducers = new HashMap<Color,List<Card>>();
|
||||||
|
for(Color col : Color.WUBRG)
|
||||||
|
{
|
||||||
|
numProducers.put(col, new ArrayList<Card>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(Card c : lands)
|
||||||
|
{
|
||||||
|
for(SpellAbility sa : c.getManaAbility())
|
||||||
|
{
|
||||||
|
AbilityManaPart abmana = sa.getManaPart();
|
||||||
|
for(Color col : Color.WUBRG)
|
||||||
|
{
|
||||||
|
if(abmana.canProduce(col.toString()))
|
||||||
|
{
|
||||||
|
numProducers.get(col).add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.print("Partial Paris: " + ai.getName() + " may exile ");
|
||||||
|
for(Card c : candidates)
|
||||||
|
{
|
||||||
|
System.out.print(c.toString() + ", ");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
if(candidates.size() < 2)
|
||||||
|
candidates.clear();
|
||||||
|
return candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean scryWillMoveCardToBottomOfLibrary(AIPlayer player, Card c) {
|
public static boolean scryWillMoveCardToBottomOfLibrary(AIPlayer player, Card c) {
|
||||||
boolean bottom = false;
|
boolean bottom = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user