mirror of
https://github.com/correl/mage.git
synced 2025-01-11 11:05:23 +00:00
Fixed Issue 441.
This commit is contained in:
parent
c5d2d41f60
commit
af05af7050
5 changed files with 220 additions and 163 deletions
|
@ -40,14 +40,17 @@ import mage.abilities.costs.mana.ManaCosts;
|
|||
import mage.abilities.costs.mana.VariableManaCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.SearchEffect;
|
||||
import mage.abilities.keyword.LevelUpAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.choices.Choice;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.Combat;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.game.turn.*;
|
||||
|
@ -472,6 +475,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
|
|||
//logger.info("simulating -- player " + currentPlayer.getName());
|
||||
SimulationNode2 bestNode = null;
|
||||
List<Ability> allActions = currentPlayer.simulatePriority(game);
|
||||
optimize(game, allActions);
|
||||
logger.debug("simulating -- adding " + allActions.size() + " children:" + allActions);
|
||||
for (Ability action: allActions) {
|
||||
if (Thread.interrupted()) {
|
||||
|
@ -482,8 +486,8 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
|
|||
Game sim = game.copy();
|
||||
if (sim.getPlayer(currentPlayer.getId()).activateAbility((ActivatedAbility) action.copy(), sim)) {
|
||||
sim.applyEffects();
|
||||
if (checkForRepeatedAction(sim, node, action, currentPlayer.getId()))
|
||||
continue;
|
||||
//if (checkForRepeatedAction(sim, node, action, currentPlayer.getId()))
|
||||
//continue;
|
||||
if (!sim.isGameOver() && action.isUsesStack()) {
|
||||
// only pass if the last action uses the stack
|
||||
sim.getPlayer(currentPlayer.getId()).pass();
|
||||
|
@ -567,6 +571,35 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Various AI optimizations for actions.
|
||||
*
|
||||
* @param allActions
|
||||
*/
|
||||
protected void optimize(Game game, List<Ability> allActions) {
|
||||
List<Ability> toRemove = null;
|
||||
for (Ability ability : allActions) {
|
||||
if (ability instanceof LevelUpAbility) {
|
||||
Permanent permanent = game.getPermanent(ability.getSourceId());
|
||||
if (permanent != null && permanent instanceof PermanentCard) {
|
||||
PermanentCard leveler = (PermanentCard) permanent;
|
||||
// check already existing Level counters and compare to maximum that make sense
|
||||
if (permanent.getCounters().getCount(CounterType.LEVEL) >= leveler.getMaxLevelCounters()) {
|
||||
if (toRemove == null) {
|
||||
toRemove = new ArrayList<Ability>();
|
||||
}
|
||||
toRemove.add(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toRemove != null) {
|
||||
for (Ability r : toRemove) {
|
||||
allActions.remove(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean allPassed(Game game) {
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (!player.isPassed() && !player.hasLost() && !player.hasLeft())
|
||||
|
@ -806,7 +839,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
|
|||
return sim;
|
||||
}
|
||||
|
||||
private boolean checkForRepeatedAction(Game sim, SimulationNode2 node, Ability action, UUID playerId) {
|
||||
/*private boolean checkForRepeatedAction(Game sim, SimulationNode2 node, Ability action, UUID playerId) {
|
||||
if (action instanceof PassAbility)
|
||||
return false;
|
||||
int val = GameStateEvaluator2.evaluate(playerId, sim);
|
||||
|
@ -820,7 +853,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
|
|||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
protected void getSuggestedActions() {
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package mage.player.ai.ma;
|
||||
|
||||
import mage.Constants;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.Card;
|
||||
|
@ -65,6 +64,7 @@ public class ArtificialScoringSystem {
|
|||
public static int getVariablePermanentScore(final Game game, final Permanent permanent) {
|
||||
|
||||
int score = permanent.getCounters().getCount(CounterType.CHARGE) * 30;
|
||||
score += permanent.getCounters().getCount(CounterType.LEVEL) * 30;
|
||||
score -= permanent.getDamage() * 2;
|
||||
if (!canTap(permanent)) {
|
||||
score += getTappedScore(permanent);
|
||||
|
@ -108,7 +108,13 @@ public class ArtificialScoringSystem {
|
|||
}
|
||||
|
||||
public static int getTappedScore(final Permanent permanent) {
|
||||
return permanent.getCardType().contains(Constants.CardType.CREATURE) ? -100 : -50;
|
||||
if (permanent.getCardType().contains(Constants.CardType.CREATURE)) {
|
||||
return -100;
|
||||
} else if (permanent.getCardType().contains(Constants.CardType.LAND)) {
|
||||
return -10;
|
||||
} else {
|
||||
return -50;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getLifeScore(final int life) {
|
||||
|
|
Binary file not shown.
|
@ -28,13 +28,14 @@
|
|||
|
||||
package mage.cards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.CardType;
|
||||
import mage.Constants.Rarity;
|
||||
import mage.abilities.keyword.LevelAbility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -66,6 +67,14 @@ public abstract class LevelerCard<T extends LevelerCard<T>> extends CardImpl<T>
|
|||
return null;
|
||||
}
|
||||
|
||||
public int getMaxLevelCounters() {
|
||||
for (LevelAbility levelerLevel: levels) {
|
||||
if (levelerLevel.getLevel2() == -1)
|
||||
return levelerLevel.getLevel1();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
List<String> rules = new ArrayList<String>();
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
|
||||
package mage.game.permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
|
@ -43,192 +40,204 @@ import mage.game.Game;
|
|||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class PermanentCard extends PermanentImpl<PermanentCard> {
|
||||
|
||||
protected List<String> levelerRules;
|
||||
protected List<String> levelerRules;
|
||||
protected int maxLevelCounters;
|
||||
protected Card card;
|
||||
|
||||
public PermanentCard(Card card, UUID controllerId) {
|
||||
super(card.getId(), card.getOwnerId(), controllerId, card.getName());
|
||||
public PermanentCard(Card card, UUID controllerId) {
|
||||
super(card.getId(), card.getOwnerId(), controllerId, card.getName());
|
||||
this.card = card.copy();
|
||||
init(card);
|
||||
}
|
||||
init(card);
|
||||
}
|
||||
|
||||
protected PermanentCard(UUID id, Card card, UUID controllerId) {
|
||||
super(card.getId(), card.getOwnerId(), controllerId, card.getName());
|
||||
protected PermanentCard(UUID id, Card card, UUID controllerId) {
|
||||
super(card.getId(), card.getOwnerId(), controllerId, card.getName());
|
||||
this.card = card.copy();
|
||||
init(card);
|
||||
}
|
||||
init(card);
|
||||
}
|
||||
|
||||
protected void init(Card card) {
|
||||
copyFromCard(card);
|
||||
/*if (card.getCardType().contains(CardType.PLANESWALKER)) {
|
||||
this.loyalty = new MageInt(card.getLoyalty().getValue());
|
||||
}*/
|
||||
if (card instanceof LevelerCard) {
|
||||
levelerRules = ((LevelerCard)card).getRules();
|
||||
}
|
||||
}
|
||||
protected void init(Card card) {
|
||||
copyFromCard(card);
|
||||
/*if (card.getCardType().contains(CardType.PLANESWALKER)) {
|
||||
this.loyalty = new MageInt(card.getLoyalty().getValue());
|
||||
}*/
|
||||
if (card instanceof LevelerCard) {
|
||||
levelerRules = ((LevelerCard) card).getRules();
|
||||
maxLevelCounters = ((LevelerCard) card).getMaxLevelCounters();
|
||||
}
|
||||
}
|
||||
|
||||
public PermanentCard(final PermanentCard permanent) {
|
||||
super(permanent);
|
||||
public PermanentCard(final PermanentCard permanent) {
|
||||
super(permanent);
|
||||
this.card = permanent.card;
|
||||
}
|
||||
this.maxLevelCounters = permanent.maxLevelCounters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(Game game) {
|
||||
// when the permanent is reset copy all original values from the card
|
||||
// must copy card each reset so that the original values don't get modified
|
||||
copyFromCard(card);
|
||||
super.reset(game);
|
||||
}
|
||||
@Override
|
||||
public void reset(Game game) {
|
||||
// when the permanent is reset copy all original values from the card
|
||||
// must copy card each reset so that the original values don't get modified
|
||||
copyFromCard(card);
|
||||
super.reset(game);
|
||||
}
|
||||
|
||||
protected void copyFromCard(Card card) {
|
||||
this.name = card.getName();
|
||||
protected void copyFromCard(Card card) {
|
||||
this.name = card.getName();
|
||||
this.abilities.clear();
|
||||
this.abilities.addAll(card.getAbilities());
|
||||
this.abilities.setControllerId(this.controllerId);
|
||||
this.abilities.addAll(card.getAbilities());
|
||||
this.abilities.setControllerId(this.controllerId);
|
||||
this.cardType.clear();
|
||||
this.cardType.addAll(card.getCardType());
|
||||
this.color = card.getColor().copy();
|
||||
this.manaCost = card.getManaCost().copy();
|
||||
this.power = card.getPower().copy();
|
||||
this.toughness = card.getToughness().copy();
|
||||
if (card instanceof LevelerCard) {
|
||||
LevelAbility level = ((LevelerCard)card).getLevel(this.getCounters().getCount(CounterType.LEVEL));
|
||||
if (level != null) {
|
||||
this.power.setValue(level.getPower());
|
||||
this.toughness.setValue(level.getToughness());
|
||||
for (Ability ability: level.getAbilities()) {
|
||||
this.addAbility(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.cardType.addAll(card.getCardType());
|
||||
this.color = card.getColor().copy();
|
||||
this.manaCost = card.getManaCost().copy();
|
||||
this.power = card.getPower().copy();
|
||||
this.toughness = card.getToughness().copy();
|
||||
if (card instanceof LevelerCard) {
|
||||
LevelAbility level = ((LevelerCard) card).getLevel(this.getCounters().getCount(CounterType.LEVEL));
|
||||
if (level != null) {
|
||||
this.power.setValue(level.getPower());
|
||||
this.toughness.setValue(level.getToughness());
|
||||
for (Ability ability : level.getAbilities()) {
|
||||
this.addAbility(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (card instanceof PermanentCard) {
|
||||
this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters;
|
||||
}
|
||||
this.subtype.clear();
|
||||
this.subtype.addAll(card.getSubtype());
|
||||
this.subtype.addAll(card.getSubtype());
|
||||
this.supertype.clear();
|
||||
this.supertype.addAll(card.getSupertype());
|
||||
this.expansionSetCode = card.getExpansionSetCode();
|
||||
this.rarity = card.getRarity();
|
||||
this.cardNumber = card.getCardNumber();
|
||||
this.supertype.addAll(card.getSupertype());
|
||||
this.expansionSetCode = card.getExpansionSetCode();
|
||||
this.rarity = card.getRarity();
|
||||
this.cardNumber = card.getCardNumber();
|
||||
|
||||
canTransform = card.canTransform();
|
||||
if (canTransform) {
|
||||
secondSideCard = card.getSecondCardFace();
|
||||
nightCard = card.isNightCard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) {
|
||||
// we only want to trigger abilities that are not on the underlying card ie. have been added by another effect
|
||||
// or we want to trigger abilities that only trigger on leaving the battlefield
|
||||
// card abilities will get triggered later when the card hits the new zone
|
||||
public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) {
|
||||
// we only want to trigger abilities that are not on the underlying card ie. have been added by another effect
|
||||
// or we want to trigger abilities that only trigger on leaving the battlefield
|
||||
// card abilities will get triggered later when the card hits the new zone
|
||||
List<UUID> triggered = new ArrayList<UUID>();
|
||||
for (TriggeredAbility ability: abilities.getTriggeredAbilities(event.getFromZone())) {
|
||||
if (!card.getAbilities().containsKey(ability.getId())) {
|
||||
if (ability.checkTrigger(event, game)) {
|
||||
for (TriggeredAbility ability : abilities.getTriggeredAbilities(event.getFromZone())) {
|
||||
if (!card.getAbilities().containsKey(ability.getId())) {
|
||||
if (ability.checkTrigger(event, game)) {
|
||||
triggered.add(ability.getId());
|
||||
ability.trigger(game, controllerId);
|
||||
}
|
||||
} else if (ability instanceof ZoneChangeTriggeredAbility && event.getFromZone() == Zone.BATTLEFIELD) {
|
||||
ZoneChangeTriggeredAbility zcAbility = (ZoneChangeTriggeredAbility)ability;
|
||||
if (zcAbility.getToZone() == null) {
|
||||
if (ability.checkTrigger(event, game)) {
|
||||
ability.trigger(game, controllerId);
|
||||
}
|
||||
} else if (ability instanceof ZoneChangeTriggeredAbility && event.getFromZone() == Zone.BATTLEFIELD) {
|
||||
ZoneChangeTriggeredAbility zcAbility = (ZoneChangeTriggeredAbility) ability;
|
||||
if (zcAbility.getToZone() == null) {
|
||||
if (ability.checkTrigger(event, game)) {
|
||||
triggered.add(ability.getId());
|
||||
ability.trigger(game, controllerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (TriggeredAbility ability: abilities.getTriggeredAbilities(event.getToZone())) {
|
||||
if (!card.getAbilities().containsKey(ability.getId())) {
|
||||
if (!triggered.contains(ability.getId()) && ability.checkTrigger(event, game)) {
|
||||
ability.trigger(game, controllerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ability.trigger(game, controllerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (TriggeredAbility ability : abilities.getTriggeredAbilities(event.getToZone())) {
|
||||
if (!card.getAbilities().containsKey(ability.getId())) {
|
||||
if (!triggered.contains(ability.getId()) && ability.checkTrigger(event, game)) {
|
||||
ability.trigger(game, controllerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null && controller.removeFromBattlefield(this, game)) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone);
|
||||
if (!game.replaceEvent(event)) {
|
||||
Player owner = game.getPlayer(ownerId);
|
||||
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
||||
if (owner != null) {
|
||||
switch (event.getToZone()) {
|
||||
case GRAVEYARD:
|
||||
owner.putInGraveyard(card, game, !flag);
|
||||
break;
|
||||
case HAND:
|
||||
owner.getHand().add(card);
|
||||
break;
|
||||
case EXILED:
|
||||
game.getExile().getPermanentExile().add(card);
|
||||
break;
|
||||
case LIBRARY:
|
||||
if (flag)
|
||||
owner.getLibrary().putOnTop(card, game);
|
||||
else
|
||||
owner.getLibrary().putOnBottom(card, game);
|
||||
break;
|
||||
case BATTLEFIELD:
|
||||
//should never happen
|
||||
break;
|
||||
}
|
||||
game.setZone(objectId, event.getToZone());
|
||||
game.fireEvent(event);
|
||||
return game.getState().getZone(objectId) == toZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null && controller.removeFromBattlefield(this, game)) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone);
|
||||
if (!game.replaceEvent(event)) {
|
||||
Player owner = game.getPlayer(ownerId);
|
||||
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
||||
if (owner != null) {
|
||||
switch (event.getToZone()) {
|
||||
case GRAVEYARD:
|
||||
owner.putInGraveyard(card, game, !flag);
|
||||
break;
|
||||
case HAND:
|
||||
owner.getHand().add(card);
|
||||
break;
|
||||
case EXILED:
|
||||
game.getExile().getPermanentExile().add(card);
|
||||
break;
|
||||
case LIBRARY:
|
||||
if (flag)
|
||||
owner.getLibrary().putOnTop(card, game);
|
||||
else
|
||||
owner.getLibrary().putOnBottom(card, game);
|
||||
break;
|
||||
case BATTLEFIELD:
|
||||
//should never happen
|
||||
break;
|
||||
}
|
||||
game.setZone(objectId, event.getToZone());
|
||||
game.fireEvent(event);
|
||||
return game.getState().getZone(objectId) == toZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null && controller.removeFromBattlefield(this, game)) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (exileId == null) {
|
||||
game.getExile().getPermanentExile().add(card);
|
||||
}
|
||||
else {
|
||||
game.getExile().createZone(exileId, name).add(card);
|
||||
}
|
||||
game.setZone(objectId, event.getToZone());
|
||||
game.fireEvent(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null && controller.removeFromBattlefield(this, game)) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (exileId == null) {
|
||||
game.getExile().getPermanentExile().add(card);
|
||||
} else {
|
||||
game.getExile().createZone(exileId, name).add(card);
|
||||
}
|
||||
game.setZone(objectId, event.getToZone());
|
||||
game.fireEvent(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermanentCard copy() {
|
||||
return new PermanentCard(this);
|
||||
}
|
||||
@Override
|
||||
public PermanentCard copy() {
|
||||
return new PermanentCard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
if (levelerRules == null)
|
||||
return super.getRules();
|
||||
List<String> rules = new ArrayList<String>();
|
||||
rules.addAll(super.getRules());
|
||||
rules.addAll(levelerRules);
|
||||
return rules;
|
||||
}
|
||||
public int getMaxLevelCounters() {
|
||||
return this.maxLevelCounters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
if (levelerRules == null)
|
||||
return super.getRules();
|
||||
List<String> rules = new ArrayList<String>();
|
||||
rules.addAll(super.getRules());
|
||||
rules.addAll(levelerRules);
|
||||
return rules;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue