mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
Merge branch 'oracle_en_vec' into 'master'
Add Oracle en-Vec See merge request core-developers/forge!4181
This commit is contained in:
@@ -69,6 +69,7 @@ public class AiAttackController {
|
||||
private Player defendingOpponent;
|
||||
|
||||
private int aiAggression = 0; // added by Masher, how aggressive the ai is attack will be depending on circumstances
|
||||
private final boolean nextTurn;
|
||||
|
||||
|
||||
/**
|
||||
@@ -78,18 +79,24 @@ public class AiAttackController {
|
||||
*
|
||||
*/
|
||||
public AiAttackController(final Player ai) {
|
||||
this(ai, false);
|
||||
} // constructor
|
||||
|
||||
public AiAttackController(final Player ai, boolean nextTurn) {
|
||||
this.ai = ai;
|
||||
this.defendingOpponent = choosePreferredDefenderPlayer();
|
||||
this.oppList = getOpponentCreatures(this.defendingOpponent);
|
||||
this.myList = ai.getCreaturesInPlay();
|
||||
this.attackers = new ArrayList<>();
|
||||
for (Card c : myList) {
|
||||
if (CombatUtil.canAttack(c, this.defendingOpponent)) {
|
||||
if (nextTurn && CombatUtil.canAttackNextTurn(c, this.defendingOpponent) ||
|
||||
CombatUtil.canAttack(c, this.defendingOpponent)) {
|
||||
attackers.add(c);
|
||||
}
|
||||
}
|
||||
this.blockers = getPossibleBlockers(oppList, this.attackers);
|
||||
} // constructor
|
||||
this.nextTurn = nextTurn;
|
||||
} // overloaded constructor to evaluate attackers that should attack next turn
|
||||
|
||||
public AiAttackController(final Player ai, Card attacker) {
|
||||
this.ai = ai;
|
||||
@@ -101,6 +108,7 @@ public class AiAttackController {
|
||||
attackers.add(attacker);
|
||||
}
|
||||
this.blockers = getPossibleBlockers(oppList, this.attackers);
|
||||
this.nextTurn = false;
|
||||
} // overloaded constructor to evaluate single specified attacker
|
||||
|
||||
public static List<Card> getOpponentCreatures(final Player defender) {
|
||||
@@ -132,6 +140,14 @@ public class AiAttackController {
|
||||
this.oppList.remove(blocker);
|
||||
}
|
||||
|
||||
private boolean canAttackWrapper(final Card attacker, final GameEntity defender) {
|
||||
if (nextTurn) {
|
||||
return CombatUtil.canAttackNextTurn(attacker, defender);
|
||||
} else {
|
||||
return CombatUtil.canAttack(attacker, defender);
|
||||
}
|
||||
}
|
||||
|
||||
/** Choose opponent for AI to attack here. Expand as necessary. */
|
||||
private Player choosePreferredDefenderPlayer() {
|
||||
Player defender = ai.getWeakestOpponent(); //Gets opponent with the least life
|
||||
@@ -704,6 +720,9 @@ public class AiAttackController {
|
||||
|
||||
// Attackers that don't really have a choice
|
||||
int numForcedAttackers = 0;
|
||||
// nextTurn is now only used by effect from Oracle en-Vec, which can skip check must attack,
|
||||
// because creatures not chosen can't attack.
|
||||
if (!nextTurn) {
|
||||
for (final Card attacker : this.attackers) {
|
||||
if (!CombatUtil.canAttack(attacker, defender)) {
|
||||
attackersLeft.remove(attacker);
|
||||
@@ -740,6 +759,7 @@ public class AiAttackController {
|
||||
if (attackersLeft.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Lightmine Field: make sure the AI doesn't wipe out its own creatures
|
||||
if (lightmineField) {
|
||||
@@ -760,7 +780,7 @@ public class AiAttackController {
|
||||
if (attackMax != -1 && combat.getAttackers().size() >= attackMax)
|
||||
return;
|
||||
|
||||
if (CombatUtil.canAttack(attacker, defender) && this.isEffectiveAttacker(ai, attacker, combat)) {
|
||||
if (canAttackWrapper(attacker, defender) && this.isEffectiveAttacker(ai, attacker, combat)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
}
|
||||
}
|
||||
@@ -801,7 +821,7 @@ public class AiAttackController {
|
||||
System.out.println("Exalted");
|
||||
this.aiAggression = 6;
|
||||
for (Card attacker : this.attackers) {
|
||||
if (CombatUtil.canAttack(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
if (canAttackWrapper(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
return;
|
||||
}
|
||||
@@ -817,7 +837,7 @@ public class AiAttackController {
|
||||
// reached max, breakup
|
||||
if (attackMax != -1 && combat.getAttackers().size() >= attackMax)
|
||||
break;
|
||||
if (CombatUtil.canAttack(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
if (canAttackWrapper(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
}
|
||||
}
|
||||
@@ -1058,7 +1078,7 @@ public class AiAttackController {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.shouldAttack(ai, attacker, this.blockers, combat) && CombatUtil.canAttack(attacker, defender)) {
|
||||
if (this.shouldAttack(ai, attacker, this.blockers, combat) && canAttackWrapper(attacker, defender)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
// check if attackers are enough to finish the attacked planeswalker
|
||||
if (defender instanceof Card) {
|
||||
|
||||
@@ -79,6 +79,7 @@ public class AiController {
|
||||
private final Game game;
|
||||
private final AiCardMemory memory;
|
||||
private Combat predictedCombat;
|
||||
private Combat predictedCombatNextTurn;
|
||||
private boolean cheatShuffle;
|
||||
private boolean useSimulation;
|
||||
private SpellAbilityPicker simPicker;
|
||||
@@ -123,6 +124,15 @@ public class AiController {
|
||||
return predictedCombat;
|
||||
}
|
||||
|
||||
public Combat getPredictedCombatNextTurn() {
|
||||
if (predictedCombatNextTurn == null) {
|
||||
AiAttackController aiAtk = new AiAttackController(player, true);
|
||||
predictedCombatNextTurn = new Combat(player);
|
||||
aiAtk.declareAttackers(predictedCombatNextTurn);
|
||||
}
|
||||
return predictedCombatNextTurn;
|
||||
}
|
||||
|
||||
public AiController(final Player computerPlayer, final Game game0) {
|
||||
player = computerPlayer;
|
||||
game = game0;
|
||||
@@ -1364,6 +1374,8 @@ public class AiController {
|
||||
// Reset cached predicted combat, as it may be stale. It will be
|
||||
// re-created if needed and used for any AI logic that needs it.
|
||||
predictedCombat = null;
|
||||
// Also reset predicted combat for next turn here
|
||||
predictedCombatNextTurn = null;
|
||||
|
||||
// Reset priority mana reservation that's meant to work for one spell only
|
||||
AiCardMemory.clearMemorySet(player, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_NEXT_SPELL);
|
||||
|
||||
@@ -309,6 +309,17 @@ public class ComputerUtilCard {
|
||||
return biggest;
|
||||
}
|
||||
|
||||
// For ability of Oracle en-Vec, return the first card that are going to attack next turn
|
||||
public static Card getBestCreatureToAttackNextTurnAI(final Player aiPlayer, final Iterable<Card> list) {
|
||||
AiController aic = ((PlayerControllerAi)aiPlayer.getController()).getAi();
|
||||
for(final Card card : list) {
|
||||
if (aic.getPredictedCombatNextTurn().isAttacking(card)) {
|
||||
return card;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getWorstAI.
|
||||
|
||||
@@ -289,6 +289,8 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
// Choose the best (hopefully the fattest, whatever) creature so that hopefully it won't die too easily
|
||||
choice = ComputerUtilCard.getBestAI(creatures);
|
||||
}
|
||||
} else if (logic.equals("NextTurnAttacker")) {
|
||||
choice = ComputerUtilCard.getBestCreatureToAttackNextTurnAI(ai, options);
|
||||
} else {
|
||||
choice = ComputerUtilCard.getBestAI(options);
|
||||
}
|
||||
|
||||
@@ -122,6 +122,9 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
||||
chosen.addAll(p.getController().chooseCardsForEffect(choices, sa, title, minAmount, validAmount, !sa.hasParam("Mandatory"), null));
|
||||
}
|
||||
}
|
||||
if (sa.hasParam("Reveal")) {
|
||||
game.getAction().reveal(chosen, p, true, Localizer.getInstance().getMessage("lblChosenCards") + " ");
|
||||
}
|
||||
}
|
||||
host.setChosenCards(chosen);
|
||||
if (sa.hasParam("RememberChosen")) {
|
||||
|
||||
13
forge-gui/res/cardsfolder/o/oracle_en_vec.txt
Normal file
13
forge-gui/res/cardsfolder/o/oracle_en_vec.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Oracle en-Vec
|
||||
ManaCost:1 W
|
||||
Types:Creature Human Wizard
|
||||
PT:1/1
|
||||
A:AB$ ChooseCard | Cost$ T | ValidTgts$ Player.Opponent | MinAmount$ 0 | Amount$ X | Choices$ Creature | TargetControls$ True | ChoiceTitle$ Choose any number of creatures you control | PlayerTurn$ True | Reveal$ True | AILogic$ NextTurnAttacker | SubAbility$ DBOracleEffect | StackDescription$ SpellDescription | SpellDescription$ Target opponent chooses any number of creatures they control. During that player's next turn, the chosen creatures attack if able, and other creatures can't attack. At the beginning of that turn's end step, destroy each of the chosen creatures that didn't attack this turn. Activate this ability only during your turn.
|
||||
SVar:X:Count$Valid Creature.TargetedPlayerCtrl
|
||||
SVar:DBOracleEffect:DB$ Effect | EffectOwner$ TargetedPlayer | StaticAbilities$ ForceAttack,ForbidAttack | Triggers$ TrigDestroy | Duration$ UntilTheEndOfYourNextTurn | SubAbility$ DBCleanup
|
||||
SVar:ForceAttack:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl+ChosenCard | AddHiddenKeyword$ CARDNAME attacks each combat if able. | Description$ During that player's next turn, the chosen creatures attack if able, and other creatures can't attack.
|
||||
SVar:ForbidAttack:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl+nonChosenCard | AddHiddenKeyword$ CARDNAME can't attack.
|
||||
SVar:TrigDestroy:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | Execute$ DBDestroy | TriggerDescription$ At the beginning of that turn's end step, destroy each of the chosen creatures that didn't attack this turn.
|
||||
SVar:DBDestroy:DB$ DestroyAll | ValidCards$ Creature.ChosenCard+notAttackedThisTurn
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True
|
||||
Oracle:{T}: Target opponent chooses any number of creatures they control. During that player's next turn, the chosen creatures attack if able, and other creatures can't attack. At the beginning of that turn's end step, destroy each of the chosen creatures that didn't attack this turn. Activate this ability only during your turn.
|
||||
Reference in New Issue
Block a user