package com.vdom.players;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import com.vdom.api.ActionCard;
import com.vdom.api.Card;
import com.vdom.api.GameType;
import com.vdom.api.TreasureCard;
import com.vdom.api.VictoryCard;
import com.vdom.core.BasePlayer;
import com.vdom.core.Cards;
import com.vdom.core.Game;
import com.vdom.core.MoveContext;
public class VDomPlayerSarah extends BasePlayer {
protected Random rand = new Random(System.currentTimeMillis());
protected static final int earlyGame = 5;
protected static final int MAX_OF_ONE_ACTION_CARD = 4;
protected int earlyCardBuyCount;
protected boolean alwaysBuyProvince;
protected boolean buyEstates;
protected boolean favorSilverGoldPlat;
protected int silverMax;
protected Card[] valuedCards;
protected int actionCardMax;
protected Card[] earlyCardBuys;
protected int earlyCardBuyMax;
protected boolean onlyBuyEarlySingle;
protected int throneRoomsAndKingsCourtsMax = 2;
protected boolean improvise = false;
protected Card[] trashCards;
@Override
public boolean isAi() {
return true;
}
public void setupGameVariables(GameType gameType, Card[] cardsInPlay) {
trashCards = new Card[] { Cards.curse, Cards.estate, Cards.copper, Cards.rats, Cards.overgrownEstate, Cards.hovel, Cards.abandonedMine, Cards.ruinedLibrary, Cards.ruinedMarket, Cards.ruinedVillage, Cards.survivors, Cards.virtualRuins };
valuedCards = new Card[] { Cards.torturer, Cards.bazaar, Cards.masquerade, Cards.ghostShip, Cards.wharf, Cards.smithy, Cards.harem, Cards.adventurer,
Cards.shantyTown, Cards.festival, Cards.moneyLender, Cards.venture, Cards.tournament, Cards.miningVillage, Cards.mint, Cards.farmingVillage,
Cards.kingsCourt, Cards.jester, Cards.youngWitch, Cards.goons, Cards.monument, Cards.bishop, Cards.hamlet, Cards.fortuneTeller, Cards.watchTower,
Cards.familiar, Cards.duke, Cards.platinum, Cards.gold, Cards.silver };
improvise = false;
midGame = 12;
actionCardMax = 12;
alwaysBuyProvince = true;
// buyEstates = true;
buyEstates = false;
favorSilverGoldPlat = true;
onlyBuyEarlySingle = false;
earlyCardBuys = new Card[] { Cards.militia, Cards.seaHag, Cards.familiar, Cards.youngWitch, Cards.thief, Cards.pirateShip, Cards.rabble, Cards.goons,
Cards.fortuneTeller, Cards.jester };
earlyCardBuyCount = 1;
silverMax = 4;
if (gameType == GameType.BigMoney || gameType == GameType.SizeDistortion || gameType == GameType.VictoryDance || gameType == GameType.SecretSchemes
|| gameType == GameType.BestWishes || gameType == GameType.RandomIntrigue || gameType == GameType.Underlings || gameType == GameType.HighSeas
|| gameType == GameType.BuriedTreasure || gameType == GameType.GiveAndTake) {
alwaysBuyProvince = false;
}
if (gameType == GameType.Underlings || gameType == GameType.Repetition) {
buyEstates = false;
}
if (gameType == GameType.FirstGame || gameType == GameType.RandomBaseGame || gameType == GameType.VictoryDance || gameType == GameType.HandMadness
|| gameType == GameType.Underlings) {
silverMax = 5;
}
int numCornucopia = 0;
for (final Card card : cardsInPlay) {
if (card.getExpansion() != null && card.getExpansion().equals("Cornucopia")) {
numCornucopia++;
}
}
if (gameType == GameType.BigMoney || gameType == GameType.VillageSquare || gameType == GameType.SecretSchemes || numCornucopia >= 5) {
favorSilverGoldPlat = false;
}
if (gameType == GameType.FirstGame) {
midGame = 12;
valuedCards = new Card[] { Cards.cellar, Cards.militia, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.BigMoney) {
midGame = 20;
earlyCardBuyMax = 2;
valuedCards = new Card[] { Cards.feast, Cards.laboratory, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.Interaction) {
midGame = 12;
earlyCardBuyMax = 2;
} else if (gameType == GameType.SizeDistortion) {
midGame = 14;
valuedCards = new Card[] { Cards.feast, Cards.chapel, Cards.laboratory, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.VillageSquare) {
midGame = 12;
actionCardMax = 7;
valuedCards = new Card[] { Cards.smithy, Cards.festival, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.Repetition) {
earlyCardBuyMax = 2;
} else if (gameType == GameType.GiveAndTake) {
actionCardMax = 10;
valuedCards = new Card[] { Cards.fishingVillage, Cards.library, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.Shipwrecks) {
midGame = 18;
valuedCards = new Card[] { Cards.treasury, Cards.pearlDiver, Cards.ghostShip, Cards.seaHag, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.RandomSeaside) {
midGame = 16;
earlyCardBuyMax = 1;
actionCardMax = 16;
valuedCards = new Card[] { Cards.warehouse, Cards.wharf, Cards.bazaar, Cards.pearlDiver, Cards.ghostShip, Cards.platinum, Cards.gold,
Cards.silver };
} else if (gameType == GameType.ReachForTomorrow) {
earlyCardBuys = new Card[] { Cards.seaHag };
earlyCardBuyMax = 1;
midGame = 14;
actionCardMax = 8;
valuedCards = new Card[] { Cards.treasureMap, Cards.ghostShip, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.BuriedTreasure) {
midGame = 14;
earlyCardBuys = new Card[] { Cards.treasureMap };
// onlyBuyEarlySingle = true;
earlyCardBuyMax = 2;
actionCardMax = 12;
valuedCards = new Card[] { Cards.warehouse, Cards.treasureMap, Cards.wharf, Cards.pearlDiver, Cards.fishingVillage, Cards.platinum,
Cards.gold, Cards.silver };
} else if (gameType == GameType.Beginners) {
// bank
// countingHouse
// expand
// goons
// monument
// rabble
// royalSeal
// venture
// watchTower
// workersVillage
improvise = true;
} else if (gameType == GameType.FriendlyInteractive) {
// bishop
// city
// contraband
// forge
// hoard
// peddler
// royalSeal
// tradeRoute
// vault
// workersVillage
improvise = true;
} else if (gameType == GameType.BigActions) {
// city
// expand
// grandMarket
// kingsCourt
// loan
// mint
// quarry
// rabble
// talisman
// vault
improvise = true;
} else if (gameType == GameType.BiggestMoney) {
// bank
// grandMarket
// mint
// royalSeal
// venture
// adventurer
// laboratory
// mine
// moneyLender
// spy
earlyCardBuys = new Card[] { Cards.moneyLender };
earlyCardBuyMax = 1;
midGame = 14;
actionCardMax = 5;
valuedCards = new Card[] { Cards.laboratory, Cards.adventurer, Cards.venture, Cards.royalSeal, Cards.mint, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.TheKingsArmy) {
// expand
// goons
// kingsCourt
// rabble
// vault
// bureaucrat
// councilRoom
// moat
// spy
// village
improvise = true;
} else if (gameType == GameType.TheGoodLife) {
// contraband
// countingHouse
// hoard
// monument
// mountebank
// bureaucrat
// cellar
// chancellor
// gardens
// village
earlyCardBuys = new Card[] { Cards.mountebank };
earlyCardBuyMax = 1;
midGame = 15;
actionCardMax = 6;
valuedCards = new Card[] { Cards.countingHouse, Cards.contraband, Cards.bureaucrat, Cards.chancellor, Cards.mountebank, Cards.platinum, Cards.gold, Cards.silver, Cards.copper };
trashCards = new Card[] { Cards.curse, Cards.estate };
} else if (gameType == GameType.PathToVictory) {
// bishop
// countingHouse
// goons
// monument
// peddler
// baron
// harem
// pawn
// shantyTown
// upgrade
improvise = true;
} else if (gameType == GameType.AllAlongTheWatchtower) {
// hoard
// talisman
// tradeRoute
// vault
// watchTower
// bridge
// greatHall
// miningVillage
// pawn
// torturer
earlyCardBuys = new Card[] { Cards.torturer };
earlyCardBuyMax = 1;
midGame = 14;
actionCardMax = 7;
valuedCards = new Card[] { Cards.watchTower, Cards.miningVillage, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.LuckySeven) {
// bank
// expand
// forge
// kingsCourt
// vault
// bridge
// coppersmith
// swindler
// tribute
// wishingWell
improvise = true;
} else if (gameType == GameType.BountyOfTheHunt) {
// harvest
// hornOfPlenty
// huntingParty
// menagerie
// tournament
// cellar
// festival
// militia
// moneyLender
// smithy
earlyCardBuys = new Card[] { Cards.militia };
earlyCardBuyMax = 1;
midGame = 14;
actionCardMax = 5;
valuedCards = new Card[] { Cards.festival, Cards.moneyLender, Cards.menagerie, Cards.harvest, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.BadOmens) {
// fortuneTeller
// hamlet
// hornOfPlenty
// jester
// remake
// adventurer
// bureaucrat
// laboratory
// spy
// throneRoom
midGame = 15;
actionCardMax = 7;
valuedCards = new Card[] { Cards.jester, Cards.throneRoom, Cards.fortuneTeller, Cards.laboratory, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.TheJestersWorkshop) {
// fairgrounds
// farmingVillage
// horseTraders
// jester
// youngWitch
// feast
// laboratory
// market
// remodel
// workshop
// addPile(banePile = new Pile(Cards.chancellor,
// kingdomCardPileSize)
earlyCardBuys = new Card[] { Cards.youngWitch };
earlyCardBuyMax = 1;
midGame = 14;
actionCardMax = 5;
valuedCards = new Card[] { Cards.jester, Cards.chancellor, Cards.farmingVillage, Cards.market, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.LastLaughs) {
// farmingVillage
// harvest
// horseTraders
// huntingParty
// jester
// minion
// nobles
// pawn
// steward
// swindler
improvise = true;
} else if (gameType == GameType.TheSpiceOfLife) {
// fairgrounds
// hornOfPlenty
// remake
// tournament
// youngWitch
// coppersmith
// courtyard
// greatHall
// miningVillage
// tribute
// addPile(banePile = new Pile(Cards.wishingWell,
// kingdomCardPileSize)
earlyCardBuys = new Card[] { Cards.youngWitch, Cards.wishingWell };
earlyCardBuyMax = 2;
midGame = 15;
actionCardMax = 5;
valuedCards = new Card[] { Cards.jester, Cards.wishingWell, Cards.miningVillage, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.SmallVictories) {
// fortuneTeller
// hamlet
// huntingParty
// remake
// tournament
// conspirator
// duke
// greatHall
// harem
// pawn
midGame = 15;
actionCardMax = 10;
valuedCards = new Card[] { Cards.fortuneTeller, Cards.greatHall, Cards.harem, Cards.duke, Cards.pawn, Cards.platinum, Cards.gold, Cards.silver };
} else if (gameType == GameType.RandomCornucopia) {
midGame = 15;
actionCardMax = 6;
valuedCards = new Card[] { Cards.tournament, Cards.jester, Cards.youngWitch, Cards.hamlet, Cards.fortuneTeller, Cards.platinum, Cards.gold, Cards.silver };
} else {
improvise = true;
actionCardMax = 5;
}
}
@Override
public String getPlayerName() {
return getPlayerName(Game.maskPlayerNames);
}
@Override
public String getPlayerName(boolean maskName) {
return maskName ? "Player " + (playerNumber + 1) : "Sarah";
}
@Override
public Card doAction(MoveContext context) {
ArrayList<ActionCard> actionCards = context.getPlayer().getActionsInHand();
// don't play rats
if (game.isCardInGame(Cards.rats)) {
for (Iterator<ActionCard> it = actionCards.iterator(); it.hasNext(); ) {
if (Cards.rats.equals(it.next())) {
it.remove();
}
}
}
// Pair of Treasure Maps goes first
int treasureMapCount = 0;
for (Iterator<ActionCard> it = actionCards.iterator(); it.hasNext(); ) {
if (Cards.treasureMap.equals(it.next())) {
treasureMapCount++;
it.remove();
}
}
if (treasureMapCount >= 2) {
return context.player.fromHand(Cards.treasureMap);
}
// don't play trashForced cards if no trash cards available (Apprentice, Ambassador, etc)
Card[] trashableCards = pickOutCards(context.getPlayer().getHand(), 1, getTrashCards());
if (trashableCards == null) {
for (Iterator<ActionCard> it = actionCards.iterator(); it.hasNext(); ) {
if (it.next().trashForced())
it.remove();
}
}
// play Action Cards that add more actions
for (final Card card : actionCards) {
if (context.canPlay(card)) {
ActionCard action = (ActionCard) card;
if (action.getAddActions() > 0)
return action;
}
}
if (context.player.inHand(Cards.throneRoom) && context.canPlay(Cards.throneRoom)) {
return context.player.fromHand(Cards.throneRoom);
}
//TODO: ...
//if(context.getKingsCourtsInEffect() == 0) {
if (context.player.inHand(Cards.kingsCourt) && context.canPlay(Cards.kingsCourt))
return context.player.fromHand(Cards.kingsCourt);
//}
//TODO: simple action play order list instead of just picking the most expensive card
int cost = COST_MAX;
final ArrayList<Card> randList = new ArrayList<Card>();
while (cost >= 0) {
for (final Card card : actionCards) {
if (
!context.canPlay(card) ||
card.equals(Cards.treasureMap) ||
card.getCost(context) != cost
) {
continue;
}
if(card.getCost(context) == cost) {
randList.add(card);
}
}
if (randList.size() > 0) {
return randList.get(rand.nextInt(randList.size()));
}
cost--;
}
return null;
}
public boolean shouldPassOnBuy(MoveContext context, Card card) {
return
!context.canBuy(card) ||
card instanceof ActionCard && actionCardCount >= actionCardMax ||
!favorSilverGoldPlat && (card.equals(Cards.silver) || card.equals(Cards.gold) || card.equals(Cards.platinum)) ||
card.equals(Cards.curse) ||
card.equals(Cards.copper) ||
card.equals(Cards.rats) ||
card.equals(Cards.potion) && !shouldBuyPotion() ||
card.equals(Cards.throneRoom) && throneRoomAndKingsCourtCount >= throneRoomsAndKingsCourtsMax ||
card.equals(Cards.kingsCourt) && throneRoomAndKingsCourtCount >= throneRoomsAndKingsCourtsMax ||
context.getEmbargos(card) > 0 ||
!(card instanceof ActionCard) && !(card instanceof TreasureCard);
}
@Override
public Card doBuy(MoveContext context) {
final int coinAvailableForBuy = context.getCoinAvailableForBuy();
if (earlyCardBuyCount < earlyCardBuyMax) {
final ArrayList<Card> randList = new ArrayList<Card>();
for (final Card card : earlyCardBuys) {
if (context.canBuy(card)) { // && (coinAvailableForBuy == card.getCost()) {
randList.add(card);
}
}
if (randList.size() > 0) {
earlyCardBuyCount++;
return randList.get(rand.nextInt(randList.size()));
}
}
if (onlyBuyEarlySingle && earlyCardBuyCount < earlyCardBuyMax) {
return null;
}
if (context.canBuy(Cards.colony)) {
return Cards.colony;
}
if (favorSilverGoldPlat && coinAvailableForBuy >= 9 && context.canBuy(Cards.platinum) && turnCount < midGame) {
return Cards.platinum;
}
if ((alwaysBuyProvince || turnCount > earlyGame) && context.canBuy(Cards.province)) {
return Cards.province;
}
if (turnCount > midGame && coinAvailableForBuy <= 7 && context.canBuy(Cards.duchy) && rand.nextInt(3) == 0) {
if(context.getEmbargos(Cards.duchy) == 0) {
return Cards.duchy;
}
}
if (buyEstates) {
if (turnCount > midGame && coinAvailableForBuy <= 2 && context.canBuy(Cards.estate)) {
if(context.getEmbargos(Cards.estate) == 0) {
return Cards.estate;
}
}
}
if(context.canBuy(Cards.grandMarket) && rand.nextInt(MAX_OF_ONE_ACTION_CARD * 2) < inHandCount(Cards.grandMarket)) {
return Cards.grandMarket;
}
final double silverLine = .5d;
if (favorSilverGoldPlat) {
if (game.pileSize(Cards.silver) > 0 && coinAvailableForBuy >= 3 && coinAvailableForBuy <= silverMax && rand.nextFloat() > silverLine) {
if(context.getEmbargos(Cards.silver) == 0) {
return Cards.silver;
}
}
if (game.pileSize(Cards.gold) > 0 && coinAvailableForBuy >= 6 && coinAvailableForBuy <= 6 && rand.nextFloat() > silverLine) {
if(context.getEmbargos(Cards.gold) == 0) {
return Cards.gold;
}
}
}
Card ret = null;
if(!improvise) {
ret = bestBuy(coinAvailableForBuy, context, valuedCards);
if(ret != null) {
return ret;
}
}
ret = bestBuy(coinAvailableForBuy, context, context.getCardsInGame());
if(ret != null) {
return ret;
}
if (context.canBuy(Cards.platinum)) {
return Cards.platinum;
}
if (context.canBuy(Cards.gold)) {
if(context.getEmbargos(Cards.gold) == 0) {
return Cards.gold;
}
}
if (context.canBuy(Cards.silver)) {
if(context.getEmbargos(Cards.silver) == 0) {
return Cards.silver;
}
}
return null;
}
@Override
public ArrayList<TreasureCard> treasureCardsToPlayInOrder(MoveContext context) {
if(context.cardInGame(Cards.grandMarket)) {
final ArrayList<TreasureCard> cards = new ArrayList<TreasureCard>();
int coinWithoutCopper = 0;
for(final Card c : context.getPlayer().getHand()) {
if(c instanceof TreasureCard && !c.equals(Cards.copper)) {
final TreasureCard tc = (TreasureCard) c;
cards.add(tc);
coinWithoutCopper += tc.getValue();
}
}
if(coinWithoutCopper >= Cards.grandMarket.getCost(context)) {
return cards;
}
}
return super.treasureCardsToPlayInOrder(context);
}
@Override
public void newGame(MoveContext context) {
super.newGame(context);
earlyCardBuyCount = 0;
setupGameVariables(context.getGameType(), context.getCardsInGame());
}
@Override
public Card[] getTrashCards() {
return trashCards;
}
public Card bestBuy(int coinAvailableForBuy, MoveContext context, Card[] cards) {
// Try to buy valued cards...
int cost = coinAvailableForBuy;
while (cost >= 0) {
final ArrayList<Card> randList = new ArrayList<Card>();
for (final Card card : cards) {
if (card.getCost(context) != cost) {
continue;
}
if(shouldPassOnBuy(context, card)) {
continue;
}
final int currentCount = inHandCount(card);
if(isOnlyTreasure(card) || card instanceof VictoryCard || currentCount == 0 || rand.nextInt(MAX_OF_ONE_ACTION_CARD) < currentCount) {
randList.add(card);
}
}
if (randList.size() > 0) {
return randList.get(rand.nextInt(randList.size()));
}
cost--;
}
return null;
}
public Card[] chapel_cardsToTrash(MoveContext context) {
ArrayList<Card> cards = new ArrayList<Card>();
for (Card card : context.player.getHand()) {
if (card.equals(Cards.estate) || card.equals(Cards.curse)) {
cards.add(card);
}
}
if (getCurrencyTotal(context) >= 3) {
for (Card card : context.player.getHand()) {
if (card.equals(Cards.copper)) {
cards.add(card);
}
}
}
while (cards.size() > 4) {
cards.remove(cards.size() - 1);
}
return cards.toArray(new Card[0]);
}
}