- Added three bid life cards

This commit is contained in:
swordshine
2014-05-03 12:54:33 +00:00
parent d4783e1b89
commit e933ecc70c
14 changed files with 209 additions and 3 deletions

5
.gitattributes vendored
View File

@@ -37,6 +37,7 @@ forge-ai/src/main/java/forge/ai/ability/AnimateAllAi.java -text
forge-ai/src/main/java/forge/ai/ability/AttachAi.java -text
forge-ai/src/main/java/forge/ai/ability/BalanceAi.java -text
forge-ai/src/main/java/forge/ai/ability/BecomesBlockedAi.java -text
forge-ai/src/main/java/forge/ai/ability/BidLifeAi.java -text
forge-ai/src/main/java/forge/ai/ability/BondAi.java -text
forge-ai/src/main/java/forge/ai/ability/CanPlayAsDrawbackAi.java -text
forge-ai/src/main/java/forge/ai/ability/CannotPlayAi.java -text
@@ -296,6 +297,7 @@ forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java svneo
forge-game/src/main/java/forge/game/ability/effects/AttachEffect.java -text
forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java -text
forge-game/src/main/java/forge/game/ability/effects/BecomesBlockedEffect.java -text
forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java -text
forge-game/src/main/java/forge/game/ability/effects/BondEffect.java -text
forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java -text
forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java -text
@@ -6877,6 +6879,7 @@ forge-gui/res/cardsfolder/i/iizuka_the_ruthless.txt svneol=native#text/plain
forge-gui/res/cardsfolder/i/ikiral_outrider.txt svneol=native#text/plain
forge-gui/res/cardsfolder/i/ill_gotten_gains.txt svneol=native#text/plain
forge-gui/res/cardsfolder/i/ill_tempered_cyclops.txt -text
forge-gui/res/cardsfolder/i/illicit_auction.txt -text
forge-gui/res/cardsfolder/i/illness_in_the_ranks.txt -text
forge-gui/res/cardsfolder/i/illuminate.txt -text
forge-gui/res/cardsfolder/i/illuminated_folio.txt -text
@@ -8135,6 +8138,7 @@ forge-gui/res/cardsfolder/m/mage_il_vec.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mage_slayer.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/magebane_armor.txt -text
forge-gui/res/cardsfolder/m/magefire_wings.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mages_contest.txt -text
forge-gui/res/cardsfolder/m/mages_guile.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mageta_the_lion.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/magetas_boon.txt svneol=native#text/plain
@@ -9590,6 +9594,7 @@ forge-gui/res/cardsfolder/p/pain_suffering.txt -text
forge-gui/res/cardsfolder/p/painbringer.txt -text svneol=unset#text/plain
forge-gui/res/cardsfolder/p/painful_memories.txt svneol=native#text/plain
forge-gui/res/cardsfolder/p/painful_quandary.txt -text
forge-gui/res/cardsfolder/p/pains_reward.txt -text
forge-gui/res/cardsfolder/p/painsmith.txt svneol=native#text/plain
forge-gui/res/cardsfolder/p/painters_servant.txt svneol=native#text/plain
forge-gui/res/cardsfolder/p/painwracker_oni.txt svneol=native#text/plain

View File

@@ -922,6 +922,22 @@ public class AiController {
return SpellApiToAi.Converter.get(api).confirmAction(player, sa, mode, message);
}
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode mode, String message,
int bid, Player winner) {
if (mode != null) switch (mode) {
case BidLife:
if (sa.hasParam("AIBidMax")) {
return !player.equals(winner) && bid < Integer.parseInt(sa.getParam("AIBidMax")) && player.getLife() > bid + 5;
} else {
return false;
}
default:
return false;
}
return false;
}
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
if (logic.equalsIgnoreCase("ProtectFriendly")) {
final Player controller = hostCard.getController();

View File

@@ -122,6 +122,8 @@ public class PlayerControllerAi extends PlayerController {
switch (ability.getApi()) {
case ChooseNumber:
return ability.getActivatingPlayer().isOpponentOf(player) ? 0 : ComputerUtilMana.determineLeftoverMana(ability, player);
case BidLife:
return 0;
default:
return null;
}
@@ -166,6 +168,12 @@ public class PlayerControllerAi extends PlayerController {
public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) {
return getAi().confirmAction(sa, mode, message);
}
@Override
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode mode, String string,
int bid, Player winner) {
return getAi().confirmBidAction(sa, mode, string, bid, winner);
}
@Override
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {

View File

@@ -22,6 +22,7 @@ public enum SpellApiToAi {
apiToClass.put(ApiType.Attach, AttachAi.class);
apiToClass.put(ApiType.Balance, BalanceAi.class);
apiToClass.put(ApiType.BecomesBlocked, BecomesBlockedAi.class);
apiToClass.put(ApiType.BidLife, BidLifeAi.class);
apiToClass.put(ApiType.Bond, BondAi.class);
apiToClass.put(ApiType.ChangeTargets, ChangeTargetsAi.class);
apiToClass.put(ApiType.ChangeZone, ChangeZoneAi.class);

View File

@@ -0,0 +1,53 @@
package forge.ai.ability;
import java.util.List;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
public class BidLifeAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
final Card source = sa.getHostCard();
final Game game = source.getGame();
TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (tgt.canTgtCreature()) {
List<Card> list = CardLists.getTargetableCards(aiPlayer.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, tgt.getValidTgts(), source.getController(), source);
if (list.isEmpty()) {
return false;
}
Card c = ComputerUtilCard.getBestCreatureAI(list);
sa.getTargets().add(c);
} else if (tgt.getZone().contains(ZoneType.Stack)) {
if (game.getStack().isEmpty()) {
return false;
}
final SpellAbility topSA = game.getStack().peekAbility();
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || aiPlayer.equals(topSA.getActivatingPlayer())) {
return false;
}
if (sa.canTargetSpellAbility(topSA)) {
sa.getTargets().add(topSA);
} else {
return false;
}
}
}
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
return chance;
}
}

