966 lines
27 KiB
Java
966 lines
27 KiB
Java
package magic.model;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.TreeSet;
|
|
|
|
import magic.model.action.LoseGameAction;
|
|
import magic.model.choice.MagicBuilderManaCost;
|
|
import magic.model.event.MagicActivationPriority;
|
|
import magic.model.event.MagicSourceActivation;
|
|
import magic.model.event.MagicSourceManaActivation;
|
|
import magic.model.mstatic.MagicLayer;
|
|
import magic.model.mstatic.MagicPermanentStatic;
|
|
import magic.model.mstatic.MagicStatic;
|
|
import magic.model.player.AiProfile;
|
|
import magic.model.target.MagicTarget;
|
|
import magic.model.target.MagicTargetFilter;
|
|
import magic.model.target.MagicTargetType;
|
|
|
|
public class MagicPlayer extends MagicObjectImpl implements MagicSource, MagicTarget, MagicMappable<MagicPlayer> {
|
|
|
|
public static final MagicPlayer NONE = new MagicPlayer(-1, null, -1) {
|
|
@Override
|
|
public String toString() {
|
|
return "";
|
|
}
|
|
@Override
|
|
public boolean controlsPermanent(final MagicPermanent permanent) {
|
|
return false;
|
|
}
|
|
@Override
|
|
public boolean isValid() {
|
|
return false;
|
|
}
|
|
@Override
|
|
public MagicPlayer copy(final MagicCopyMap copyMap) {
|
|
return this;
|
|
}
|
|
@Override
|
|
public MagicGame getGame() {
|
|
throw new RuntimeException("getGame called for MagicPlayer.NONE");
|
|
}
|
|
@Override
|
|
public MagicPlayer getOpponent() {
|
|
return this;
|
|
}
|
|
};
|
|
|
|
private static final int LOSING_POISON=10;
|
|
private static final long ID_FACTOR=31;
|
|
|
|
private final DuelPlayerConfig playerConfig;
|
|
private final int index;
|
|
private final int startingLife;
|
|
|
|
private int stateFlags;
|
|
private int life;
|
|
private int lifeLossThisTurn;
|
|
private int lifeGainThisTurn;
|
|
private int poison;
|
|
private int experience;
|
|
private int energy;
|
|
private int preventDamage;
|
|
private int extraTurns;
|
|
private int drawnCards;
|
|
private int startingHandSize;
|
|
private int maxHandSize;
|
|
private int spellsCast;
|
|
private int nonCreatureSpellsCast;
|
|
private int spellsCastLastTurn;
|
|
private int creaturesAttackedThisTurn;
|
|
private final MagicCardList hand;
|
|
private final MagicCardList library;
|
|
private final MagicCardList graveyard;
|
|
private final MagicCardList exile;
|
|
private final MagicPermanentSet permanents;
|
|
private MagicGame currGame;
|
|
private MagicBuilderManaCost builderCost;
|
|
private MagicActivationPriority activationPriority;
|
|
private Set<MagicAbility> cachedAbilityFlags;
|
|
|
|
private long[] keys;
|
|
|
|
MagicPlayer(final int aLife,final DuelPlayerConfig aPlayerConfig,final int aIndex) {
|
|
playerConfig = aPlayerConfig;
|
|
index = aIndex;
|
|
startingLife = aLife;
|
|
life = startingLife;
|
|
|
|
hand=new MagicCardList();
|
|
library=new MagicCardList();
|
|
graveyard=new MagicCardList();
|
|
exile=new MagicCardList();
|
|
permanents=new MagicPermanentSet();
|
|
builderCost=new MagicBuilderManaCost();
|
|
activationPriority=new MagicActivationPriority();
|
|
}
|
|
|
|
private MagicPlayer(final MagicCopyMap copyMap, final MagicPlayer sourcePlayer) {
|
|
copyMap.put(sourcePlayer, this);
|
|
|
|
playerConfig = sourcePlayer.playerConfig;
|
|
index = sourcePlayer.index;
|
|
startingLife = sourcePlayer.startingLife;
|
|
life = sourcePlayer.life;
|
|
lifeGainThisTurn = sourcePlayer.lifeGainThisTurn;
|
|
lifeLossThisTurn = sourcePlayer.lifeLossThisTurn;
|
|
poison=sourcePlayer.poison;
|
|
experience=sourcePlayer.experience;
|
|
energy=sourcePlayer.energy;
|
|
stateFlags=sourcePlayer.stateFlags;
|
|
preventDamage=sourcePlayer.preventDamage;
|
|
extraTurns=sourcePlayer.extraTurns;
|
|
drawnCards=sourcePlayer.drawnCards;
|
|
maxHandSize=sourcePlayer.maxHandSize;
|
|
spellsCast=sourcePlayer.spellsCast;
|
|
nonCreatureSpellsCast=sourcePlayer.nonCreatureSpellsCast;
|
|
spellsCastLastTurn=sourcePlayer.spellsCastLastTurn;
|
|
creaturesAttackedThisTurn=sourcePlayer.creaturesAttackedThisTurn;
|
|
hand=new MagicCardList(copyMap, sourcePlayer.hand);
|
|
library=new MagicCardList(copyMap, sourcePlayer.library);
|
|
graveyard=new MagicCardList(copyMap, sourcePlayer.graveyard);
|
|
exile=new MagicCardList(copyMap, sourcePlayer.exile);
|
|
permanents=new MagicPermanentSet(copyMap,sourcePlayer.permanents);
|
|
builderCost=new MagicBuilderManaCost(sourcePlayer.builderCost);
|
|
activationPriority=new MagicActivationPriority(sourcePlayer.activationPriority);
|
|
cachedAbilityFlags=sourcePlayer.cachedAbilityFlags;
|
|
}
|
|
|
|
@Override
|
|
public MagicPlayer copy(final MagicCopyMap copyMap) {
|
|
return new MagicPlayer(copyMap, this);
|
|
}
|
|
|
|
@Override
|
|
public MagicPlayer map(final MagicGame game) {
|
|
return game.getPlayer(index);
|
|
}
|
|
|
|
public void setGame(final MagicGame game) {
|
|
currGame = game;
|
|
}
|
|
|
|
@Override
|
|
public MagicGame getGame() {
|
|
return currGame;
|
|
}
|
|
|
|
@Override
|
|
public long getStateId() {
|
|
keys = new long[] {
|
|
life,
|
|
lifeLossThisTurn,
|
|
lifeGainThisTurn,
|
|
poison,
|
|
experience,
|
|
energy,
|
|
stateFlags,
|
|
preventDamage,
|
|
extraTurns,
|
|
drawnCards,
|
|
maxHandSize,
|
|
spellsCast,
|
|
nonCreatureSpellsCast,
|
|
spellsCastLastTurn,
|
|
creaturesAttackedThisTurn,
|
|
hand.getStateId(),
|
|
library.getStateId(),
|
|
graveyard.getStateId(),
|
|
exile.getStateId(),
|
|
permanents.getStateId(),
|
|
builderCost.getMinimumAmount(),
|
|
activationPriority.getPriority(),
|
|
activationPriority.getActivationId(),
|
|
cachedAbilityFlags.hashCode()
|
|
};
|
|
return MurmurHash3.hash(keys);
|
|
}
|
|
|
|
String getIdString() {
|
|
final StringBuilder sb = new StringBuilder();
|
|
sb.append(keys[0]);
|
|
for (int i = 1; i < keys.length; i++) {
|
|
sb.append(' ');
|
|
sb.append(keys[i]);
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
long getPlayerId(final long id) {
|
|
// Exile is not used for id.
|
|
long playerId=id;
|
|
playerId=playerId*ID_FACTOR+life;
|
|
playerId=playerId*ID_FACTOR+poison;
|
|
playerId=playerId*ID_FACTOR+experience;
|
|
playerId=playerId*ID_FACTOR+energy;
|
|
playerId=playerId*ID_FACTOR+builderCost.getMinimumAmount();
|
|
playerId=playerId*ID_FACTOR+permanents.getStateId();
|
|
playerId=playerId*ID_FACTOR+hand.getStateId();
|
|
playerId=playerId*ID_FACTOR+graveyard.getStateId();
|
|
return playerId;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return playerConfig.getName();
|
|
}
|
|
|
|
@Override
|
|
public Set<MagicSourceActivation<? extends MagicSource>> getSourceActivations() {
|
|
Set<MagicSourceActivation<? extends MagicSource>> set = new TreeSet<>();
|
|
for (final MagicCard card : hand) {
|
|
set.addAll(card.getSourceActivations());
|
|
}
|
|
for (final MagicCard card : graveyard) {
|
|
set.addAll(card.getSourceActivations());
|
|
}
|
|
for (final MagicPermanent perm : permanents) {
|
|
set.addAll(perm.getSourceActivations());
|
|
}
|
|
return set;
|
|
}
|
|
|
|
public DuelPlayerConfig getConfig() {
|
|
return playerConfig;
|
|
}
|
|
|
|
public int getIndex() {
|
|
return index;
|
|
}
|
|
|
|
@Override
|
|
public long getId() {
|
|
return 1000000000L + index;
|
|
}
|
|
|
|
public void setState(final MagicPlayerState state) {
|
|
stateFlags|=state.getMask();
|
|
}
|
|
|
|
public void clearState(final MagicPlayerState state) {
|
|
stateFlags&=Integer.MAX_VALUE-state.getMask();
|
|
}
|
|
|
|
public boolean hasState(final MagicPlayerState state) {
|
|
return state.hasState(stateFlags);
|
|
}
|
|
|
|
public boolean isMonarch() {
|
|
return hasState(MagicPlayerState.Monarch);
|
|
}
|
|
|
|
public int getStateFlags() {
|
|
return stateFlags;
|
|
}
|
|
|
|
public void setStateFlags(final int flags) {
|
|
stateFlags=flags;
|
|
}
|
|
|
|
public void setLife(final int life) {
|
|
this.life=life;
|
|
}
|
|
|
|
public int getLife() {
|
|
return life;
|
|
}
|
|
|
|
public int getPositiveLife() {
|
|
return life > 0 ? life : 0;
|
|
}
|
|
|
|
public int getHalfLifeRoundUp() {
|
|
return life < 0 ? 0 : (life + 1)/2;
|
|
}
|
|
|
|
public int getHalfLifeRoundDown() {
|
|
return life < 0 ? 0 : life / 2;
|
|
}
|
|
|
|
public int getLifeGainThisTurn() {
|
|
return lifeGainThisTurn;
|
|
}
|
|
|
|
public void setLifeGainThisTurn(final int lifeGainThisTurn) {
|
|
this.lifeGainThisTurn=lifeGainThisTurn;
|
|
}
|
|
|
|
public void changeLifeGainThisTurn(final int lifeGainThisTurn) {
|
|
this.lifeGainThisTurn+=lifeGainThisTurn;
|
|
}
|
|
|
|
public int getLifeLossThisTurn() {
|
|
return lifeLossThisTurn;
|
|
}
|
|
|
|
public void setLifeLossThisTurn(final int life) {
|
|
lifeLossThisTurn = life;
|
|
}
|
|
|
|
public void changeLifeLossThisTurn(final int life) {
|
|
lifeLossThisTurn += life;
|
|
}
|
|
|
|
public void setPoison(final int p) {
|
|
poison = p;
|
|
}
|
|
|
|
public int getPoison() {
|
|
return poison;
|
|
}
|
|
|
|
public void setExperience(final int e) {
|
|
experience = e;
|
|
}
|
|
|
|
public int getExperience() {
|
|
return experience;
|
|
}
|
|
|
|
public void setEnergy(final int e) {
|
|
energy = e;
|
|
}
|
|
|
|
public int getEnergy() {
|
|
return energy;
|
|
}
|
|
|
|
public void changeExtraTurns(final int amount) {
|
|
extraTurns+=amount;
|
|
}
|
|
|
|
public int getExtraTurns() {
|
|
return extraTurns;
|
|
}
|
|
|
|
public int getHandSize() {
|
|
return hand.size();
|
|
}
|
|
|
|
public int getStartingHandSize() {
|
|
return startingHandSize;
|
|
}
|
|
|
|
public int getStartingLife() {
|
|
return startingLife;
|
|
}
|
|
|
|
public int getNumExcessCards() {
|
|
return Math.max(0, getHandSize() - maxHandSize);
|
|
}
|
|
|
|
public void noMaxHandSize() {
|
|
maxHandSize = Integer.MAX_VALUE;
|
|
}
|
|
|
|
public void setMaxHandSize(final int amount) {
|
|
maxHandSize = amount;
|
|
}
|
|
|
|
public void reduceMaxHandSize(final int amount) {
|
|
maxHandSize -= amount;
|
|
}
|
|
|
|
public void increaseMaxHandSize(final int amount) {
|
|
maxHandSize += amount;
|
|
}
|
|
|
|
public int getCreaturesAttackedThisTurn() {
|
|
return creaturesAttackedThisTurn;
|
|
}
|
|
|
|
public void setCreaturesAttackedThisTurn(final int count) {
|
|
creaturesAttackedThisTurn=count;
|
|
}
|
|
|
|
public void incCreaturesAttacked() {
|
|
creaturesAttackedThisTurn++;
|
|
}
|
|
|
|
public void decCreaturesAttacked() {
|
|
creaturesAttackedThisTurn--;
|
|
}
|
|
|
|
public int getSpellsCastLastTurn() {
|
|
return spellsCastLastTurn;
|
|
}
|
|
|
|
public void setSpellsCastLastTurn(final int count) {
|
|
spellsCastLastTurn=count;
|
|
}
|
|
|
|
public int getSpellsCast() {
|
|
return spellsCast;
|
|
}
|
|
|
|
public void incSpellsCast() {
|
|
spellsCast++;
|
|
}
|
|
|
|
public int getNonCreatureSpellsCast() {
|
|
return nonCreatureSpellsCast;
|
|
}
|
|
|
|
public void setNonCreatureSpellsCast(final int count) {
|
|
nonCreatureSpellsCast=count;
|
|
}
|
|
|
|
public void incNonCreatureSpellsCast() {
|
|
nonCreatureSpellsCast++;
|
|
}
|
|
|
|
public void setSpellsCast(final int count) {
|
|
spellsCast=count;
|
|
}
|
|
|
|
public MagicCardList getPrivateHand() {
|
|
return hand;
|
|
}
|
|
|
|
public List<MagicCard> getHand() {
|
|
return Collections.unmodifiableList(hand);
|
|
}
|
|
|
|
public void addCardToHand(final MagicCard card) {
|
|
hand.addToTop(card);
|
|
}
|
|
|
|
public void addCardToHand(final MagicCard card,final int aIndex) {
|
|
hand.add(aIndex,card);
|
|
}
|
|
|
|
public int removeCardFromHand(final MagicCard card) {
|
|
return hand.removeCard(card);
|
|
}
|
|
|
|
void setHandToUnknown() {
|
|
hand.setAIKnown(false);
|
|
}
|
|
|
|
void showRandomizedHandAndLibrary() {
|
|
final MagicCardList unknownCards = new MagicCardList();
|
|
// gather all unknown cards
|
|
for (final MagicCard card : hand) {
|
|
if (card.isUnknown()) {
|
|
unknownCards.add(card);
|
|
}
|
|
}
|
|
for (final MagicCard card : library) {
|
|
if (card.isUnknown()) {
|
|
unknownCards.add(card);
|
|
}
|
|
}
|
|
|
|
unknownCards.shuffle(MagicRandom.nextRNGInt());
|
|
unknownCards.setAIKnown(true);
|
|
|
|
// fill in unknown cards
|
|
for (int i = 0; i < hand.size(); i++) {
|
|
final MagicCard card = hand.get(i);
|
|
if (card.isUnknown()) {
|
|
hand.set(i, unknownCards.removeCardAtTop());
|
|
}
|
|
}
|
|
|
|
// fill in unknown cards
|
|
for (int i = 0; i < library.size(); i++) {
|
|
final MagicCard card = library.get(i);
|
|
if (card.isUnknown()) {
|
|
library.set(i, unknownCards.removeCardAtTop());
|
|
}
|
|
}
|
|
}
|
|
|
|
// creating the MagicCard is potentially slow due to card ability loading,
|
|
// check for thread.isInterrupted to terminate early when interrupted
|
|
void createHandAndLibrary(final int handSize) {
|
|
startingHandSize = handSize;
|
|
final MagicDeck deck = playerConfig.getDeck();
|
|
Thread thread = Thread.currentThread();
|
|
for (int i = 0; i < deck.size() && !thread.isInterrupted(); i++) {
|
|
final MagicCardDefinition cardDefinition = deck.get(i);
|
|
if (cardDefinition.isValid()) {
|
|
final long id = currGame.getUniqueId();
|
|
library.add(new MagicCard(cardDefinition, this, id));
|
|
}
|
|
}
|
|
|
|
library.initialShuffle(MagicRandom.nextRNGInt());
|
|
|
|
for (int count = handSize; count > 0 && !library.isEmpty(); count--) {
|
|
addCardToHand(library.removeCardAtTop());
|
|
}
|
|
}
|
|
|
|
public MagicCardList getLibrary() {
|
|
return library;
|
|
}
|
|
|
|
public MagicCardList getGraveyard() {
|
|
return graveyard;
|
|
}
|
|
|
|
public MagicCardList getExile() {
|
|
return exile;
|
|
}
|
|
|
|
public MagicPermanentSet getPermanents() {
|
|
return permanents;
|
|
}
|
|
|
|
public List<MagicCard> filterCards(final MagicTargetFilter<MagicCard> filter) {
|
|
final List<MagicCard> targets = new ArrayList<>();
|
|
|
|
// Cards in graveyard
|
|
if (filter.acceptType(MagicTargetType.Graveyard)) {
|
|
addCards(targets, graveyard, filter);
|
|
}
|
|
|
|
// Cards in hand
|
|
if (filter.acceptType(MagicTargetType.Hand)) {
|
|
addCards(targets, hand, filter);
|
|
}
|
|
|
|
// Cards in library
|
|
if (filter.acceptType(MagicTargetType.Library)) {
|
|
addCards(targets, library, filter);
|
|
}
|
|
|
|
return targets;
|
|
}
|
|
|
|
public MagicCardList filterCards(final List<MagicCard> list, final MagicTargetFilter<MagicCard> filter) {
|
|
final MagicCardList targets = new MagicCardList();
|
|
addCards(targets, list, filter);
|
|
return targets;
|
|
}
|
|
|
|
private void addCards(final List<MagicCard> targets, final List<MagicCard> list, final MagicTargetFilter<MagicCard> filter) {
|
|
for (final MagicCard card : list) {
|
|
if (filter.accept(MagicSource.NONE, this, card)) {
|
|
targets.add(card);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void addPermanent(final MagicPermanent permanent) {
|
|
final boolean added = permanents.add(permanent);
|
|
assert added : permanent + " cannot be added to " + this;
|
|
}
|
|
|
|
public void removePermanent(final MagicPermanent permanent) {
|
|
final boolean removed = permanents.remove(permanent);
|
|
assert removed : permanent + " cannot be removed from " + this;
|
|
}
|
|
|
|
public List<MagicSourceManaActivation> getManaActivations(final MagicGame game) {
|
|
final List<MagicSourceManaActivation> activations= new ArrayList<>();
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (!permanent.producesMana()) {
|
|
continue;
|
|
}
|
|
|
|
if (game.isArtificial() && permanent.hasState(MagicPermanentState.ExcludeManaSource)) {
|
|
continue;
|
|
}
|
|
|
|
final MagicSourceManaActivation sourceActivation=new MagicSourceManaActivation(game,permanent);
|
|
if (sourceActivation.available) {
|
|
activations.add(sourceActivation);
|
|
}
|
|
}
|
|
return activations;
|
|
}
|
|
|
|
private int getManaActivationsCount(final MagicGame game) {
|
|
int count=0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (!permanent.producesMana()) {
|
|
continue;
|
|
}
|
|
final MagicSourceManaActivation sourceActivation=new MagicSourceManaActivation(game,permanent);
|
|
if (sourceActivation.available) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public void setBuilderCost(final MagicBuilderManaCost builderCost) {
|
|
this.builderCost=builderCost;
|
|
}
|
|
|
|
public MagicBuilderManaCost getBuilderCost() {
|
|
return builderCost;
|
|
}
|
|
|
|
public void setActivationPriority(final MagicActivationPriority abilityPriority) {
|
|
this.activationPriority=abilityPriority;
|
|
}
|
|
|
|
public MagicActivationPriority getActivationPriority() {
|
|
return activationPriority;
|
|
}
|
|
|
|
public int getMaximumX(final MagicGame game,final MagicManaCost cost) {
|
|
return (getManaActivationsCount(game) -
|
|
builderCost.getMinimumAmount() -
|
|
cost.getConvertedCost()) /
|
|
cost.getXCount();
|
|
}
|
|
|
|
public int getNrOfAttackers() {
|
|
return getNrOfPermanents(MagicPermanentState.Attacking);
|
|
}
|
|
|
|
public int getNrOfBlockers() {
|
|
return getNrOfPermanents(MagicPermanentState.Blocking);
|
|
}
|
|
|
|
public int getNrOfPermanents() {
|
|
return permanents.size();
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicPermanentState state) {
|
|
int count=0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasState(state)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicType type) {
|
|
int count=0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasType(type)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicSubType subType) {
|
|
int count=0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasSubType(subType)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicColor color) {
|
|
int count=0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasColor(color)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicType type, final MagicColor color) {
|
|
int count = 0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasColor(color) && permanent.hasType(type)){
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicTargetFilter<MagicPermanent> filter) {
|
|
return getNrOfPermanents(MagicSource.NONE, filter);
|
|
}
|
|
|
|
public int getNrOfPermanents(final MagicSource source, final MagicTargetFilter<MagicPermanent> filter) {
|
|
int count = 0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (filter.accept(source, this, permanent)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicTargetFilter<MagicPermanent> filter) {
|
|
return controlsPermanent(MagicSource.NONE, filter);
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicSource source, final MagicTargetFilter<MagicPermanent> filter) {
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (filter.accept(source, this, permanent)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicPermanent permanent) {
|
|
return permanents.contains(permanent);
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicColor color) {
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasColor(color)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicType type) {
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasType(type)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicSubType subType) {
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasSubType(subType)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean controlsPermanent(final MagicAbility ability) {
|
|
for (final MagicPermanent permanent : permanents) {
|
|
if (permanent.hasAbility(ability)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public int getDomain() {
|
|
int domain = 0;
|
|
for (final MagicSubType basicLandType : MagicSubType.ALL_BASIC_LANDS) {
|
|
if (this.controlsPermanent(basicLandType)) {
|
|
domain+=1;
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
|
|
public int getDevotion(final MagicColor... colors) {
|
|
int devotion = 0;
|
|
for (final MagicPermanent permanent : permanents) {
|
|
devotion += permanent.getDevotion(colors);
|
|
}
|
|
return devotion;
|
|
}
|
|
|
|
@Override
|
|
public MagicCardDefinition getCardDefinition() {
|
|
throw new RuntimeException("player has no card definition");
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return playerConfig.getName();
|
|
}
|
|
|
|
@Override
|
|
public boolean isPermanent() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPlayer() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSpell() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int getPreventDamage() {
|
|
return preventDamage;
|
|
}
|
|
|
|
@Override
|
|
public void setPreventDamage(final int amount) {
|
|
preventDamage=amount;
|
|
}
|
|
|
|
@Override
|
|
public MagicPlayer getController() {
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public MagicPlayer getOpponent() {
|
|
return currGame.getOpponent(this);
|
|
}
|
|
|
|
public boolean isValid() {
|
|
return true;
|
|
}
|
|
|
|
public void addAbility(final MagicAbility ability) {
|
|
cachedAbilityFlags.add(ability);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasAbility(final MagicAbility ability) {
|
|
return cachedAbilityFlags.contains(ability);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasType(final MagicType type) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasSubType(final MagicSubType subType) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasColor(final MagicColor color) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int getColorFlags() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean isValidTarget(final MagicSource source) {
|
|
// Can't be the target of spells or abilities.
|
|
if (hasAbility(MagicAbility.Shroud)) {
|
|
return false;
|
|
}
|
|
|
|
// Can't be the target of spells or abilities your opponents controls.
|
|
if (hasAbility(MagicAbility.Hexproof) && isEnemy(source)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isLegalTarget(final MagicPlayer player, final MagicTargetFilter<? extends MagicTarget> targetFilter) {
|
|
return true;
|
|
}
|
|
|
|
public void incDrawnCards() {
|
|
drawnCards++;
|
|
}
|
|
|
|
public void decDrawnCards() {
|
|
drawnCards--;
|
|
}
|
|
|
|
public void setDrawnCards(final int drawnCards) {
|
|
this.drawnCards = drawnCards;
|
|
}
|
|
|
|
public int getDrawnCards() {
|
|
return drawnCards;
|
|
}
|
|
|
|
public void generateStateBasedActions() {
|
|
if (getLife() <= 0) {
|
|
currGame.addDelayedAction(new LoseGameAction(this,LoseGameAction.LIFE_REASON));
|
|
}
|
|
if (getPoison() >= LOSING_POISON) {
|
|
currGame.addDelayedAction(new LoseGameAction(this,LoseGameAction.POISON_REASON));
|
|
}
|
|
}
|
|
|
|
public void apply(final MagicLayer layer) {
|
|
switch (layer) {
|
|
case Player:
|
|
cachedAbilityFlags = MagicAbility.noneOf();
|
|
stateFlags &= MagicPlayerState.TURN_MASK;
|
|
maxHandSize = 7;
|
|
break;
|
|
default:
|
|
throw new RuntimeException("No case for " + layer + " in MagicPlayer.apply");
|
|
}
|
|
}
|
|
|
|
private void apply(final MagicPermanent source, final MagicStatic mstatic) {
|
|
final MagicLayer layer = mstatic.getLayer();
|
|
switch (layer) {
|
|
case Player:
|
|
mstatic.modPlayer(source, this);
|
|
break;
|
|
default:
|
|
throw new RuntimeException("No case for " + layer + " in MagicPlayer.apply");
|
|
}
|
|
}
|
|
|
|
public static void update(final MagicGame game) {
|
|
for (final MagicPlayer player : game.getPlayers()) {
|
|
player.apply(MagicLayer.Player);
|
|
}
|
|
for (final MagicPermanentStatic mpstatic : game.getStatics(MagicLayer.Player)) {
|
|
final MagicStatic mstatic = mpstatic.getStatic();
|
|
final MagicPermanent source = mpstatic.getPermanent();
|
|
for (final MagicPlayer player : game.getPlayers()) {
|
|
if (mstatic.accept(game, source, source)) {
|
|
player.apply(source, mstatic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getCounters(final MagicCounterType counterType) {
|
|
switch (counterType) {
|
|
case Poison:
|
|
return getPoison();
|
|
case Experience:
|
|
return getExperience();
|
|
case Energy:
|
|
return getEnergy();
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void changeCounters(final MagicCounterType counterType,final int amount) {
|
|
switch (counterType) {
|
|
case Poison:
|
|
poison += amount;
|
|
break;
|
|
case Experience:
|
|
experience += amount;
|
|
break;
|
|
case Energy:
|
|
energy += amount;
|
|
break;
|
|
default:
|
|
throw new RuntimeException(counterType + " cannot be modified on player");
|
|
}
|
|
}
|
|
|
|
public boolean isHuman() {
|
|
return playerConfig.getProfile().isHuman();
|
|
}
|
|
|
|
public boolean isArtificial() {
|
|
return playerConfig.getProfile().isArtificial();
|
|
}
|
|
|
|
public AiProfile getAiProfile() {
|
|
return (AiProfile)playerConfig.getProfile();
|
|
}
|
|
}
|