Class GameContext
- All Implemented Interfaces:
Serializable,Cloneable,Comparable<GameContext>,EntityZoneTable,Inventory
GameLogic, and then save the updated state as a result of
those actions.
For example, this code starts a game between two opponents that perform random actions:
GameContext context = GameContext.fromTwoRandomDecks();
context.setBehaviour(GameContext.PLAYER_1, new PlayRandomBehaviour());
context.setBehaviour(GameContext.PLAYER_2, new PlayRandomBehaviour());
context.play();
// The game is over here.
This will start a game between two opponents that try to play a little smarter, using the Spellsource agent GameStateValueBehaviour. It will also use a pair of decks to do it.
GameContext context = new GameContext();
for (int playerId : new int[] {GameContext.PLAYER_1, GameContext.PLAYER_2}) {
context.setBehaviour(playerId, new GameStateValueProvider());
context.setDeck(playerId, Deck.randomDeck("RED", DeckFormat.getFormat("Standard")));
}
context.play();
The most important part of the game state is encoded inside the fields of the Player object in getPlayers(), like Player.getMinions(). The actions taken by the players are delegated to the Behaviour objects in getBehaviours().
Game state is composed of a variety of fields that live inside the context. These fields are:
- The
getPlayers()player objects. This includes zones, attributes on the player object itself, and some statistics fields. - The
getEnvironment()"environment variables," referring to state or memory in the game that does not live on entities. - The
getTriggers()value from thegetLogic()trigger manager. - The
DeckFormatliving ingetDeckFormat(). - The next entity ID that will be returned by
GameLogic.generateId(), which is stored inGameLogic.getIdFactory()'s values. - The seed of
GameLogic.getSeed()and the internal serialized state of theGameLogic.getRandom()random object indicating the next value. - The
getTempCards()temporary cards in a catalogue. These include cards that are generated by effects like Build-A-Beast. - The
getTurn()current turn. - The
getTurnState()current turn state. - The
getActivePlayerId()currently active player ID. - The
getActionsThisTurn()number of actions taken this turn. - The state implicit in the call stack of the currently executing action. While this cannot be inspected or easily serialized, consider that while awaiting a mulligan, battlecry choice or discover action this instance is in the middle of executing a function but still has a valid game state.
To get a copy of the state, use getGameStateCopy(); while you can access a modifiable copy of the GameState with getGameState(), you're encouraged only use the GameLogic methods (which mutate the
state stored inside this game context) in order to always have valid data.
Game actions are chosen by Behaviour objects living inside getBehaviours(). Typically, the GameLogic instance will call getActivePlayer() for the currently active player, call getBehaviours() to get the behaviour, and then call Behaviour.requestAction(GameContext, Player, List) to request which action of a list of actions the player takes. Note that this is just called as a plain
function, so the end user of the GameContext is responsible for the blocking that would occur if e.g. the
Behaviour waits on user input to answer the action request. Ordinarily, as long as the thread running GameContext doesn't do anything but process the game, blocking on user input isn't an issue; only one player may
take an action at a time.
State is mutated by the GameLogic instance. It will process a player's selected GameAction with
performAction(int, GameAction), mutating the state fields in the GameContext appropriately until it
encounters the next request for actions (e.g., once an action has been processed, when a battlecry is resolved, or
when the player must choose which card to discover). It is not necessarily dangerous to modify the game state without
using GameLogic, though doing so many break what players would expect to happen based on the text of cards.
Generally, this instance does not provide a way to "choose" actions in game. The end user of a GameContext is
expected to provide a Player instance with a Behaviour that suits the end user's needs. Override the
methods of the Behaviour to model how you'd like to behave given the information incoming to those methods.
Executing the card code is complicated, and follows the adage: Every sufficiently complex program has a poorly
implemented version of common Lisp. At a high level, players take turns generating GameAction objects, whose
GameAction.execute(GameContext, int) implementation does things like GameLogic.castSpell(int, SpellDesc, EntityReference, EntityReference, TargetSelection, boolean, GameAction) or GameLogic.summon(int, Minion, Entity, int, boolean). "spell" fields inside the CardDesc of the card currently being played
get executed by looking at their SpellArg.CLASS and creating an instance of the corresponding subclass of
Spell. Subsequent "sub-spells" are called by SpellUtils.castChildSpell(GameContext, Player, SpellDesc, Entity, Entity). Various components like ValueProvider or Condition are defined in the card JSON and
used to provide program-like functionality.
To illustrate, the key parts of the call stack of a player playing the card Novice Engineer looks like this:
- At the top of the stack:
play(). This is the main entry point for a started game and we exit this when the game is over. takeActionInTurn(), which is the core step in the game loop. To get possible play actions, we calledCard.play()on each card in the hand, which gives usGameActionobjects. Then, we calledBehaviour.requestAction(GameContext, Player, List)to get which action we wanted the player to take of the possible choices fromgetValidActions().GameAction.execute(GameContext, int), which actually starts the chain of effects for playing a card.GameLogic.summon(int, Minion, Entity, int, boolean), which summons minions.GameLogic.resolveOpeners(int, Actor)}, which resolves the battlecry written on Novice Engineer.GameLogic.castSpell(int, SpellDesc, EntityReference, EntityReference, TargetSelection, boolean, GameAction), which actually evaluates all effects, not just spells. This method will create an instance of aDrawCardSpelland eventually calls...Spell.cast(GameContext, Player, SpellDesc, Entity, List), which provides common targeting code for spell effects. The meat and bones of effects like drawing a card is done by:Spell.cast(GameContext, Player, SpellDesc, Entity, List), the method that all 200+ spells implement to actually cause effects in game.DrawCardSpelltherefore gets its...DrawCardSpell#onCast(GameContext, Player, SpellDesc, Entity, Entity)method called. In order to cause a card to be drawn, this method calls...GameLogic.drawCard(int, Entity), which is where the actual work of moving a card from thePlayer.getDeck()Spellsource.ZonesMessage.Zones.DECKto the hand occurs.
runGym methods in the test code for this module provides an great template for testing rules and
card behaviour using Spellsource.- See Also:
-
for more about how a game is "played."for the interface that the GameContext delegates player actions and notifications to. This is both the "event handler" specification for which events a player may be interested in; and also a "delegate" in the sense that the object implementing this interface makes decisions about what actions in the game to take (with e.g. Behaviour#requestAction(GameContext, Player, List).for an example behaviour that just makes random decisions when requested.for the class that actually implements the Spellsource game rules. This class requires a GameContext because it manipulates the state stored in it.for a class that encapsulates all of the state of a game of Spellsource.to access and modify the game state.to get a copy of the state that can be stored and diffed.to see a summary of a player's activity during a game.for a way to enumerate through all of the entities in the game.- Serialized Form
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intstatic final intprotected io.opentracing.SpanContext -
Constructor Summary
ConstructorsConstructorDescriptionCreates a game context with two empty players and twoPlayRandomBehaviourbehaviours.GameContext(String... heroClasses) Creates an uninitialized game context (i.e., no cards in the decks of the players or behaviours specified).GameContext(GameContext fromContext) Creates a game context from another context by copying it. -
Method Summary
Modifier and TypeMethodDescriptionintaddAndGetInt(String name, int delta) Adds the delta value and returns the new value of the named integer from the context's cloneable storage.voidaddTempCard(Card card) Adds a temporary card.protected voidclone()Clones the game context, recursively cloning the game state and logic.protected voidclose()Clears state to ensure this context isn't referencing it anymore.intcompareTo(@NotNull GameContext other) Returns0if the two game contexts have the same meaningful game state.voidconcede(int playerId) Concedes a game by destroying the specified player's hero and calling end game.voidCreates an integer value in the context's cloneable storage.protected booleanprotected voidendGame()Ends the game immediately.voidendTurn()Ends the current player's turn immediately, setting the active player to their opponent.static GameContextfromDeckLists(List<String> deckLists) Gets a game context that's ready to play from two deck lists encoded in the standard community format.static GameContextfromDeckLists(List<String> deckLists, Behaviour behaviour1, Behaviour behaviour2) Gets a game context that's ready to play from two deck lists encoded in the standard community format.static GameContextstatic GameContextGets a game context that's ready to play from twoGameDeckobjects.static GameContextGets a game context that's ready to play from twoGameDeckobjects.static GameContextCreates a game context from the given state.static GameContextCreates a game context from a trace.static GameContextCreates a new game context with two random decks and random play behaviour.static GameContextfromTwoRandomDecks(long seed) static GameContextfromTwoRandomDecks(DeckFormat format) Creates a game with two random decks in the specified format.intGets a reference to the currently active player (the player whose turn it is).intGets the integer ID of the player whose current turn it is.getAdjacentMinions(EntityReference targetReference) Gets the minions adjacent to the given minion.getCardById(String cardId) Gets a card by ID, checking both the catalogue and the cards ingetTempCards().@Nullable GameActionRetrieves all the damage values that are supposed to be applied.Returnsnull, because by defaultGameContextare not networked and have no sense of inventory.getDeckCombinations(List<String> decks) Creates all the possible combinations of decks given a list of decksgetDeckCombinations(List<GameDeck> decks, boolean includeMirrors) Gets theDeckFormatof this context, or the currently legal cards in terms ofCardSetobjects.Gets all the entities in the game, aside from hidden ones, as aStream.Gets a reference to the game context's environment, a piece of game state that keeps tracks of which minions are currently being summoned, which targets are being targeted, how much damage is set to be dealt, etc.Retrieves the stack of event sources.Gets the current event target stack.intbooleanWhen true, the game logic doesn't handle an events being raised.intGets the value of the named integer in the context's cloneable storage.getLastCardPlayed(int playerId) getLastCardPlayedBeforeCurrentSequence(int playerId) getLeftMinions(EntityReference minionReference) Gets the minions to the left on the battlefield of the given minion.org.slf4j.LoggergetLogic()Gets a reference to the game logic associated with this context.The number of milliseconds remaining until the active player is automatically changed.intgetMinionCount(Player player) Gets the number of minions a player has.protected PlayerintgetOpponent(Player player) Gets the opponent from the point of view of the given player.getOppositeMinions(EntityReference minionReference) Gets theActorentities geometrically opposite of the givenminionReferenceon theSpellsource.ZonesMessage.Zones.BATTLEFIELD.Gets the current output card.getPlayer(int index) Gets the player at the given index.Gets the first player.Gets the second player.Each player holds the player'sAbstractBehaviourand all of theEntityobjects in the game.getRightMinions(EntityReference minionReference) Gets minions geometrically right of the givenminionReferenceon theSpellsource.ZonesMessage.Zones.BATTLEFIELDthat belongs to the specified player.io.opentracing.SpanContextProvides context for tracing in this context.Returns the spell values calculated so far byMetaSpellspells.Gets the minions whose summoning is currently being processed.@Nullable EntitygetTargetOverride(@NotNull Player player, @Nullable Entity source) Retrieves the current target override specified in the environment.intGets the total number of minions on both player'sSpellsource.ZonesMessage.Zones.BATTLEFIELD.getTrace()Retrieves a trace of this game's actions.Retrieves the stack of hosts of the currently firing trigger.intgetTurn()Gets the current turn.Gets the currentTurnStateReturns a reference to the variables stored in the game context, used by spells to maintain correct space when a strand currently being executed is cloned.intGets the winning player's ID or-1if no player is the winner.<E extends Entity>
EntityZone<E>getZone(int owner, com.hiddenswitch.spellsource.rpc.Spellsource.ZonesMessage.Zones zone) Retrieves anEntityZonefor the provided owner and zone.booleanhasPlayer(int id) voidinit()Initializes a game.voidinit(int startingPlayerId) Initialized the game with the specified starting player.booleanprotected voidvoidonDidPerformGameAction(int playerId, GameAction action) voidonEnchantmentFired(Enchantment enchantment) Raised when aEnchantmentis fired (i.e., a secret is about to be played or a special effect hosted by a minion/weapon is about to happen).voidvoidvoidonWillPerformGameAction(int playerId, GameAction action) voidperformAction(int playerId, GameAction gameAction) Executes the specified game action, typically by callingGameLogic.performGameAction(int, GameAction).voidplay()Plays the game.voidplay(boolean fork) intRemoves the specified integer from the context's cloneable storage.<T extends Entity>
TresolveSingleTarget(Player player, Entity source, EntityReference target) Resolves a single target that could be aEntityReference.isTargetGroup()that points to exactly one entity, likeEntityReference.FRIENDLY_HERO.resolveSingleTarget(EntityReference targetKey) Tries to find the entity references by theEntityReference.resolveSingleTarget(EntityReference targetKey, boolean rejectRemovedFromPlay) Resolves a single target given the specification, even if the specification is aEntityReference.isTargetGroup()resolveTarget(Player player, Entity source, EntityReference targetKey) InterpretsEntityReferencethat specifies a group ofEntityobjects, likeEntityReference.ALL_MINIONS.voidresume()Resumes a game, playing it to completion.setActionStack(Deque<GameAction> actionStack) voidsetActionsThisTurn(int actionsThisTurn) voidsetActivePlayerId(int id) voidsetBehaviour(int i, Behaviour behaviour) voidsetBehaviours(Behaviour[] behaviours) voidSets the specified player's deck and hero (by implication)setDeckFormat(DeckFormat deckFormat) voidsetEnvironment(Map<Environment, Object> environment) voidsetGameState(GameState state) voidsetIgnoreEvents(boolean ignoreEvents) voidsetLastCardPlayed(int playerId, EntityReference cardReference) voidsetLastCardPlayedBeforeCurrentSequence(int playerId, EntityReference cardReference) voidsetLastSpellPlayedThisTurn(int playerId, EntityReference cardReference) voidsetLogger(org.slf4j.Logger logger) voidsetOtherTriggers(List<Trigger> otherTriggers) voidsetPlayer1(Player player1) voidsetPlayer2(Player player2) setSpanContext(io.opentracing.SpanContext spanContext) voidsetStatus(GameStatus result) voidsetTargetLogic(TargetLogic targetLogic) voidsetTargetOverride(EntityReference reference) voidsetTempCards(CardList tempCards) protected GameContextprotected voidvoidsetTurn(int turn) voidsetTurnState(TurnState turnState) voidstatic SimulationResultsimulate(List<GameDeck> decks, Supplier<Behaviour> player1, Supplier<Behaviour> player2, int gamesPerMatchup, boolean useJavaParallel, boolean includeMirrors) Runs a simulation of the decks with the specified AIs.static SimulationResultsimulate(List<GameDeck> decks, Supplier<Behaviour> player1, Supplier<Behaviour> player2, int gamesPerMatchup, boolean useJavaParallel, boolean includeMirrors, AtomicInteger matchCounter, Consumer<GameContext> mutateConstructedGameContext, Consumer<GameContext> afterGameContextInit) Runs a simulation of the decks with the specified AIs.static SimulationResultsimulate(List<GameDeck> decks, Supplier<Behaviour> player1, Supplier<Behaviour> player2, int gamesPerMatchup, boolean useJavaParallel, AtomicInteger matchCounter) Runs a simulation of the decks with the specified AIs.static voidsimulate(List<GameDeck> deckPair, List<Supplier<Behaviour>> behaviours, int gamesPerMatchup, boolean reduce, Consumer<SimulationResult> computed) A generator of simulation results.static intsimulationCount(int numberOfDecks, int gamesPerMatchup, boolean includeMirrors) Calculates the expected number of simulations that will be run given the parameters of the simulation function.protected voidFire the start game events here insteadprotected voidEnsures that the game state is traced / recordedvoidstartTurn(int playerId) Starts the turn for a player.booleanRequests an action from a player and takes it in the turn.toString()protected voidtraceMulligans(List<Card> mulligansActive, List<Card> mulligansNonActive) @Nullable EntitytryFind(EntityReference targetKey) Tries to find an entity given the reference.@Nullable EntitytryFind(EntityReference targetKey, boolean rejectRemovedFromPlay) Tries to find an entity given the reference.booleanDetermines whether the game is over (decided).
-
Field Details
-
PLAYER_1
public static final int PLAYER_1- See Also:
-
PLAYER_2
public static final int PLAYER_2- See Also:
-
spanContext
protected transient io.opentracing.SpanContext spanContext
-
-
Constructor Details
-
GameContext
public GameContext()Creates a game context with two empty players and twoPlayRandomBehaviourbehaviours.Hero cards are not given to the players. Thus, this is not enough typically to mutate and run a game. Use
GameContext(String...)to create a game initialized with the specified hero classes. -
GameContext
Creates a game context from another context by copying it.- Parameters:
fromContext- The other context to copy.
-
GameContext
Creates an uninitialized game context (i.e., no cards in the decks of the players or behaviours specified). A hero card is retrieved and given to each player.This is typically the absolute minimum needed to mutate and run a game.
- Parameters:
heroClasses- The player's hero classes.
-
-
Method Details
-
fromTrace
Creates a game context from a trace.- Parameters:
trace-- Returns:
-
addTempCard
Adds a temporary card. A temporary card is a card that exists only in this instance and not in theCardCatalogue.- Parameters:
card- The card to add, typically made with code.
-
clone
Clones the game context, recursively cloning the game state and logic.Internally, this is used by AI functions to evaluate a game state until a win condition (or just the end of the turn) is reached.
This method is not thread safe. Two threads can't clone and mutate a context at the same time.
-
close
protected void close()Clears state to ensure this context isn't referencing it anymore. -
endGame
protected void endGame()Ends the game immediately. -
notifyPlayersGameOver
protected void notifyPlayersGameOver() -
calculateStatistics
protected void calculateStatistics() -
endTurn
public void endTurn()Ends the current player's turn immediately, setting the active player to their opponent. -
updateAndGetGameOver
public boolean updateAndGetGameOver()Determines whether the game is over (decided). As a side effect, records the current result of the game.- Returns:
trueif the game has been decided by concession or because one of the two heroes have been destroyed.
-
getActivePlayer
Gets a reference to the currently active player (the player whose turn it is).- Returns:
- The player whose turn it is.
-
getActivePlayerId
public int getActivePlayerId()Gets the integer ID of the player whose current turn it is.- Returns:
- The integer ID.
-
getAdjacentMinions
Gets the minions adjacent to the given minion. Omits permanents.- Parameters:
targetReference- The minion whose adjacent minions we should get.- Returns:
- The adjacent minions.
-
getCardById
Gets a card by ID, checking both the catalogue and the cards ingetTempCards().- Parameters:
cardId- The string card ID.- Returns:
- A clone of the
Card.
-
getDamageStack
Retrieves all the damage values that are supposed to be applied.Implements spells that override the amount of damage something deals.
- Returns:
- The stack.
-
getDeckFormat
Gets theDeckFormatof this context, or the currently legal cards in terms ofCardSetobjects.- Returns:
- A
DeckFormatobject.
-
getEnvironment
Gets a reference to the game context's environment, a piece of game state that keeps tracks of which minions are currently being summoned, which targets are being targeted, how much damage is set to be dealt, etc.This helps implement a variety of complex rules in the game.
- Returns:
- A mutable map of environment variables.
- See Also:
-
getOutputCard
Gets the current output card.- Returns:
- The event card.
- See Also:
-
getEventTargetStack
Gets the current event target stack.- Returns:
- A stack of targets.
- See Also:
-
getLeftMinions
Gets the minions to the left on the battlefield of the given minion.- Parameters:
minionReference- AnEntityReferencepointing to the minion.- Returns:
- A list of entities to the left of the provided minion.
-
getLogic
Gets a reference to the game logic associated with this context. -
getMinionCount
Gets the number of minions a player has.- Parameters:
player- The player to query.- Returns:
- The count of minions.
-
getOpponent
Gets the opponent from the point of view of the given player.- Parameters:
player- The friendly player.- Returns:
- The opposing player from the point of view of the
playerargument.
-
getOppositeMinions
Gets theActorentities geometrically opposite of the givenminionReferenceon theSpellsource.ZonesMessage.Zones.BATTLEFIELD.- Parameters:
minionReference- The minion from whose perspective we will consider "opposite."- Returns:
- The list of
Actor(typically one or two) that are geometrically opposite from the minion referenced byminionReference.
-
getPlayer
Gets the player at the given index. -
hasPlayer
public boolean hasPlayer(int id) -
getPlayer1
Gets the first player.- Returns:
- A player object.
-
getPlayer2
Gets the second player.- Returns:
- A player object.
-
getPlayers
Each player holds the player'sAbstractBehaviourand all of theEntityobjects in the game.- Returns:
- A read only list of
Playerobjects.
-
getBehaviours
-
getRightMinions
Gets minions geometrically right of the givenminionReferenceon theSpellsource.ZonesMessage.Zones.BATTLEFIELDthat belongs to the specified player.- Parameters:
minionReference- The minion reference.- Returns:
- A list of
Actor(sometimes empty) of minions to the geometric right of theminionReference.
-
getSummonReferenceStack
Gets the minions whose summoning is currently being processed.This stack can have multiple entries because battlecries or secrets can trigger summoning of other minions in the middle of evaluating a
GameLogic.summon(int, Minion, Entity, int, boolean).- Returns:
- A stack of summons.
-
getTotalMinionCount
public int getTotalMinionCount()Gets the total number of minions on both player'sSpellsource.ZonesMessage.Zones.BATTLEFIELD.- Returns:
- A total.
-
getTurn
public int getTurn()Gets the current turn.- Returns:
- The turn. 0 is the first turn.
-
getTurnState
Gets the currentTurnState- Returns:
- The turn state of this context.
-
getValidActions
-
getWinningPlayerId
public int getWinningPlayerId()Gets the winning player's ID or-1if no player is the winner.- Returns:
- The winning player's ID or
-1if no player is the winner.
-
getIgnoreEvents
public boolean getIgnoreEvents()When true, the game logic doesn't handle an events being raised.- Returns:
trueif the game context should ignore incoming events.
-
init
public void init()Initializes a game.This function will choose a starting player, then move cards into the mulligan (set aside) zone, ask for mulligans, and start the game.
resume()will start the first turn. -
init
public void init(int startingPlayerId) Initialized the game with the specified starting player. When called by itself, does not initialize the trace.- Parameters:
startingPlayerId-
-
traceMulligans
-
startTrace
protected void startTrace()Ensures that the game state is traced / recorded -
performAction
Executes the specified game action, typically by callingGameLogic.performGameAction(int, GameAction).- Parameters:
playerId- The player who's performing the action.gameAction- The action to perform.- See Also:
-
play
public void play()Plays the game.When a game is played, mulligans are requested from both players, and then each player is asked for actions until the player can't take any.
Play relies on the
Behaviourdelegates to determine what a player's chosen action is. It takes the chosen action and feeds it to theGameLogic, which executes the effects of that action until the next action needs to be requested.- See Also:
-
play
public void play(boolean fork) -
takeActionInTurn
public boolean takeActionInTurn()Requests an action from a player and takes it in the turn.This method will call
Behaviour.requestAction(GameContext, Player, List)to get an action from the currently active player. It then callsperformAction(int, GameAction)with the returnedGameAction.- Returns:
falseif the player selected anEndTurnAction, indicating the player would like to end their turn.
-
resolveSingleTarget
Tries to find the entity references by theEntityReference.- Parameters:
targetKey- The reference to find.- Returns:
- The
Entitypointed to by theEntityReference, ornullif the provided entity reference wasnullorEntityReference.NONE - Throws:
TargetNotFoundException- if the reference could not be found. Game rules shouldn't be looking for references that cannot be found.
-
resolveSingleTarget
public Entity resolveSingleTarget(EntityReference targetKey, boolean rejectRemovedFromPlay) throws TargetNotFoundException Resolves a single target given the specification, even if the specification is aEntityReference.isTargetGroup()- Parameters:
targetKey-rejectRemovedFromPlay-- Returns:
- Throws:
TargetNotFoundException
-
resolveTarget
InterpretsEntityReferencethat specifies a group ofEntityobjects, likeEntityReference.ALL_MINIONS.- Parameters:
player- The player from whose point of view this method interprets theEntityReference.source- The entity from whose point of view this method interprets theEntityReference.targetKey- TheEntityReference.- Returns:
- A potentially empty list of entities.
- See Also:
-
setIgnoreEvents
public void setIgnoreEvents(boolean ignoreEvents) -
getEventValue
public int getEventValue() -
getTargetOverride
@Nullable public @Nullable Entity getTargetOverride(@NotNull @NotNull Player player, @Nullable @Nullable Entity source) Retrieves the current target override specified in the environment.A target override can be a specific
EntityReferenceor a "group reference" (logical entity reference) that returns exactly zero or one targets. The override should almost always succeed, and it would be surprising if there were overrides that resulted in no targets being found.- Parameters:
player- The player for whom the override should be evaluated.source- The source entity of this override.- Returns:
- An
Entityornullif no override is specified.
-
startGame
protected void startGame()Fire the start game events here instead -
getNonActivePlayerId
public int getNonActivePlayerId() -
startTurn
public void startTurn(int playerId) Starts the turn for a player.- Parameters:
playerId- The player whose turn should be started.
-
toString
-
tryFind
Tries to find an entity given the reference.- Parameters:
targetKey- The reference to the entity.- Returns:
- The found
Entity, ornullif no entity was found.
-
tryFind
Tries to find an entity given the reference.- Parameters:
targetKey- The reference to the entity.rejectRemovedFromPlay-- Returns:
- The found
Entity, ornullif no entity was found.
-
setLogic
-
setDeckFormat
-
setEnvironment
-
getWinner
-
setWinner
-
getStatus
-
setStatus
-
setTurnState
-
setTurn
public void setTurn(int turn) -
getActionsThisTurn
public int getActionsThisTurn() -
setActionsThisTurn
public void setActionsThisTurn(int actionsThisTurn) -
setPlayer1
-
setPlayer2
-
setPlayer
-
setActivePlayerId
public void setActivePlayerId(int id) -
getTargetLogic
-
setTargetLogic
-
getTempCards
-
setTempCards
-
isDisposed
public boolean isDisposed() -
getGameId
-
getEntities
Gets all the entities in the game, aside from hidden ones, as aStream.- Returns:
- The
Streamof game entities.
-
onWillPerformGameAction
-
onDidPerformGameAction
-
getGameState
-
getGameStateCopy
-
concede
public void concede(int playerId) Concedes a game by destroying the specified player's hero and calling end game.- Parameters:
playerId- The player that should concede/lose
-
onEnchantmentFired
Raised when aEnchantmentis fired (i.e., a secret is about to be played or a special effect hosted by a minion/weapon is about to happen).- Parameters:
enchantment- The spell trigger that fired.
-
getSpellValueStack
Returns the spell values calculated so far byMetaSpellspells.Implements Living Mana. Using a stack fixes issues where a later
MetaSpellbusts an earlier one.- Returns:
- A stack of
Integerspell values.
-
getEventValueStack
-
getSpellTargetStack
-
getOutputStack
-
getAttackerReferenceStack
-
getLastCardPlayedMap
-
setLastCardPlayed
-
getLastCardPlayedBeforeCurrentSequenceMap
-
setLastCardPlayedBeforeCurrentSequence
-
getLastCardPlayed
-
getLastCardPlayed
-
getLastSpellPlayedThisTurnMap
-
setLastSpellPlayedThisTurn
-
getLastCardPlayedBeforeCurrentSequence
-
getLastCardPlayedBeforeCurrentSequence
-
getAftermaths
-
getNonActivePlayer
-
resume
public void resume()Resumes a game, playing it to completion.Useful for implementing Monte Carlo Tree Search AI algorithms.
-
getEventSourceStack
Retrieves the stack of event sources.- Returns:
- A stack of event source
EntityReferenceobjects.
-
simulate
public static SimulationResult simulate(List<GameDeck> decks, Supplier<Behaviour> player1, Supplier<Behaviour> player2, int gamesPerMatchup, boolean useJavaParallel, AtomicInteger matchCounter) Runs a simulation of the decks with the specified AIs.This call will be blocking regardless of using it in a parallel fashion.
- Parameters:
decks- Decks to run the match with. At least two are required.player1- ASupplier(function which returns a new instance) of aBehaviourthat corresponds to an AI to use for this player.For example, use the argument
GameStateValueBehaviour::newto specify that the first player's AI should be a game state value behaviour.player2- ASupplier(function which returns a new instance) of aBehaviourthat corresponds to an AI to use for this player.gamesPerMatchup- The number of games per matchup to play. The number of matchups total can be calculated withsimulationCount(int, int, boolean).useJavaParallel- Whentrue, uses the Java Streams Parallel interface to parallelize this computation on this JVM instance.matchCounter- When notnull, the simulator will increment this counter each time a match is completed. This can be used to implement progress on a different thread.
-
simulate
public static SimulationResult simulate(List<GameDeck> decks, Supplier<Behaviour> player1, Supplier<Behaviour> player2, int gamesPerMatchup, boolean useJavaParallel, boolean includeMirrors) Runs a simulation of the decks with the specified AIs.This call will be blocking regardless of using it in a parallel fashion.
- Parameters:
decks- Decks to run the match with. At least one is required ifincludeMirrorsistrue, otherwise at least two.player1- ASupplier(function which returns a new instance) of aBehaviourthat corresponds to an AI to use for this player.For example, use the argument
GameStateValueBehaviour::newto specify that the first player's AI should be a game state value behaviour.player2- ASupplier(function which returns a new instance) of aBehaviourthat corresponds to an AI to use for this player.gamesPerMatchup- The number of games per matchup to play. The number of matchups total can be calculated withsimulationCount(int, int, boolean).useJavaParallel- Whentrue, uses the Java Streams Parallel interface to parallelize this computation on this JVM instance.includeMirrors- Whentrue, includes mirror matchups for each deck.
-
simulate
public static SimulationResult simulate(List<GameDeck> decks, Supplier<Behaviour> player1, Supplier<Behaviour> player2, int gamesPerMatchup, boolean useJavaParallel, boolean includeMirrors, AtomicInteger matchCounter, Consumer<GameContext> mutateConstructedGameContext, Consumer<GameContext> afterGameContextInit) Runs a simulation of the decks with the specified AIs.This call will be blocking regardless of using it in a parallel fashion.
When more than two decks are specified, the players will have their statistics merged with multiple decks.
- Parameters:
decks- Decks to run the match with. At least two are required.player1- ASupplier(function which returns a new instance) of aBehaviourthat corresponds to an AI to use for this player.For example, use the argument
GameStateValueBehaviour::newto specify that the first player's AI should be a game state value behaviour.player2- ASupplier(function which returns a new instance) of aBehaviourthat corresponds to an AI to use for this player.gamesPerMatchup- The number of games per matchup to play. The number of matchups total can be calculated withsimulationCount(int, int, boolean).useJavaParallel- Whentrue, uses the Java Streams Parallel interface to parallelize this computation on this JVM instance.includeMirrors- Whentrue, includes mirror matchupsmatchCounter- When notnull, the simulator will increment this counter each time a match ismutateConstructedGameContext- A handler that can modify the game context for customization after it was initialized with the specified decks but before mulligans. For example, theGameLogic.getSeed()canafterGameContextInit- A handler that can add/remove things to the game context after the players have mulliganned.
-
simulationCount
public static int simulationCount(int numberOfDecks, int gamesPerMatchup, boolean includeMirrors) Calculates the expected number of simulations that will be run given the parameters of the simulation function.- Parameters:
numberOfDecks- The number of decks (i.e.,decks.size())gamesPerMatchup- The number of games to play per unique deck pair.includeMirrors- When true, include mirror matches.- Returns:
-
simulate
public static void simulate(List<GameDeck> deckPair, List<Supplier<Behaviour>> behaviours, int gamesPerMatchup, boolean reduce, Consumer<SimulationResult> computed) throws InterruptedException A generator of simulation results. Blocks until all simulations are complete.- Parameters:
deckPair- Two decks to test. Specify the same deck twice to perform a mirror match.behaviours- The behaviours to use. When an empty list is specified, usesPlayRandomBehaviour.gamesPerMatchup- The number of games to play per matchup.reduce- Whentrue, merges matches that have the same behaviour and decks.computed- The callback that will be fed a simulation result whenever it is computed.- Throws:
InterruptedException
-
fromDecks
public static GameContext fromDecks(List<GameDeck> decks, Behaviour behaviour1, Behaviour behaviour2) Gets a game context that's ready to play from twoGameDeckobjects.- Parameters:
decks- TheGameDecks to use for the players.- Returns:
- A
GameContextfor whichplay()will immediately work. - See Also:
-
fromDecks
Gets a game context that's ready to play from twoGameDeckobjects. Uses thePlayRandomBehaviourfor both players.- Parameters:
decks- TheGameDecks to use for the players.- Returns:
- A
GameContextfor whichplay()will immediately work. - See Also:
-
fromDeckLists
Gets a game context that's ready to play from two deck lists encoded in the standard community format. Uses thePlayRandomBehaviourfor both players.- Parameters:
deckLists- A Hearthstone deck string or a deck list of the format, with newlines:Name: Deck Name
Class: Color Hero Class (e.g., PRIEST) specified in
HeroClass.Format: Standard, Wild, Custom or others specified in
DeckFormat.formats().1x Card Name
2x Card Name
- Returns:
- A game context.
- See Also:
-
fromDeckLists
public static GameContext fromDeckLists(List<String> deckLists, Behaviour behaviour1, Behaviour behaviour2) Gets a game context that's ready to play from two deck lists encoded in the standard community format. Uses the specified behaviours.- Parameters:
deckLists- A Hearthstone deck string or a deck list of the format, with newlines:Name: Deck Name
Class: Color Hero Class (e.g., PRIEST) specified in
HeroClass.Format: Standard, Wild, Custom or others specified in
DeckFormat.formats().1x Card Name
2x Card Name
behaviour1- An implementation ofBehaviourfor player 1behaviour2- An implementation ofBehaviourfor player 2- Returns:
- A game context
-
fromTwoRandomDecks
Creates a new game context with two random decks and random play behaviour.- Returns:
- A game context
- See Also:
-
fromTwoRandomDecks
-
fromDecks
-
fromTwoRandomDecks
Creates a game with two random decks in the specified format.- Parameters:
format-- Returns:
-
getDeckCombinations
Creates all the possible combinations of decks given a list of decks- Parameters:
decks- An input list of deck names- Returns:
- A list of 2-tuples of deck names.
-
getDeckCombinations
-
getMillisRemaining
The number of milliseconds remaining until the active player is automatically changed.- Returns:
nullif there are no turn/mulligan timers, otherwise the amount of time remaining in milliseconds.
-
getTrace
Retrieves a trace of this game's actions.Serialization is not guaranteed to work on later versions of the codebase.
- Returns:
- A
Tracecontaining all the actions that were performed in this game and its initial state.
-
getDeck
Returnsnull, because by defaultGameContextare not networked and have no sense of inventory. -
getTriggerHostStack
Retrieves the stack of hosts of the currently firing trigger.- Returns:
- A host reference, or null if the trigger didn't have a host.
-
setTargetOverride
-
getLogger
public org.slf4j.Logger getLogger() -
setLogger
public void setLogger(org.slf4j.Logger logger) -
resolveSingleTarget
public <T extends Entity> T resolveSingleTarget(Player player, Entity source, EntityReference target) Resolves a single target that could be aEntityReference.isTargetGroup()that points to exactly one entity, likeEntityReference.FRIENDLY_HERO.- Parameters:
player- The source player.source- The entity from whose point of view this target should be evaluated.target- A target key to a specific entity or a named reference ("target group") that returns exactly one entity.- Returns:
- The entity.
-
setBehaviours
-
setBehaviour
-
didCallEndGame
protected boolean didCallEndGame() -
getThread
-
setThread
-
setDeck
Sets the specified player's deck and hero (by implication)- Parameters:
playerId-deck-
-
compareTo
Returns0if the two game contexts have the same meaningful game state.Otherwise, returns
1ifotheris "further along"- Specified by:
compareToin interfaceComparable<GameContext>- Parameters:
other-- Returns:
-
setTrace
-
getSpanContext
public io.opentracing.SpanContext getSpanContext()Provides context for tracing in this context. This is the OpenTracing span context, typically assigned by the matchmaker or whatever created this instance.- Returns:
-
setSpanContext
-
getVariables
Returns a reference to the variables stored in the game context, used by spells to maintain correct space when a strand currently being executed is cloned.- Returns:
-
createInt
Creates an integer value in the context's cloneable storage.- Parameters:
name-initialValue-
-
addAndGetInt
Adds the delta value and returns the new value of the named integer from the context's cloneable storage.- Parameters:
name-delta-- Returns:
-
getInt
Gets the value of the named integer in the context's cloneable storage.- Parameters:
name-- Returns:
-
removeInt
Removes the specified integer from the context's cloneable storage.- Parameters:
name-- Returns:
-
setOtherTriggers
-
getTriggers
-
getDeferredTriggersQueue
-
getProcessingTriggers
-
getActionStack
-
setActionStack
-
getCurrentAction
-
onNotificationWillFire
-
onNotificationDidFire
-