View File

@@ -21,6 +21,7 @@ public enum ApiType {
Attach (AttachEffect.class),
Balance (BalanceEffect.class),
BecomesBlocked (BecomesBlockedEffect.class),
BidLife (BidLifeEffect.class),
Bond (BondEffect.class),
ChangeTargets (ChangeTargetsEffect.class),
ChangeZone (ChangeZoneEffect.class),

View File

@@ -0,0 +1,81 @@
package forge.game.ability.effects;
import com.google.common.collect.Iterables;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import java.util.ArrayList;
import java.util.List;
public class BidLifeEffect extends SpellAbilityEffect {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected String getStackDescription(SpellAbility sa) {
return "Bid Life";
}
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellEffect#resolve(java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final Player activator = sa.getActivatingPlayer();
final List<Player> bidPlayers = new ArrayList<Player>();
final int startBidding;
if (sa.hasParam("StartBidding")) {
String start = sa.getParam("StartBidding");
if ("Any".equals(start)) {
startBidding = activator.getController().announceRequirements(sa, "Choose a starting bid", true);
} else {
startBidding = AbilityUtils.calculateAmount(host, start, sa);
}
} else {
startBidding = 0;
}
if (sa.hasParam("OtherBidder")) {
bidPlayers.add(activator);
bidPlayers.addAll(AbilityUtils.getDefinedPlayers(host, sa.getParam("OtherBidder"), sa));
} else{
bidPlayers.addAll(activator.getGame().getPlayers());
int pSize = bidPlayers.size();
// start with the activator
while (bidPlayers.contains(activator) && !activator.equals(Iterables.getFirst(bidPlayers, null))) {
bidPlayers.add(pSize - 1, bidPlayers.remove(0));
}
}
boolean willBid = true;
Player winner = activator;
int bid = startBidding;
while (willBid) {
willBid = false;
for (final Player p : bidPlayers) {
final boolean result = p.getController().confirmBidAction(sa, PlayerActionConfirmMode.BidLife,
"Do you want to top bid? Current Bid =" + String.valueOf(bid), bid, winner);
willBid |= result;
if (result) { // a different choose number
bid += p.getController().chooseNumber(sa, "Bid life:", 1, 9);
winner = p;
}
}
}
host.setChosenNumber(bid);
host.addRemembered(winner);
final SpellAbility action = AbilityFactory.getAbility(host.getSVar(sa.getParam("BidSubAbility")), host);
action.setActivatingPlayer(sa.getActivatingPlayer());
((AbilitySub) action).setParent(sa);
AbilityUtils.resolve(action);
host.clearRemembered();
}
}

View File

@@ -11,6 +11,7 @@ public enum PlayerActionConfirmMode {
ChangeZoneToAltDestination,
ChangeZoneFromAltSource,
ChangeZoneGeneral,
BidLife,
Tribute;
// Ripple;

View File

@@ -143,6 +143,7 @@ public abstract class PlayerController {
public abstract SpellAbility chooseSingleSpellForEffect(List<SpellAbility> spells, SpellAbility sa, String title);
public abstract boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message);
public abstract boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife, String string, int bid, Player winner);
public abstract boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message);
public abstract boolean confirmTrigger(SpellAbility sa, Trigger regtrig, Map<String, String> triggerParams, boolean isMandatory);
public abstract boolean getWillPlayOnFirstTurn(boolean isFirstGame);
@@ -234,8 +235,6 @@ public abstract class PlayerController {
public abstract String chooseCardName(SpellAbility sa, Predicate<PaperCard> cpp, String valid, String message);
// better to have this odd method than those if playerType comparison in ChangeZone
public abstract Card chooseSingleCardForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, List<Card> fetchList, String selectPrompt, boolean b, Player decider);
public abstract Card chooseSingleCardForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, List<Card> fetchList, String selectPrompt, boolean b, Player decider);
}

View File

@@ -173,6 +173,12 @@ public class PlayerControllerForTests extends PlayerController {
return true;
}
@Override
public boolean confirmBidAction(SpellAbility sa,
PlayerActionConfirmMode bidlife, String string, int bid, Player winner) {
return false;
}
@Override
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
return true;
@@ -600,4 +606,5 @@ public class PlayerControllerForTests extends PlayerController {
// TODO Auto-generated method stub
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
}
}

View File

@@ -0,0 +1,9 @@
Name:Illicit Auction
ManaCost:3 R R
Types:Sorcery
A:SP$ BidLife | Cost$ 3 R R | ValidTgts$ Creature | AILogic$ Min | AIBidMax$ 8 | BidSubAbility$ DBLoseLife | SpellDescription$ Each player may bid life for control of target creature. You start the bidding with a bid of 0. 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 gains control of the creature. (This effect lasts indefinitely.)
SVar:DBLoseLife:DB$ LoseLife | Defined$ Remembered | LifeAmount$ X | References$ X | SubAbility$ DBControl
SVar:DBControl:DB$ GainControl | Defined$ Targeted | NewController$ Remembered
SVar:X:Count$ChosenNumber
SVar:Picture:http://www.wizards.com/global/images/magic/general/illicit_auction.jpg
Oracle:Each player may bid life for control of target creature. You start the bidding with a bid of 0. 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 gains control of the creature. (This effect lasts indefinitely.)

View File

@@ -0,0 +1,9 @@
Name:Mages' Contest
ManaCost:1 R R
Types:Instant
A:SP$ BidLife | Cost$ 1 R R | TargetType$ Spell | ValidTgts$ Card | TgtZone$ Stack | OtherBidder$ TargetedController | StartBidding$ 1 | AILogic$ Min | AIBidMax$ 8 | BidSubAbility$ DBLoseLife | SpellDescription$ You and target spell's controller bid life. You start the bidding with a bid of 1. 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. If you win the bidding, counter that spell.
SVar:DBLoseLife:DB$ LoseLife | Defined$ Remembered | LifeAmount$ X | References$ X | SubAbility$ DBCounter
SVar:DBCounter:DB$ Counter | Defined$ Targeted | ConditionPlayerDefined$ Remembered | ConditionPlayerContains$ You
SVar:X:Count$ChosenNumber
SVar:Picture:http://www.wizards.com/global/images/magic/general/mages_contest.jpg
Oracle:You and target spell's controller bid life. You start the bidding with a bid of 1. 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. If you win the bidding, counter that spell.

View File

@@ -0,0 +1,9 @@
Name:Pain's Reward
ManaCost:2 B
Types:Sorcery
A:SP$ BidLife | Cost$ 2 B | StartBidding$ Any | AILogic$ Min | AIBidMax$ 10 | BidSubAbility$ DBLoseLife | SpellDescription$ 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.
SVar:DBLoseLife:DB$ LoseLife | Defined$ Remembered | LifeAmount$ X | References$ X | SubAbility$ DBDraw
SVar:DBDraw:DB$ Draw | Defined$ Remembered | NumCards$ 4
SVar:X:Count$ChosenNumber
SVar:Picture:http://www.wizards.com/global/images/magic/general/pains_reward.jpg
Oracle: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.

View File

@@ -317,6 +317,12 @@ public class PlayerControllerHuman extends PlayerController {
return SGuiDialog.confirm(sa.getHostCard(), message);
}
@Override
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife,
String string, int bid, Player winner) {
return SGuiDialog.confirm(sa.getHostCard(), string + " Highest Bidder " + winner);
}
@Override
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
return SGuiDialog.confirm(hostCard, message);
@@ -1032,4 +1038,5 @@ public class PlayerControllerHuman extends PlayerController {
public Card chooseSingleCardForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, List<Card> fetchList, String selectPrompt, boolean b, Player decider) {
return chooseSingleEntityForEffect(fetchList, sa, selectPrompt, b, decider);
}
}