mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
- Added three bid life cards
This commit is contained in:
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
53
forge-ai/src/main/java/forge/ai/ability/BidLifeAi.java
Normal file
53
forge-ai/src/main/java/forge/ai/ability/BidLifeAi.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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),
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public enum PlayerActionConfirmMode {
|
||||
ChangeZoneToAltDestination,
|
||||
ChangeZoneFromAltSource,
|
||||
ChangeZoneGeneral,
|
||||
BidLife,
|
||||
Tribute;
|
||||
// Ripple;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
9
forge-gui/res/cardsfolder/i/illicit_auction.txt
Normal file
9
forge-gui/res/cardsfolder/i/illicit_auction.txt
Normal 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.)
|
||||
9
forge-gui/res/cardsfolder/m/mages_contest.txt
Normal file
9
forge-gui/res/cardsfolder/m/mages_contest.txt
Normal 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.
|
||||
9
forge-gui/res/cardsfolder/p/pains_reward.txt
Normal file
9
forge-gui/res/cardsfolder/p/pains_reward.txt
Normal 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.
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user