mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
7
forge-gui/res/cardsfolder/a/agent_of_acquisitions.txt
Normal file
7
forge-gui/res/cardsfolder/a/agent_of_acquisitions.txt
Normal 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 can’t 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 can’t draft cards for the rest of this draft round. (You may look at booster packs passed to you.)
|
||||
7
forge-gui/res/cardsfolder/c/cogwork_librarian.txt
Normal file
7
forge-gui/res/cardsfolder/c/cogwork_librarian.txt
Normal 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.
|
||||
7
forge-gui/res/cardsfolder/l/leovolds_operative.txt
Normal file
7
forge-gui/res/cardsfolder/l/leovolds_operative.txt
Normal 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 Leovold’s Operative face up.\n\nAs you draft a card, you may draft an additional card from that booster pack. If you do, turn Leovold’s Operative face down, then pass the next booster pack without drafting a card from it. (You may look at that booster pack.)
|
||||
10
forge-gui/res/cardsfolder/s/spire_phantasm.txt
Normal file
10
forge-gui/res/cardsfolder/s/spire_phantasm.txt
Normal 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 card’s 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 card’s 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.
|
||||
@@ -248,6 +248,7 @@ Hold the Perimeter
|
||||
Hymn of the Wilds
|
||||
Illusionary Informant
|
||||
Incendiary Dissent
|
||||
Leovold's Operative
|
||||
Natural Unity
|
||||
Noble Banneret
|
||||
Paliano Vanguard
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,11 +513,16 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
|
||||
recordDraftPick(thisBooster, c);
|
||||
|
||||
// TODO Agent of Acquisitions activation to loop the entire pack?
|
||||
|
||||
this.localPlayer.draftCard(c);
|
||||
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++;
|
||||
this.passPacks();
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 card’s 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 can’t 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
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user