Add Spire Phantasm, Agent of Acquisitions, Cogwork Librarian, Leovold's Operative (#5437)

* Next few Draft cards

* Code review fixes

* Add Spire Phantasm

* Add Agent of Acquisitions, Cogwork Librarian, Leovold's Operative

* Some small fixes

* Getting closer

* Now the UI is updating

* Switch DraftPack to a delegate class

* Fix agent of acquisitions when AI drafts it
This commit is contained in:
Chris H
2024-06-22 06:42:29 -04:00
committed by GitHub
parent e0d8bcf490
commit d4469ca736
16 changed files with 384 additions and 58 deletions

View File

@@ -174,6 +174,21 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
return cp != null && !cp.isEmpty();
}
public PaperCard removeCardName(String name) {
PaperCard paperCard;
for (Entry<DeckSection, CardPool> kv : parts.entrySet()) {
CardPool pool = kv.getValue();
for (Entry<PaperCard, Integer> pc : pool) {
if (pc.getKey().getName().equalsIgnoreCase(name)) {
paperCard = pc.getKey();
pool.remove(paperCard);
return paperCard;
}
}
}
return null;
}
// will return new if it was absent
public CardPool getOrCreate(DeckSection deckSection) {
CardPool p = get(deckSection);

View File

@@ -2129,6 +2129,9 @@ public class CardProperty {
List<String> nameList = Lists.newArrayList(names.split(";"));
return nameList.contains(card.getName());
} else if (property.equals("NotedGuessPhantasm")) {
String names = sourceController.getDraftNotes().get("Spire Phantasm");
return names != null && !names.isEmpty();
} else if (property.equals("NotedTypes")) {
// Should Paliano Vanguard be hardcoded here or part of the property?
String types = sourceController.getDraftNotes().get("Paliano Vanguard");

View File

@@ -116,12 +116,21 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> i
// can only draft one at a time, regardless of the requested quantity
PaperCard card = items.iterator().next().getKey();
if (boosterDraft.getHumanPlayer().shouldSkipThisPick()) {
System.out.println(card + " not drafted because we're skipping this pick");
showPackToDraft();
return;
}
// Verify if card is in the activate pack?
this.getDeckManager().addItem(card, 1);
// get next booster pack
// get next booster pack if we aren't picking again from this pack
this.boosterDraft.setChoice(card);
showPackToDraft();
}
protected void showPackToDraft() {
boolean nextChoice = this.boosterDraft.hasNextChoice();
ItemPool<PaperCard> pool = null;
if (nextChoice) {

View File

@@ -58,10 +58,15 @@ public class BoosterDraftTest implements IBoosterDraft {
return result;
}
/** {@inheritDoc} */
/**
* {@inheritDoc}
*
* @return
*/
@Override
public void setChoice(final PaperCard c) {
public boolean setChoice(final PaperCard c) {
System.out.println(c.getName());
return false;
}
@Override

View File

@@ -0,0 +1,7 @@
Name:Agent of Acquisitions
ManaCost:2
Types:Artifact Creature Construct
PT:2/1
Draft:Draft CARDNAME face up.
Draft:Instead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn CARDNAME face down and you cant draft cards for the rest of this draft round. (You may look at booster packs passed to you.)
Oracle:Draft Agent of Acquisitions face up.\nInstead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn Agent of Acquisitions face down and you cant draft cards for the rest of this draft round. (You may look at booster packs passed to you.)

View File

@@ -0,0 +1,7 @@
Name:Cogwork Librarian
ManaCost:4
Types:Artifact Creature Construct
PT:3/3
Draft:Draft CARDNAME face up.
Draft:As you draft a card, you may draft an additional card from that booster pack. If you do, put CARDNAME into that booster pack.
Oracle:Draft Cogwork Librarian face up.\nAs you draft a card, you may draft an additional card from that booster pack. If you do, put Cogwork Librarian into that booster pack.

View File

@@ -0,0 +1,7 @@
Name:Leovold's Operative
ManaCost:2 G
Types:Creature Elf Rogue
PT:3/2
Draft:Draft CARDNAME face up.
Draft:As you draft a card, you may draft an additional card from that booster pack. If you do, turn CARDNAME face down, then pass the next booster pack without drafting a card from it. (You may look at that booster pack.)
Oracle:Draft Leovolds Operative face up.\n\nAs you draft a card, you may draft an additional card from that booster pack. If you do, turn Leovolds Operative face down, then pass the next booster pack without drafting a card from it. (You may look at that booster pack.)

View File

@@ -0,0 +1,10 @@
Name:Spire Phantasm
ManaCost:2 U U
Types:Creature Gargoyle Illusion
PT:3/2
Draft:Reveal CARDNAME as you draft it.
Draft:The next time a player drafts a card from this booster pack, guess that cards name. Then that player reveals the drafted card.
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+NotedGuessPhantasm | Execute$ DrawACard | TriggerDescription$ When CARDNAME enters the battlefield, if you guessed correctly for a card named Spire Phantasm, draw a card.
SVar:DrawACard:DB$ Draw | Amount$ 1
Oracle:Reveal Spire Phantasm as you draft it. The next time a player drafts a card from this booster pack, guess that cards name. Then that player reveals the drafted card.\nFlying\nWhen Spire Phantasm enters the battlefield, if you guessed correctly for a card named Spire Phantasm, draw a card.

View File

@@ -248,6 +248,7 @@ Hold the Perimeter
Hymn of the Wilds
Illusionary Informant
Incendiary Dissent
Leovold's Operative
Natural Unity
Noble Banneret
Paliano Vanguard

View File

@@ -221,31 +221,31 @@ ScryfallCode=CNS
210 R Reflecting Pool @Fred Fields
[Draft Matters]
#1 Advantageous Proclamation|CNS
1 Advantageous Proclamation|CNS
1 Aether Searcher|CNS
#1 Agent of Acquisitions|CNS
1 Agent of Acquisitions|CNS
#1 Backup Plan|CNS
1 Brago's Favor|CNS
#1 Canal Dredger|CNS
1 Cogwork Grinder|CNS
#1 Cogwork Librarian|CNS
1 Cogwork Librarian|CNS
1 Cogwork Spy|CNS
1 Cogwork Tracker|CNS
#1 Deal Broker|CNS
#1 Double Stroke|CNS
1 Double Stroke|CNS
1 Immediate Action|CNS
#1 Iterative Analysis|CNS
1 Iterative Analysis|CNS
#1 Lore Seeker|CNS
1 Lurking Automaton|CNS
1 Muzzio's Preparations|CNS
1 Paliano, the High City|CNS
#1 Power Play|CNS
1 Power Play|CNS
1 Secret Summoning|CNS
1 Secrets of Paradise|CNS
#1 Sentinel Dispatch|CNS
#1 Unexpected Potential|CNS
1 Sentinel Dispatch|CNS
1 Unexpected Potential|CNS
1 Whispergear Sneak|CNS
#1 Worldknit|CNS
1 Worldknit|CNS
[tokens]
w_1_1_spirit_flying

View File

@@ -50,6 +50,7 @@ import java.util.*;
*/
public class BoosterDraft implements IBoosterDraft {
private static int nextId = 0;
private static final int N_PLAYERS = 8;
public static final String FILE_EXT = ".draft";
private final List<LimitedPlayer> players = new ArrayList<>();
@@ -371,9 +372,11 @@ public class BoosterDraft implements IBoosterDraft {
}
public void initializeBoosters() {
for (Supplier<List<PaperCard>> boosterRound : this.product) {
for (int i = 0; i < N_PLAYERS; i++) {
this.players.get(i).receiveUnopenedPack(boosterRound.get());
DraftPack pack = new DraftPack(boosterRound.get(), nextId++);
this.players.get(i).receiveUnopenedPack(pack);
}
}
startRound();
@@ -437,8 +440,10 @@ public class BoosterDraft implements IBoosterDraft {
adjust = 0;
}
// Do any players have a Canal Dredger?
for (int i = 0; i < N_PLAYERS; i++) {
List<PaperCard> passingPack = this.players.get(i).passPack();
DraftPack passingPack = this.players.get(i).passPack();
if (passingPack == null)
continue;
@@ -463,7 +468,17 @@ public class BoosterDraft implements IBoosterDraft {
for (int i = 1; i < N_PLAYERS; i++) {
LimitedPlayer pl = this.players.get(i);
// TODO Agent of Acquisitions activation to loop the entire pack?
pl.draftCard(pl.chooseCard());
if (pl.shouldSkipThisPick()) {
continue;
}
// Computer player has an empty pack or is passing the pack
Boolean passPack;
do {
// THe player holding onto the pack to draft an extra card... Do it now.
passPack = pl.draftCard(pl.chooseCard());
} while (passPack != null && !passPack);
}
}
@@ -473,6 +488,7 @@ public class BoosterDraft implements IBoosterDraft {
@Override
public boolean isRoundOver() {
// Really should check if all packs are empty, but this is a good enough approximation
return packsInDraft == 0;
}
@@ -483,10 +499,12 @@ public class BoosterDraft implements IBoosterDraft {
/**
* {@inheritDoc}
*
* @return
*/
@Override
public void setChoice(final PaperCard c) {
final List<PaperCard> thisBooster = this.localPlayer.nextChoice();
public boolean setChoice(final PaperCard c) {
final DraftPack thisBooster = this.localPlayer.nextChoice();
if (!thisBooster.contains(c)) {
throw new RuntimeException("BoosterDraft : setChoice() error - card not found - " + c
@@ -495,12 +513,17 @@ public class BoosterDraft implements IBoosterDraft {
recordDraftPick(thisBooster, c);
// TODO Agent of Acquisitions activation to loop the entire pack?
this.localPlayer.draftCard(c);
this.currentBoosterPick++;
boolean passPack = this.localPlayer.draftCard(c);
if (passPack) {
// Leovolds Operative and Cogwork Librarian get to draft an extra card.. How do we do that?
this.passPacks();
}
this.currentBoosterPick++;
// Return whether or not we passed, but that the UI always needs to refresh
// But returning might be useful for testing or other things?
return passPack;
}
private static String choosePackByPack(final List<String> setz, int packs) {
StringBuilder sb = new StringBuilder();

View File

@@ -3,7 +3,6 @@ package forge.gamemodes.limited;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.DeckHints;
import forge.card.MagicColor;
@@ -114,6 +113,22 @@ public class CardRanker {
return cardScores;
}
public static List<PaperCard> getOrderedRawScores(List<PaperCard> cards) {
List<Pair<Double, PaperCard>> cardScores = Lists.newArrayList();
for(PaperCard card : cards) {
cardScores.add(Pair.of(getRawScore(card), card));
}
cardScores.sort(Collections.reverseOrder(new CardRankingComparator()));
List<PaperCard> rankedCards = new ArrayList<>(cardScores.size());
for (Pair<Double, PaperCard> pair : cardScores) {
rankedCards.add(pair.getValue());
}
return rankedCards;
}
public static double getRawScore(PaperCard card) {
Double rawScore;
if (MagicColor.Constant.BASIC_LANDS.contains(card.getName())) {

View File

@@ -0,0 +1,49 @@
package forge.gamemodes.limited;
import com.google.common.collect.ForwardingList;
import forge.item.PaperCard;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
public class DraftPack extends ForwardingList<PaperCard> {
private final List<PaperCard> cards;
private final int id;
private LimitedPlayer passedFrom;
private Map.Entry<LimitedPlayer, PaperCard> awaitingGuess;
public DraftPack(List<PaperCard> cards, int id) {
this.cards = cards;
this.id = id;
}
public int getId() {
return id;
}
public LimitedPlayer getPassedFrom() {
return passedFrom;
}
public void setPassedFrom(LimitedPlayer passedFrom) {
this.passedFrom = passedFrom;
}
public void setAwaitingGuess(LimitedPlayer player, PaperCard card) {
this.awaitingGuess = new AbstractMap.SimpleEntry<>(player, card);
}
public Map.Entry<LimitedPlayer, PaperCard> getAwaitingGuess() {
return awaitingGuess;
}
public void resetAwaitingGuess() {
this.awaitingGuess = null;
}
@Override
protected List<PaperCard> delegate() {
return cards;
}
}

View File

@@ -34,7 +34,7 @@ public interface IBoosterDraft {
int getRound();
CardPool nextChoice();
void setChoice(PaperCard c);
boolean setChoice(PaperCard c);
boolean hasNextChoice();
boolean isRoundOver();
Deck[] getDecks(); // size 7, all the computers decks
@@ -49,4 +49,6 @@ public interface IBoosterDraft {
IDraftLog getDraftLog();
LimitedPlayer getNeighbor(LimitedPlayer p, boolean left);
LimitedPlayer getPlayer(int i);
}

View File

@@ -21,15 +21,15 @@ public class LimitedPlayer {
protected Deck deck;
protected PaperCard lastPick;
protected Queue<List<PaperCard>> packQueue;
protected Queue<List<PaperCard>> unopenedPacks;
protected Queue<DraftPack> packQueue;
protected Queue<DraftPack> unopenedPacks;
protected List<PaperCard> removedFromCardPool = new ArrayList<>();
private static final int CantDraftThisRound = 1;
private static final int SpyNextCardDrafted = 1 << 1;
private static final int ReceiveLastCard = 1 << 2;
private static final int CanRemoveAfterDraft = 1 << 3;
private static final int CanTradeAfterDraft = 1 << 4;
private static final int AgentAcquisitionsCanDraftAll = 1;
private static final int AgentAcquisitionsIsDraftingAll = 1 << 1;
private static final int AgentAcquisitionsSkipDraftRound = 1 << 2;
private static final int CogworkLibrarianExtraDraft = 1 << 3;
private static final int CogworkLibrarianReturnLibrarian = 1 << 4;
private static final int AnimusRemoveFromPool = 1 << 5;
private static final int NobleBanneretActive = 1 << 6;
private static final int PalianoVanguardActive = 1 << 7;
@@ -37,6 +37,10 @@ public class LimitedPlayer {
private static final int SearcherNoteNext = 1 << 9;
private static final int WhispergearBoosterPeek = 1 << 10;
private static final int IllusionaryInformantPeek = 1 << 11;
private static final int LeovoldsOperativeCanExtraDraft = 1 << 12;
private static final int LeovoldsOperativeExtraDraft = 1 << 13;
private static final int LeovoldsOperativeSkipNext = 1 << 14;
private static final int SpyNextCardDrafted = 1 << 15;
private int playerFlags = 0;
@@ -88,24 +92,25 @@ public class LimitedPlayer {
return null;
}
public boolean draftCard(PaperCard bestPick) {
public Boolean draftCard(PaperCard bestPick) {
return draftCard(bestPick, DeckSection.Sideboard);
}
public boolean draftCard(PaperCard bestPick, DeckSection section) {
public Boolean draftCard(PaperCard bestPick, DeckSection section) {
if (bestPick == null) {
return false;
return null;
}
List<PaperCard> chooseFrom = packQueue.peek();
DraftPack chooseFrom = packQueue.peek();
if (chooseFrom == null) {
return false;
return null;
}
boolean removedFromPool = false;
boolean alreadyRevealed = false;
boolean passPack = true;
chooseFrom.remove(bestPick);
lastPick = lastPick;
lastPick = bestPick;
draftedThisRound++;
@@ -134,9 +139,10 @@ public class LimitedPlayer {
recordRemoveFromDraft(bestPick, choice);
}
LimitedPlayer fromPlayer = receivedFrom();
LimitedPlayer fromPlayer = chooseFrom.getPassedFrom();
// If the previous player has an active Cogwork Spy, show them this card
if ((fromPlayer.playerFlags & SpyNextCardDrafted) == SpyNextCardDrafted) {
if (fromPlayer != null && (fromPlayer.playerFlags & SpyNextCardDrafted) == SpyNextCardDrafted) {
if (fromPlayer instanceof LimitedPlayerAI) {
// I'm honestly not sure what the AI would do by learning this information
// But just log that a reveal "happened"
@@ -169,9 +175,73 @@ public class LimitedPlayer {
}
}
if ((playerFlags & AgentAcquisitionsCanDraftAll) == AgentAcquisitionsCanDraftAll) {
if (handleAgentOfAcquisitions(chooseFrom, bestPick)) {
addLog(name() + " drafted the rest of the pack with Agent of Acquisitions");
playerFlags &= ~AgentAcquisitionsCanDraftAll;
playerFlags |= AgentAcquisitionsIsDraftingAll;
}
}
if ((playerFlags & AgentAcquisitionsIsDraftingAll) == AgentAcquisitionsIsDraftingAll) {
if (chooseFrom.isEmpty()) {
playerFlags &= ~AgentAcquisitionsIsDraftingAll;
playerFlags |= AgentAcquisitionsSkipDraftRound;
} else {
passPack = false;
}
}
if ((playerFlags & LeovoldsOperativeExtraDraft) == LeovoldsOperativeExtraDraft) {
if (handleLeovoldsOperative(chooseFrom, bestPick)) {
addLog(name() + " skipped their next pick with Leovold's Operative.");
playerFlags &= ~LeovoldsOperativeExtraDraft;
playerFlags |= LeovoldsOperativeSkipNext;
passPack = false;
}
}
if ((playerFlags & LeovoldsOperativeCanExtraDraft) == LeovoldsOperativeCanExtraDraft) {
if (handleLeovoldsOperative(chooseFrom, bestPick)) {
addLog(name() + " picking again with Leovold's Operative.");
playerFlags &= ~LeovoldsOperativeCanExtraDraft;
playerFlags |= LeovoldsOperativeExtraDraft;
passPack = false;
}
}
if ((playerFlags & CogworkLibrarianReturnLibrarian) == CogworkLibrarianReturnLibrarian) {
addLog(name() + " returned Cogwork Librarian to the pack.");
PaperCard librarian = deck.removeCardName("Cogwork Librarian");
// TODO The librarian needs to be removed from the UI
// We shouldn't get here unless we've drafted librarian so we should be able to find one in Deck
// If somehow we don't wellll.. we should remove the bitflag anyway
playerFlags &= ~CogworkLibrarianReturnLibrarian;
if (librarian != null) {
chooseFrom.add(librarian);
} else {
System.out.println("This shouldn't happen. We drafted a libarian but didn't remove it properly.");
}
}
if ((playerFlags & CogworkLibrarianExtraDraft) == CogworkLibrarianExtraDraft) {
if (handleCogworkLibrarian(chooseFrom, bestPick)) {
addLog(name() + " drafted an extra card with Cogwork Librarian.");
playerFlags &= ~CogworkLibrarianExtraDraft;
playerFlags |= CogworkLibrarianReturnLibrarian;
passPack = false;
}
}
if (chooseFrom.getAwaitingGuess() != null) {
comparePhantasmGuess(chooseFrom, bestPick);
}
if (removedFromPool) {
// Can we hide this from UI?
return true;
return passPack;
}
CardPool pool = deck.getOrCreate(section);
@@ -182,7 +252,7 @@ public class LimitedPlayer {
Iterable<String> draftActions = bestPick.getRules().getMainPart().getDraftActions();
if (draftActions == null || !draftActions.iterator().hasNext()) {
return true;
return passPack;
}
// Draft Actions
@@ -223,17 +293,17 @@ public class LimitedPlayer {
}
else {
if (Iterables.contains(draftActions, "You may look at the next card drafted from this booster pack.")) {
// Cogwork Spy
playerFlags |= SpyNextCardDrafted;
}
if (Iterables.contains(draftActions, "Note the player who passed CARDNAME to you.")) {
} else if (fromPlayer != null && Iterables.contains(draftActions, "Note the player who passed CARDNAME to you.")) {
// Note who passed it to you.
// If you receive last card from Canal Dredger, we need to figure out who last had the pack?
List<String> note = noted.computeIfAbsent(bestPick.getName(), k -> Lists.newArrayList());
note.add(String.valueOf(fromPlayer.order));
addLog(name() + " revealed " + bestPick.getName() + " and noted " + fromPlayer.name() + " passed it.");
} else if (Iterables.contains(draftActions, "Reveal the next card you draft and note its name.")) {
playerFlags |= SearcherNoteNext;
} else if (Iterables.contains(draftActions, "The next time a player drafts a card from this booster pack, guess that cards name. Then that player reveals the drafted card.")) {
chooseFrom.setAwaitingGuess(this, handleSpirePhantasm(chooseFrom));
}
addLog(name() + " revealed " + bestPick.getName() + " as " + name() + " drafted it.");
@@ -261,6 +331,12 @@ public class LimitedPlayer {
// Do we need to ask to use the Sneak immediately?
} else if (Iterables.contains(draftActions, "During the draft, you may turn CARDNAME face down. If you do, look at the next card drafted by a player of your choice.")) {
playerFlags |= IllusionaryInformantPeek;
} else if (Iterables.contains(draftActions, "As you draft a card, you may draft an additional card from that booster pack. If you do, put CARDNAME into that booster pack.")) {
playerFlags |= CogworkLibrarianExtraDraft;
} else if (Iterables.contains(draftActions, "As you draft a card, you may draft an additional card from that booster pack. If you do, turn CARDNAME face down, then pass the next booster pack without drafting a card from it. (You may look at that booster pack.)")) {
playerFlags |= LeovoldsOperativeExtraDraft;
} else if (Iterables.contains(draftActions, "Instead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn CARDNAME face down and you cant draft cards for the rest of this draft round. (You may look at booster packs passed to you.)")) {
playerFlags |= AgentAcquisitionsCanDraftAll;
}
}
@@ -277,32 +353,44 @@ public class LimitedPlayer {
// Mobile doesnt have a draft log yet
}
public List<PaperCard> nextChoice() {
public DraftPack nextChoice() {
return packQueue.peek();
}
public LimitedPlayer receivedFrom() {
return draft.getNeighbor(this, draft.getRound() % 2 == 0);
}
public void newPack() {
currentPack = order;
draftedThisRound = 0;
packQueue.add(unopenedPacks.poll());
playerFlags &= ~AgentAcquisitionsSkipDraftRound;
}
public void adjustPackNumber(int adjust, int numPacks) {
// I shouldn't need this since DraftPack has this info
currentPack = (currentPack + adjust + numPacks) % numPacks;
}
public List<PaperCard> passPack() {
return packQueue.poll();
public DraftPack passPack() {
DraftPack pack = packQueue.poll();
if (pack != null) {
pack.setPassedFrom(this);
}
return pack;
}
public void receiveUnopenedPack(List<PaperCard> pack) {
public boolean shouldSkipThisPick() {
boolean skipping = (playerFlags & AgentAcquisitionsSkipDraftRound) == AgentAcquisitionsSkipDraftRound || (playerFlags & LeovoldsOperativeSkipNext) == LeovoldsOperativeSkipNext;
if (skipping && (playerFlags & LeovoldsOperativeSkipNext) == LeovoldsOperativeSkipNext) {
playerFlags &= ~LeovoldsOperativeSkipNext;
}
return skipping;
}
public void receiveUnopenedPack(DraftPack pack) {
unopenedPacks.add(pack);
}
public void receiveOpenedPack(List<PaperCard> pack) {
public void receiveOpenedPack(DraftPack pack) {
packQueue.add(pack);
}
@@ -504,7 +592,7 @@ public class LimitedPlayer {
return true;
}
protected List<PaperCard> peekAtBoosterPack(int round, int playerNumber) {
protected DraftPack peekAtBoosterPack(int round, int playerNumber) {
if (draft.getRound() > round) {
// There aren't any unopened packs from earlier rounds
return null;
@@ -541,11 +629,51 @@ public class LimitedPlayer {
return true;
}
public PaperCard handleSpirePhantasm(DraftPack chooseFrom) {
if (chooseFrom.isEmpty()) {
return null;
}
return SGuiChoose.one("Guess the next card drafted from this pack", chooseFrom);
}
public boolean handleLeovoldsOperative(DraftPack pack, PaperCard drafted) {
if (Objects.equals(SGuiChoose.one("Draft an extra pick with Leovold's Operative?", Lists.newArrayList("Yes", "No")), "No")) {
return false;
}
playerFlags |= LeovoldsOperativeExtraDraft;
return true;
}
public boolean handleCogworkLibrarian(DraftPack pack, PaperCard drafted) {
return !Objects.equals(SGuiChoose.one("Draft an extra pick with Cogwork Librarian?", Lists.newArrayList("Yes", "No")), "No");
}
public boolean handleAgentOfAcquisitions(DraftPack pack, PaperCard drafted) {
return !Objects.equals(SGuiChoose.one("Draft the rest of the pack with Agent of Acquisitions?", Lists.newArrayList("Yes", "No")), "No");
}
public void comparePhantasmGuess(DraftPack pack, PaperCard drafted) {
LimitedPlayer guesser = pack.getAwaitingGuess().getKey();
PaperCard guess = pack.getAwaitingGuess().getValue();
addLog(name() + " reveals " + drafted.getName() + " from " + guesser.name() + "'s guess of " + guess.getName() + " with Spire Phantasm.");
if (guess.equals(drafted)) {
addLog(guesser.name() + " correctly guessed " + guess.getName() + " with Spire Phantasm.");
guesser.getDraftNotes().computeIfAbsent("Spire Phantasm", k -> Lists.newArrayList()).add(guess.getName());
} else {
addLog(guesser.name() + " incorrectly guessed " + guess.getName() + " with Spire Phantasm.");
}
pack.resetAwaitingGuess();
}
/*
public void addSingleBoosterPack(boolean random) {
// TODO Lore Seeker
// Generate booster pack then, insert it "before" the pack we're currently drafting from
}
*/
}

View File

@@ -12,6 +12,9 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import static forge.gamemodes.limited.CardRanker.getOrderedRawScores;
import static forge.gamemodes.limited.CardRanker.rankCardsInPack;
public class LimitedPlayerAI extends LimitedPlayer {
protected DeckColors deckCols;
@@ -26,7 +29,7 @@ public class LimitedPlayerAI extends LimitedPlayer {
return null;
}
List<PaperCard> chooseFrom = packQueue.peek();
DraftPack chooseFrom = packQueue.peek();
if (chooseFrom.isEmpty()) {
return null;
}
@@ -38,11 +41,10 @@ public class LimitedPlayerAI extends LimitedPlayer {
// TODO Archdemon of Paliano random draft while active
final ColorSet chosenColors = deckCols.getChosenColors();
final boolean canAddMoreColors = deckCols.canChoseMoreColors();
List<PaperCard> rankedCards = CardRanker.rankCardsInPack(chooseFrom, pool.toFlatList(), chosenColors, canAddMoreColors);
List<PaperCard> rankedCards = rankCardsInPack(chooseFrom, pool.toFlatList(), chosenColors, canAddMoreColors);
PaperCard bestPick = rankedCards.get(0);
if (canAddMoreColors) {
@@ -177,4 +179,47 @@ public class LimitedPlayerAI extends LimitedPlayer {
//peekAt.getLastPick();
return true;
}
@Override
public PaperCard handleSpirePhantasm(DraftPack chooseFrom) {
if (chooseFrom.isEmpty()) {
return null;
}
// Choose the card with the highest rank left
return getOrderedRawScores(chooseFrom).get(0);
}
@Override
public boolean handleLeovoldsOperative(DraftPack pack, PaperCard drafted) {
// Whats the score of the thing I just drafted?
// Whats the next card I would draft?
if (currentPack == 3) {
return true;
}
return draftedThisRound < 3;
}
@Override
public boolean handleAgentOfAcquisitions(DraftPack pack, PaperCard drafted) {
// Whats the score of the thing I just drafted?
// Whats the total score of the rest of the pack?
// How many of these cards would actually make my deck?
if (currentPack == 3) {
return true;
}
return draftedThisRound > 2 && draftedThisRound < 6;
}
@Override
public boolean handleCogworkLibrarian(DraftPack pack, PaperCard drafted) {
if (currentPack == 3) {
return true;
}
return draftedThisRound < 3;
}
}