/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.players;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageItem;
import mage.MageObject;
import mage.abilities.Abilities;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.Mode;
import mage.abilities.Modes;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.costs.AlternativeSourceCosts;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.mana.ManaOptions;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.decks.Deck;
import mage.choices.Choice;
import mage.constants.AbilityType;
import mage.constants.ManaType;
import mage.constants.Outcome;
import mage.constants.PlayerAction;
import mage.constants.RangeOfInfluence;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.Counters;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.Graveyard;
import mage.game.Table;
import mage.game.combat.CombatGroup;
import mage.game.draft.Draft;
import mage.game.match.Match;
import mage.game.match.MatchPlayer;
import mage.game.permanent.Permanent;
import mage.game.tournament.Tournament;
import mage.players.net.UserData;
import mage.target.Target;
import mage.target.TargetAmount;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.util.Copyable;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public interface Player extends MageItem, Copyable<Player> {
boolean isHuman();
String getName();
String getLogName();
RangeOfInfluence getRange();
Library getLibrary();
Cards getSideboard();
Graveyard getGraveyard();
Abilities<Ability> getAbilities();
void addAbility(Ability ability);
Counters getCounters();
int getLife();
void initLife(int life);
void setLife(int life, Game game);
/**
*
* @param amount amount of life loss
* @param game
* @param atCombat was the source combat damage
* @return
*/
int loseLife(int amount, Game game, boolean atCombat);
int gainLife(int amount, Game game);
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable);
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects);
// to handle rule changing effects (613.10)
boolean isCanLoseLife();
void setCanLoseLife(boolean canLoseLife);
void setCanGainLife(boolean canGainLife);
boolean isCanGainLife();
void setCanPayLifeCost(boolean canPayLifeCost);
boolean canPayLifeCost();
void setCanPaySacrificeCostFilter(FilterPermanent filter);
FilterPermanent getSacrificeCostFilter();
boolean canPaySacrificeCost(Permanent permanent, UUID sourceId, UUID controllerId, Game game);
void setLifeTotalCanChange(boolean lifeTotalCanChange);
boolean isLifeTotalCanChange();
void setLoseByZeroOrLessLife(boolean loseByZeroOrLessLife);
boolean canLoseByZeroOrLessLife();
void setPlayCardsFromGraveyard(boolean playCardsFromGraveyard);
boolean canPlayCardsFromGraveyard();
/**
* Returns alternative casting costs a player can cast spells for
*
* @return
*/
List<AlternativeSourceCosts> getAlternativeSourceCosts();
Cards getHand();
int getLandsPlayed();
int getLandsPerTurn();
void setLandsPerTurn(int landsPerTurn);
int getLoyaltyUsePerTurn();
void setLoyaltyUsePerTurn(int loyaltyUsePerTurn);
int getMaxHandSize();
void setMaxHandSize(int maxHandSize);
int getMaxAttackedBy();
void setMaxAttackedBy(int maxAttackedBy);
boolean isPassed();
boolean isEmptyDraw();
void pass(Game game);
void resetPassed();
void resetPlayerPassedActions();
boolean getPassedTurn();
boolean getPassedUntilEndOfTurn();
boolean getPassedUntilNextMain();
boolean getPassedUntilStackResolved();
boolean getPassedUntilEndStepBeforeMyTurn();
boolean getPassedAllTurns();
AbilityType getJustActivatedType();
void setJustActivatedType(AbilityType abilityType);
boolean hasLost();
boolean hasDrew();
boolean hasWon();
boolean hasQuit();
void quit(Game game);
boolean hasTimerTimeout();
void timerTimeout(Game game);
boolean hasIdleTimeout();
void idleTimeout(Game game);
boolean hasLeft();
/**
* Player is still active in game (has not left, lost or won the game).
*
* @return
*/
boolean isInGame();
/**
* Player is still active in game (has not left, lost or won the game) and
* no abort state is given.
*
* @return
*/
boolean canRespond();
/**
* Called if other player left the game
*
* @param game
*/
void otherPlayerLeftGame(Game game);
ManaPool getManaPool();
Set<UUID> getInRange();
boolean isTopCardRevealed();
void setTopCardRevealed(boolean topCardRevealed);
/**
* Get data from the client Preferences (e.g. avatarId or
* showAbilityPickerForce)
*
* @return
*/
UserData getUserData();
void setUserData(UserData userData);
boolean canLose(Game game);
boolean autoLoseGame();
/**
* Returns a set of players which turns under you control. Doesn't include
* yourself.
*
* @return
*/
Set<UUID> getPlayersUnderYourControl();
/**
* Defines player whose turn this player controls at the moment.
*
* @param game
* @param playerId
*/
void controlPlayersTurn(Game game, UUID playerId);
/**
* Sets player {@link UUID} who controls this player's turn.
*
* @param playerId
*/
void setTurnControlledBy(UUID playerId);
UUID getTurnControlledBy();
/**
* Resets players whose turns you control at the moment.
*/
void resetOtherTurnsControlled();
/**
* Returns false in case player don't control the game.
*
* Note: For effects like "You control target player during that player's
* next turn".
*
* @return
*/
boolean isGameUnderControl();
/**
* Returns false in case you don't control the game.
*
* Note: For effects like "You control target player during that player's
* next turn".
*
* @param value
*/
void setGameUnderYourControl(boolean value);
boolean isTestMode();
void setTestMode(boolean value);
void addAction(String action);
int getActionCount();
void setAllowBadMoves(boolean allowBadMoves);
void init(Game game);
void init(Game game, boolean testMode);
void useDeck(Deck deck, Game game);
/**
* Called before each applyEffects, to rest all what can be applyed by
* continuous effects
*/
void reset();
void shuffleLibrary(Ability source, Game game);
int drawCards(int num, Game game);
int drawCards(int num, Game game, ArrayList<UUID> appliedEffects);
boolean cast(SpellAbility ability, Game game, boolean noMana);
SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana);
boolean putInHand(Card card, Game game);
boolean removeFromHand(Card card, Game game);
boolean removeFromBattlefield(Permanent permanent, Game game);
boolean putInGraveyard(Card card, Game game);
boolean removeFromGraveyard(Card card, Game game);
boolean removeFromLibrary(Card card, Game game);
boolean searchLibrary(TargetCardInLibrary target, Game game);
/**
*
* @param target
* @param game
* @param targetPlayerId player whose library will be searched
* @return true if search was successful
*/
boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId);
boolean canPlayLand();
/**
* Plays a card if possible
*
* @param card the card that can be cast
* @param game
* @param noMana if it's a spell i can be cast without paying mana
* @param ignoreTiming if it's cast during the resolution of another spell
* no sorcery or play land timing restriction are checked. For a land it has
* to be the turn of the player playing that card.
* @return
*/
boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming);
/**
*
* @param card the land card to play
* @param game
* @param ignoreTiming false - it won't be checked if the stack is empty and
* you are able to play a Sorcery. It's still checked, if you are able to
* play a land concerning the numner of lands you already played.
* @return
*/
boolean playLand(Card card, Game game, boolean ignoreTiming);
boolean activateAbility(ActivatedAbility ability, Game game);
boolean triggerAbility(TriggeredAbility ability, Game game);
boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game);
boolean hasProtectionFrom(MageObject source, Game game);
boolean flipCoin(Game game);
boolean flipCoin(Game game, ArrayList<UUID> appliedEffects);
@Deprecated
void discard(int amount, Ability source, Game game);
Card discardOne(boolean random, Ability source, Game game);
Cards discard(int amount, boolean random, Ability source, Game game);
void discardToMax(Game game);
boolean discard(Card card, Ability source, Game game);
void lost(Game game);
void lostForced(Game game);
void drew(Game game);
void won(Game game);
void leave();
void concede(Game game);
void abort();
void abortReset();
void skip();
// priority, undo, ...
void sendPlayerAction(PlayerAction passPriorityAction, Game game, Object data);
int getStoredBookmark();
void setStoredBookmark(int bookmark);
void resetStoredBookmark(Game game);
void revealCards(String name, Cards cards, Game game);
void revealCards(String name, Cards cards, Game game, boolean postToLog);
void lookAtCards(String name, Card card, Game game);
void lookAtCards(String name, Cards cards, Game game);
@Override
Player copy();
void restore(Player player);
void setResponseString(String responseString);
void setResponseUUID(UUID responseUUID);
void setResponseBoolean(Boolean responseBoolean);
void setResponseInteger(Integer data);
void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType);
boolean priority(Game game);
boolean choose(Outcome outcome, Target target, UUID sourceId, Game game);
boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options);
boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game);
boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game);
boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game);
boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game);
boolean chooseMulligan(Game game);
boolean chooseUse(Outcome outcome, String message, Ability source, Game game);
boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game);
boolean choose(Outcome outcome, Choice choice, Game game);
boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game);
boolean playMana(Ability ability, ManaCost unpaid, String promptText, Game game);
/**
* Moves the cards from cards to the bottom of the players library.
*
* @param cards - list of cards that have to be moved
* @param game - game
* @param anyOrder - true if player can determine the order of the cards
* else random order
* @param source - source ability
* @return
*/
boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder);
/**
* Moves the cards from cards to the top of players library.
*
* @param cards - list of cards that have to be moved
* @param game - game
* @param anyOrder - true if player can determine the order of the cards
* @param source - source ability
* @return
*/
boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder);
// set the value for X mana spells and abilities
int announceXMana(int min, int max, String message, Game game, Ability ability);
// set the value for non mana X costs
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
int chooseReplacementEffect(Map<String, String> abilityMap, Game game);
TriggeredAbility chooseTriggeredAbility(List<TriggeredAbility> abilities, Game game);
Mode chooseMode(Modes modes, Ability source, Game game);
void selectAttackers(Game game, UUID attackingPlayerId);
void selectBlockers(Game game, UUID defendingPlayerId);
UUID chooseAttackerOrder(List<Permanent> attacker, Game game);
/**
* Choose the order in which blockers get damage assigned to
*
* @param blockers list of blockers where to choose the next one from
* @param combatGroup the concerning combat group
* @param blockerOrder the already set order of blockers
* @param game
* @return blocker next to add to the blocker order
*/
UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game);
void assignDamage(int damage, List<UUID> targets, String singleTargetName, UUID sourceId, Game game);
int getAmount(int min, int max, String message, Game game);
void sideboard(Match match, Deck deck);
void construct(Tournament tournament, Deck deck);
void pickCard(List<Card> cards, Deck deck, Draft draft);
void declareAttacker(UUID attackerId, UUID defenderId, Game game, boolean allowUndo);
void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game);
List<Permanent> getAvailableAttackers(Game game);
List<Permanent> getAvailableAttackers(UUID defenderId, Game game);
List<Permanent> getAvailableBlockers(Game game);
void beginTurn(Game game);
void endOfTurn(Game game);
void phasing(Game game);
void untap(Game game);
ManaOptions getManaAvailable(Game game);
List<Ability> getPlayable(Game game, boolean hidden);
List<Ability> getPlayableOptions(Ability ability, Game game);
Set<UUID> getPlayableInHand(Game game);
LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game);
boolean addCounters(Counter counter, Game game);
void removeCounters(String name, int amount, Ability source, Game game);
List<UUID> getAttachments();
boolean addAttachment(UUID permanentId, Game game);
boolean removeAttachment(Permanent permanent, Game game);
/**
* Signals that the player becomes active player in this turn.
*/
void becomesActivePlayer();
int getTurns();
/**
* asThough effect to reveal faceDown cards
*
* @param card
* @param game
* @return player looked at the card
*/
boolean lookAtFaceDownCard(Card card, Game game);
/**
* Set seconds left to play the game.
*
* @param timeLeft
*/
void setPriorityTimeLeft(int timeLeft);
/**
* Returns seconds left to play the game.
*
* @return
*/
int getPriorityTimeLeft();
void setReachedNextTurnAfterLeaving(boolean reachedNextTurnAfterLeaving);
boolean hasReachedNextTurnAfterLeaving();
/**
* Checks if a AI player is able to join a table i.e. Draft - bot can not
* enter a table with constructed format
*
* @param table
* @return
*/
boolean canJoinTable(Table table);
/**
* Set the commanderId of the player
*
* @param commandersIds
*/
void addCommanderId(UUID commanderId);
/**
* Get the commanderId of the player
*
* @return
*/
Set<UUID> getCommandersIds();
/**
* Moves cards from one zone to another
*
* @param cards
* @param toZone
* @param source
* @param game
* @return
*/
boolean moveCards(Cards cards, Zone toZone, Ability source, Game game);
boolean moveCards(Card card, Zone toZone, Ability source, Game game);
boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects);
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game);
/**
* Universal method to move cards from one zone to another. Do not mix
* objects from different from zones to move.
*
* @param cards
* @param toZone
* @param source
* @param game
* @param tapped the cards are tapped on the battlefield
* @param faceDown the cards are face down in the to zone
* @param byOwner the card is moved (or put onto battlefield) by the owner
* of the card and if target zone is battlefield controls the permanent
* (instead of the controller of the source)
* @param appliedEffects
* @return
*/
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects);
boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName);
boolean moveCardsToExile(Set<Card> cards, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName);
/**
* Uses card.moveToZone and posts a inform message about moving the card
* into the game log
*
* @param card
* @param sourceId
* @param game
* @return
*/
boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game);
/**
* @param card
* @param sourceId
* @param game
* @param withName show the card name in the log
* @return
*
*/
boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game, boolean withName);
/**
* Uses card.moveToExile and posts a inform message about moving the card to
* exile into the game log
*
* @param card
* @param exileId exile zone id (optional)
* @param exileName name of exile zone (optional)
* @param sourceId
* @param game
* @param fromZone
* @param withName
* @return
*/
boolean moveCardToExileWithInfo(Card card, UUID exileId, String exileName, UUID sourceId, Game game, Zone fromZone, boolean withName);
/**
* Uses card.moveToZone and posts a inform message about moving the card to
* graveyard into the game log
*
* @param card
* @param sourceId
* @param game
* @param fromZone if null, this info isn't postet
* @return
*/
boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, Game game, Zone fromZone);
/**
* Internal used to move cards Use commonly player.moveCards()
*
* @param cards
* @param source
* @param game
* @param fromZone if null, this info isn't postet
* @return Set<Cards> that were successful moved to graveyard
*/
Set<Card> moveCardsToGraveyardWithInfo(Set<Card> cards, Ability source, Game game, Zone fromZone);
/**
* Uses card.moveToZone and posts a inform message about moving the card to
* library into the game log
*
* @param card
* @param sourceId
* @param game
* @param fromZone if null, this info isn't postet
* @param toTop to the top of the library else to the bottom
* @param withName show the card name in the log
* @return
*/
boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop, boolean withName);
/**
* Checks if the playerToCheckId is from an opponent in range
*
* @param playerToCheckId
* @param game
* @return true if playerToCheckId belongs to an opponent
*/
boolean hasOpponent(UUID playerToCheckId, Game game);
/**
* Free resources on match end
*/
void cleanUpOnMatchEnd();
/**
* If the next spell cast has the set sourceId, the spell will be cast
* without mana (null) or the mana set to manaCosts instead of its normal
* mana costs.
*
* @param sourceId the source that can be cast without mana
* @param manaCosts alternate ManaCost, null if it can be cast without mana
* cost
* @param costs alternate other costs you need to pay
*/
void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts<ManaCost> manaCosts, Costs<Cost> costs);
UUID getCastSourceIdWithAlternateMana();
ManaCosts<ManaCost> getCastSourceIdManaCosts();
Costs<Cost> getCastSourceIdCosts();
// permission handling to show hand cards
void addPermissionToShowHandCards(UUID watcherUserId);
boolean hasUserPermissionToSeeHand(UUID userId);
void revokePermissionToSeeHandCards();
boolean isRequestToShowHandCardsAllowed();
Set<UUID> getUsersAllowedToSeeHandCards();
boolean isInPayManaMode();
void setMatchPlayer(MatchPlayer matchPlayer);
MatchPlayer getMatchPlayer();
boolean scry(int value, Ability source, Game game);
/**
* Only used for test player for pre-setting targets
*
* @param ability
* @param game
* @return
*/
boolean addTargets(Ability ability, Game game);
String getHistory();
}