mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
* Choice of Damnations - improved AI support, fixed rollback error in AI games;
* Pain's Reward - improved AI support, fixed rollback error in AI games; * Volcano Hellion - improved AI support, fixed rollback error in AI games;
This commit is contained in:
parent
ac98a3a31a
commit
f692a1f097
5 changed files with 79 additions and 35 deletions
|
@ -50,10 +50,7 @@ import mage.players.net.UserData;
|
|||
import mage.players.net.UserGroup;
|
||||
import mage.target.*;
|
||||
import mage.target.common.*;
|
||||
import mage.util.Copier;
|
||||
import mage.util.RandomUtil;
|
||||
import mage.util.TournamentUtil;
|
||||
import mage.util.TreeNode;
|
||||
import mage.util.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -1666,8 +1663,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
@Override
|
||||
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) {
|
||||
log.debug("announceXCost");
|
||||
//TODO: improve this
|
||||
int value = RandomUtil.nextInt(max + 1);
|
||||
int value = RandomUtil.nextInt(CardUtil.overflowInc(max, 1));
|
||||
if (value < min) {
|
||||
value = min;
|
||||
}
|
||||
|
@ -1964,9 +1960,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
if (message.startsWith("Assign damage to ")) {
|
||||
return min;
|
||||
}
|
||||
//TODO: improve this
|
||||
if (min < max && min == 0) {
|
||||
return RandomUtil.nextInt(max + 1);
|
||||
return RandomUtil.nextInt(CardUtil.overflowInc(max, 1));
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
|
@ -18,14 +16,15 @@ import mage.target.Target;
|
|||
import mage.target.common.TargetControlledPermanent;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class ChoiceOfDamnations extends CardImpl {
|
||||
|
||||
public ChoiceOfDamnations(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{B}");
|
||||
this.subtype.add(SubType.ARCANE);
|
||||
|
||||
// Target opponent chooses a number. You may have that player lose that much life. If you don't, that player sacrifices all but that many permanents.
|
||||
|
@ -63,13 +62,40 @@ class ChoiceOfDamnationsEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
if (targetPlayer != null) {
|
||||
int amount = targetPlayer.getAmount(0, Integer.MAX_VALUE, "Chooses a number", game);
|
||||
int numberPermanents = game.getState().getBattlefield().countAll(new FilterPermanent(), targetPlayer.getId(), game);
|
||||
|
||||
// AI hint
|
||||
int amount;
|
||||
if (!targetPlayer.isHuman() && !targetPlayer.isTestMode()) {
|
||||
// AI as defender
|
||||
int safeLifeToLost = Math.max(0, targetPlayer.getLife() / 2);
|
||||
amount = Math.min(numberPermanents, safeLifeToLost);
|
||||
} else {
|
||||
// Human must choose
|
||||
amount = targetPlayer.getAmount(0, Integer.MAX_VALUE, "Chooses a number", game);
|
||||
}
|
||||
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
if (controller.chooseUse(outcome, "Shall " + targetPlayer.getLogName() + " lose " + amount + " life?", source, game)) {
|
||||
|
||||
// AI hint
|
||||
boolean chooseLoseLife;
|
||||
if (!targetPlayer.isHuman() && !targetPlayer.isTestMode()) {
|
||||
// AI as attacker
|
||||
chooseLoseLife = (numberPermanents == 0 || amount <= numberPermanents || targetPlayer.getLife() < amount);
|
||||
} else {
|
||||
// Human must choose
|
||||
chooseLoseLife = controller.chooseUse(outcome, "Shall " + targetPlayer.getLogName() + " lose " + amount + " life?", source, game);
|
||||
}
|
||||
|
||||
if (chooseLoseLife) {
|
||||
targetPlayer.loseLife(amount, game, source, false);
|
||||
} else {
|
||||
int numberPermanents = game.getState().getBattlefield().countAll(new FilterPermanent(), targetPlayer.getId(), game);
|
||||
// rules:
|
||||
// If the opponent must sacrifice all but a number of permanents, that opponent chooses that many
|
||||
// permanents and then sacrifices the rest. If the number chosen is greater than the number of
|
||||
// permanents the opponent controls, the player sacrifices nothing.
|
||||
// (2005-06-01)
|
||||
if (numberPermanents > amount) {
|
||||
int numberToSacrifice = numberPermanents - amount;
|
||||
Target target = new TargetControlledPermanent(numberToSacrifice, numberToSacrifice, new FilterControlledPermanent("permanent you control to sacrifice"), false);
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
|
||||
package mage.cards.p;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -13,15 +10,16 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.players.PlayerList;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class PainsReward extends CardImpl {
|
||||
|
||||
public PainsReward(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
|
||||
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
|
||||
|
||||
// Each player may bid life. You start the bidding with a bid of any number. In turn order, each player may top the high bid. The bidding ends if the high bid stands. The high bidder loses life equal to the high bid and draws four cards.
|
||||
this.getSpellAbility().addEffect(new PainsRewardEffect());
|
||||
|
@ -62,14 +60,19 @@ class PainsRewardEffect extends OneShotEffect {
|
|||
playerList.setCurrent(controller.getId());
|
||||
Player winner = game.getPlayer(controller.getId());
|
||||
|
||||
int highBid = controller.getAmount(0, Integer.MAX_VALUE, "Choose amount of life to bid", game);
|
||||
int highBid = chooseLifeAmountToBid(controller, -1, game); // -1 for start with 0 min big
|
||||
game.informPlayers(winner.getLogName() + " has bet " + highBid + " lifes");
|
||||
|
||||
Player currentPlayer = playerList.getNextInRange(controller, game);
|
||||
while (currentPlayer != null && !Objects.equals(currentPlayer, winner)) {
|
||||
String text = winner.getLogName() + " has bet " + highBid + " life" + (highBid > 1 ? "s" : "") + ". Top the bid?";
|
||||
if (currentPlayer.chooseUse(Outcome.Detriment, text, source, game)) {
|
||||
int newBid = currentPlayer.getAmount(highBid + 1, Integer.MAX_VALUE, "Choose amount of life to bid", game);
|
||||
|
||||
// AI hint
|
||||
int safeLifeToLost = Math.min(6, currentPlayer.getLife() / 2);
|
||||
Outcome aiOutcome = (highBid + 1 <= safeLifeToLost) ? Outcome.Benefit : Outcome.Detriment;
|
||||
|
||||
if (currentPlayer.chooseUse(aiOutcome, text, source, game)) {
|
||||
int newBid = chooseLifeAmountToBid(currentPlayer, highBid, game);
|
||||
if (newBid > highBid) {
|
||||
highBid = newBid;
|
||||
winner = currentPlayer;
|
||||
|
@ -86,4 +89,16 @@ class PainsRewardEffect extends OneShotEffect {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int chooseLifeAmountToBid(Player player, int currentBig, Game game) {
|
||||
int newBid;
|
||||
if (!player.isHuman() && !player.isTestMode()) {
|
||||
// AI choose
|
||||
newBid = currentBig + 1;
|
||||
} else {
|
||||
// Human choose
|
||||
newBid = player.getAmount(currentBig + 1, Integer.MAX_VALUE, "Choose amount of life to bid", game);
|
||||
}
|
||||
return newBid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.v;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
|
@ -11,15 +9,16 @@ import mage.abilities.keyword.EchoAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class VolcanoHellion extends CardImpl {
|
||||
|
@ -54,7 +53,7 @@ public final class VolcanoHellion extends CardImpl {
|
|||
class VolcanoHellionEffect extends OneShotEffect {
|
||||
|
||||
public VolcanoHellionEffect() {
|
||||
super(Outcome.AIDontUseIt);
|
||||
super(Outcome.Damage);
|
||||
this.staticText = "it deals an amount of damage of your choice to you and target creature. The damage can't be prevented";
|
||||
}
|
||||
|
||||
|
@ -72,7 +71,20 @@ class VolcanoHellionEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (controller != null) {
|
||||
int amount = controller.getAmount(0, Integer.MAX_VALUE, "Choose the amount of damage to deliver to you and a target creature. The damage can't be prevented.", game);
|
||||
int amount;
|
||||
if (!controller.isHuman() && !controller.isTestMode()) {
|
||||
// AI hint: have much life and can destroy target permanent
|
||||
int safeLifeToLost = Math.min(6, controller.getLife() / 2);
|
||||
if (permanent != null && permanent.getToughness().getValue() <= safeLifeToLost) {
|
||||
amount = permanent.getToughness().getValue();
|
||||
} else {
|
||||
amount = 0;
|
||||
}
|
||||
} else {
|
||||
//Human choose
|
||||
amount = controller.getAmount(0, Integer.MAX_VALUE, "Choose the amount of damage to deliver to you and a target creature. The damage can't be prevented.", game);
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
controller.damage(amount, source.getSourceId(), source, game, false, false);
|
||||
if (permanent != null) {
|
||||
|
|
|
@ -46,10 +46,6 @@ public class ModalDoubleFacesCardsInCommanderTest extends CardTestCommanderDuelB
|
|||
addCard(Zone.LIBRARY, playerA, "Forest");
|
||||
addCard(Zone.LIBRARY, playerA, "Grizzly Bears");
|
||||
addCard(Zone.LIBRARY, playerA, "Forest");
|
||||
//
|
||||
// Exile target artifact or enchantment.
|
||||
addCard(Zone.HAND, playerB, "Ironwright's Cleansing"); // {2}{W}
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains");
|
||||
|
||||
// prepare mdf
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "The Prismatic Bridge");
|
||||
|
|
Loading…
Reference in a new issue