diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index 5248d95f1ed..34fdf84590c 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -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 implements //logger.info("simulating -- player " + currentPlayer.getName()); SimulationNode2 bestNode = null; List 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 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 implements } } + /** + * Various AI optimizations for actions. + * + * @param allActions + */ + protected void optimize(Game game, List allActions) { + List 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(); + } + 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 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 implements } } return false; - } + }*/ protected void getSuggestedActions() { try { diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java index f0db2eed657..de0a95122d9 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java @@ -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) { diff --git a/Mage.Server/plugins/mage-player-ai-ma.jar b/Mage.Server/plugins/mage-player-ai-ma.jar index 06fe71dda0c..083c03e4e59 100644 Binary files a/Mage.Server/plugins/mage-player-ai-ma.jar and b/Mage.Server/plugins/mage-player-ai-ma.jar differ diff --git a/Mage/src/mage/cards/LevelerCard.java b/Mage/src/mage/cards/LevelerCard.java index 176745bf444..371d8a3e8ba 100644 --- a/Mage/src/mage/cards/LevelerCard.java +++ b/Mage/src/mage/cards/LevelerCard.java @@ -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> extends CardImpl return null; } + public int getMaxLevelCounters() { + for (LevelAbility levelerLevel: levels) { + if (levelerLevel.getLevel2() == -1) + return levelerLevel.getLevel1(); + } + return 0; + } + @Override public List getRules() { List rules = new ArrayList(); diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index bc879b207a7..8265fbd3e39 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -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 { - protected List levelerRules; + protected List 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 triggered = new ArrayList(); - 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 getRules() { - if (levelerRules == null) - return super.getRules(); - List rules = new ArrayList(); - rules.addAll(super.getRules()); - rules.addAll(levelerRules); - return rules; - } + public int getMaxLevelCounters() { + return this.maxLevelCounters; + } + + @Override + public List getRules() { + if (levelerRules == null) + return super.getRules(); + List rules = new ArrayList(); + rules.addAll(super.getRules()); + rules.addAll(levelerRules); + return rules; + } }