Fixed Issue 441.

This commit is contained in:
magenoxx 2011-12-11 15:53:34 +04:00
parent c5d2d41f60
commit af05af7050
5 changed files with 220 additions and 163 deletions

View file

@ -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 {

View file

@ -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) {

View file

@ -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>();

View file

@ -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;
}
}