mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 09:48:02 +00:00
Merge branch 'trig' into 'master'
makeChoices for Trigger: move to stack entry See merge request core-developers/forge!5028
This commit is contained in:
@@ -510,7 +510,6 @@ public class AiController {
|
|||||||
landList = unreflectedLands;
|
landList = unreflectedLands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//try to skip lands that enter the battlefield tapped
|
//try to skip lands that enter the battlefield tapped
|
||||||
if (!nonLandsInHand.isEmpty()) {
|
if (!nonLandsInHand.isEmpty()) {
|
||||||
CardCollection nonTappedLands = new CardCollection();
|
CardCollection nonTappedLands = new CardCollection();
|
||||||
@@ -534,6 +533,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO if this is the only source for a color we need badly prioritize it instead
|
||||||
if (foundTapped) {
|
if (foundTapped) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -813,7 +813,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Cost payCosts = sa.getPayCosts();
|
Cost payCosts = sa.getPayCosts();
|
||||||
if(payCosts != null) {
|
if (payCosts != null) {
|
||||||
ManaCost mana = payCosts.getTotalMana();
|
ManaCost mana = payCosts.getTotalMana();
|
||||||
if (mana != null) {
|
if (mana != null) {
|
||||||
if (mana.countX() > 0) {
|
if (mana.countX() > 0) {
|
||||||
@@ -1916,7 +1916,7 @@ public class AiController {
|
|||||||
if (sa.hasParam("AIMaxAmount")) {
|
if (sa.hasParam("AIMaxAmount")) {
|
||||||
max = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("AIMaxAmount"), sa);
|
max = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("AIMaxAmount"), sa);
|
||||||
}
|
}
|
||||||
switch(sa.getApi()) {
|
switch (sa.getApi()) {
|
||||||
case TwoPiles:
|
case TwoPiles:
|
||||||
// TODO: improve AI
|
// TODO: improve AI
|
||||||
Card biggest = null;
|
Card biggest = null;
|
||||||
@@ -2013,7 +2013,7 @@ public class AiController {
|
|||||||
|
|
||||||
final CardCollection library = new CardCollection(in);
|
final CardCollection library = new CardCollection(in);
|
||||||
CardLists.shuffle(library);
|
CardLists.shuffle(library);
|
||||||
|
|
||||||
// remove all land, keep non-basicland in there, shuffled
|
// remove all land, keep non-basicland in there, shuffled
|
||||||
CardCollection land = CardLists.filter(library, CardPredicates.Presets.LANDS);
|
CardCollection land = CardLists.filter(library, CardPredicates.Presets.LANDS);
|
||||||
for (Card c : land) {
|
for (Card c : land) {
|
||||||
@@ -2021,7 +2021,7 @@ public class AiController {
|
|||||||
library.remove(c);
|
library.remove(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// mana weave, total of 7 land
|
// mana weave, total of 7 land
|
||||||
// The Following have all been reduced by 1, to account for the
|
// The Following have all been reduced by 1, to account for the
|
||||||
@@ -2038,19 +2038,14 @@ public class AiController {
|
|||||||
System.err.println("Error: cannot smooth mana curve, not enough land");
|
System.err.println("Error: cannot smooth mana curve, not enough land");
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the rest of land to the end of the deck
|
// add the rest of land to the end of the deck
|
||||||
for (int i = 0; i < land.size(); i++) {
|
for (int i = 0; i < land.size(); i++) {
|
||||||
if (!library.contains(land.get(i))) {
|
if (!library.contains(land.get(i))) {
|
||||||
library.add(land.get(i));
|
library.add(land.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check
|
|
||||||
for (int i = 0; i < library.size(); i++) {
|
|
||||||
System.out.println(library.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return library;
|
return library;
|
||||||
} // smoothComputerManaCurve()
|
} // smoothComputerManaCurve()
|
||||||
|
|
||||||
@@ -2224,7 +2219,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
return ComputerUtil.chooseSacrificeType(player, type, ability, ability.getTargetCard(), amount);
|
return ComputerUtil.chooseSacrificeType(player, type, ability, ability.getTargetCard(), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkAiSpecificRestrictions(final SpellAbility sa) {
|
private boolean checkAiSpecificRestrictions(final SpellAbility sa) {
|
||||||
// AI-specific restrictions specified as activation parameters in spell abilities
|
// AI-specific restrictions specified as activation parameters in spell abilities
|
||||||
|
|
||||||
@@ -2276,5 +2271,5 @@ public class AiController {
|
|||||||
// AI logic for choosing which replacement effect to apply happens here.
|
// AI logic for choosing which replacement effect to apply happens here.
|
||||||
return Iterables.getFirst(list, null);
|
return Iterables.getFirst(list, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1899,8 +1899,7 @@ public class ComputerUtilMana {
|
|||||||
if (!res.contains(a)) {
|
if (!res.contains(a)) {
|
||||||
if (cost.isReusuableResource()) {
|
if (cost.isReusuableResource()) {
|
||||||
res.add(0, a);
|
res.add(0, a);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
res.add(res.size(), a);
|
res.add(res.size(), a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import forge.game.IHasSVars;
|
|||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
|
||||||
import forge.game.ability.effects.CharmEffect;
|
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
@@ -346,8 +344,7 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean runNonStaticTriggersForPlayer(final Player player, final TriggerWaiting wt, final List<Trigger> delayedTriggersWorkingCopy ) {
|
private boolean runNonStaticTriggersForPlayer(final Player player, final TriggerWaiting wt, final List<Trigger> delayedTriggersWorkingCopy) {
|
||||||
|
|
||||||
final TriggerType mode = wt.getMode();
|
final TriggerType mode = wt.getMode();
|
||||||
final Map<AbilityKey, Object> runParams = wt.getParams();
|
final Map<AbilityKey, Object> runParams = wt.getParams();
|
||||||
final List<Trigger> triggers = wt.getTriggers() != null ? wt.getTriggers() : activeTriggers;
|
final List<Trigger> triggers = wt.getTriggers() != null ? wt.getTriggers() : activeTriggers;
|
||||||
@@ -503,7 +500,6 @@ public class TriggerHandler {
|
|||||||
// runs it if so.
|
// runs it if so.
|
||||||
// Return true if the trigger went off, false otherwise.
|
// Return true if the trigger went off, false otherwise.
|
||||||
private void runSingleTriggerInternal(final Trigger regtrig, final Map<AbilityKey, Object> runParams) {
|
private void runSingleTriggerInternal(final Trigger regtrig, final Map<AbilityKey, Object> runParams) {
|
||||||
|
|
||||||
// All tests passed, execute ability.
|
// All tests passed, execute ability.
|
||||||
if (regtrig instanceof TriggerTapsForMana) {
|
if (regtrig instanceof TriggerTapsForMana) {
|
||||||
final SpellAbility abMana = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
|
final SpellAbility abMana = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
|
||||||
@@ -519,8 +515,7 @@ public class TriggerHandler {
|
|||||||
if (sa == null) {
|
if (sa == null) {
|
||||||
if (!regtrig.hasParam("Execute")) {
|
if (!regtrig.hasParam("Execute")) {
|
||||||
sa = new SpellAbility.EmptySa(host);
|
sa = new SpellAbility.EmptySa(host);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
String name = regtrig.getParam("Execute");
|
String name = regtrig.getParam("Execute");
|
||||||
if (!host.getCurrentState().hasSVar(name)) {
|
if (!host.getCurrentState().hasSVar(name)) {
|
||||||
System.err.println("Warning: tried to run a trigger for card " + host + " referencing a SVar " + name + " not present on the current state " + host.getCurrentState() + ". Aborting trigger execution to prevent a crash.");
|
System.err.println("Warning: tried to run a trigger for card " + host + " referencing a SVar " + name + " not present on the current state " + host.getCurrentState() + ". Aborting trigger execution to prevent a crash.");
|
||||||
@@ -577,12 +572,6 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sa.setStackDescription(sa.toString());
|
sa.setStackDescription(sa.toString());
|
||||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
|
||||||
if (!CharmEffect.makeChoices(sa)) {
|
|
||||||
// 603.3c If no mode is chosen, the ability is removed from the stack.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Player decider = null;
|
Player decider = null;
|
||||||
boolean isMandatory = false;
|
boolean isMandatory = false;
|
||||||
@@ -592,8 +581,7 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
else if (sa instanceof AbilitySub || !sa.hasParam("Cost") || sa.getParam("Cost").equals("0")) {
|
else if (sa instanceof AbilitySub || !sa.hasParam("Cost") || sa.getParam("Cost").equals("0")) {
|
||||||
isMandatory = true;
|
isMandatory = true;
|
||||||
}
|
} else { // triggers with a cost can't be mandatory
|
||||||
else { // triggers with a cost can't be mandatory
|
|
||||||
sa.setOptionalTrigger(true);
|
sa.setOptionalTrigger(true);
|
||||||
decider = sa.getActivatingPlayer();
|
decider = sa.getActivatingPlayer();
|
||||||
}
|
}
|
||||||
@@ -605,8 +593,7 @@ public class TriggerHandler {
|
|||||||
wrapperAbility.setLastStateBattlefield(game.getLastStateBattlefield());
|
wrapperAbility.setLastStateBattlefield(game.getLastStateBattlefield());
|
||||||
if (regtrig.isStatic()) {
|
if (regtrig.isStatic()) {
|
||||||
wrapperAbility.getActivatingPlayer().getController().playTrigger(host, wrapperAbility, isMandatory);
|
wrapperAbility.getActivatingPlayer().getController().playTrigger(host, wrapperAbility, isMandatory);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
game.getStack().addSimultaneousStackEntry(wrapperAbility);
|
game.getStack().addSimultaneousStackEntry(wrapperAbility);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -549,7 +549,6 @@ public class WrappedAbility extends Ability {
|
|||||||
sa.setXManaCostPaid(n);
|
sa.setXManaCostPaid(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CardState getCardState() {
|
public CardState getCardState() {
|
||||||
return sa.getCardState();
|
return sa.getCardState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import forge.game.GameObject;
|
|||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
|
import forge.game.ability.effects.CharmEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
@@ -224,8 +225,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
undoStackOwner = activator;
|
undoStackOwner = activator;
|
||||||
}
|
}
|
||||||
undoStack.push(sp);
|
undoStack.push(sp);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
clearUndoStack();
|
clearUndoStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,8 +628,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
if (sa.isZeroTargets()) {
|
if (sa.isZeroTargets()) {
|
||||||
// Nothing targeted, and nothing needs to be targeted.
|
// Nothing targeted, and nothing needs to be targeted.
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Some targets were chosen, fizzling for this subability is now possible
|
// Some targets were chosen, fizzling for this subability is now possible
|
||||||
//fizzle = true;
|
//fizzle = true;
|
||||||
// With multi-targets, as long as one target is still legal,
|
// With multi-targets, as long as one target is still legal,
|
||||||
@@ -675,8 +674,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
}
|
}
|
||||||
else if (sa.getTargetCard() != null) {
|
else if (sa.getTargetCard() != null) {
|
||||||
fizzle = !sa.canTarget(sa.getTargetCard());
|
fizzle = !sa.canTarget(sa.getTargetCard());
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Set fizzle to the same as the parent if there's no target info
|
// Set fizzle to the same as the parent if there's no target info
|
||||||
fizzle = parentFizzled;
|
fizzle = parentFizzled;
|
||||||
}
|
}
|
||||||
@@ -799,7 +797,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
result |= chooseOrderOfSimultaneousStackEntry(whoAddsToStack);
|
result |= chooseOrderOfSimultaneousStackEntry(whoAddsToStack);
|
||||||
// 2014-08-10 Fix infinite loop when a player dies during a multiplayer game during their turn
|
// 2014-08-10 Fix infinite loop when a player dies during a multiplayer game during their turn
|
||||||
whoAddsToStack = game.getNextPlayerAfter(whoAddsToStack);
|
whoAddsToStack = game.getNextPlayerAfter(whoAddsToStack);
|
||||||
} while( whoAddsToStack != null && whoAddsToStack != playerTurn);
|
} while (whoAddsToStack != null && whoAddsToStack != playerTurn);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,9 +807,19 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<SpellAbility> activePlayerSAs = Lists.newArrayList();
|
final List<SpellAbility> activePlayerSAs = Lists.newArrayList();
|
||||||
|
final List<SpellAbility> failedSAs = Lists.newArrayList();
|
||||||
for (int i = 0; i < simultaneousStackEntryList.size(); i++) {
|
for (int i = 0; i < simultaneousStackEntryList.size(); i++) {
|
||||||
SpellAbility sa = simultaneousStackEntryList.get(i);
|
SpellAbility sa = simultaneousStackEntryList.get(i);
|
||||||
Player activator = sa.getActivatingPlayer();
|
Player activator = sa.getActivatingPlayer();
|
||||||
|
|
||||||
|
if (sa.getApi() == ApiType.Charm) {
|
||||||
|
if (!CharmEffect.makeChoices(sa)) {
|
||||||
|
// 603.3c If no mode is chosen, the ability is removed from the stack.
|
||||||
|
failedSAs.add(sa);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (activator == null) {
|
if (activator == null) {
|
||||||
if (sa.getHostCard().getController().equals(activePlayer)) {
|
if (sa.getHostCard().getController().equals(activePlayer)) {
|
||||||
activePlayerSAs.add(sa);
|
activePlayerSAs.add(sa);
|
||||||
@@ -823,6 +831,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
simultaneousStackEntryList.removeAll(activePlayerSAs);
|
simultaneousStackEntryList.removeAll(activePlayerSAs);
|
||||||
|
simultaneousStackEntryList.removeAll(failedSAs);
|
||||||
|
|
||||||
if (activePlayerSAs.isEmpty()) {
|
if (activePlayerSAs.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -875,8 +884,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
public final void addCastCommand(final String valid, final GameCommand c) {
|
public final void addCastCommand(final String valid, final GameCommand c) {
|
||||||
if (commandList.containsKey(valid)) {
|
if (commandList.containsKey(valid)) {
|
||||||
commandList.get(valid).add(0, c);
|
commandList.get(valid).add(0, c);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
commandList.put(valid, Lists.newArrayList(c));
|
commandList.put(valid, Lists.newArrayList(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user