mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Merge branch 'damagedeal' into 'master'
DamageDealAi: Improve mandatory targeting with stuff like Fury, so AI less masochistic See merge request core-developers/forge!5522
This commit is contained in:
@@ -344,7 +344,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
final Player activator = sa.getActivatingPlayer();
|
final Player activator = sa.getActivatingPlayer();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final Game game = source.getGame();
|
final Game game = source.getGame();
|
||||||
List<Card> hPlay = getTargetableCards(mandatory ? pl : ai, sa, pl, tgt, activator, source, game);
|
List<Card> hPlay = getTargetableCards(ai, sa, pl, tgt, activator, source, game);
|
||||||
|
|
||||||
// Filter MustTarget requirements
|
// Filter MustTarget requirements
|
||||||
StaticAbilityMustTarget.filterMustTargetCards(ai, hPlay, sa);
|
StaticAbilityMustTarget.filterMustTargetCards(ai, hPlay, sa);
|
||||||
@@ -381,15 +381,20 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try unfiltered now
|
||||||
|
hPlay = getTargetableCards(pl, sa, pl, tgt, activator, source, game);
|
||||||
|
List<Card> controlledByOpps = CardLists.filterControlledBy(hPlay, ai.getOpponents());
|
||||||
|
|
||||||
if (!hPlay.isEmpty()) {
|
if (!hPlay.isEmpty()) {
|
||||||
if (pl.isOpponentOf(ai) && activator.equals(ai)) {
|
if (pl.isOpponentOf(ai) && activator.equals(ai)) {
|
||||||
if (sa.getTargetRestrictions().canTgtPlaneswalker()) {
|
if (sa.getTargetRestrictions().canTgtPlaneswalker()) {
|
||||||
targetCard = ComputerUtilCard.getBestPlaneswalkerAI(hPlay);
|
targetCard = ComputerUtilCard.getBestPlaneswalkerAI(controlledByOpps);
|
||||||
}
|
}
|
||||||
if (targetCard == null) {
|
if (targetCard == null) {
|
||||||
targetCard = ComputerUtilCard.getBestCreatureAI(hPlay);
|
targetCard = ComputerUtilCard.getBestCreatureAI(controlledByOpps);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
if (targetCard == null) {
|
||||||
targetCard = ComputerUtilCard.getWorstCreatureAI(hPlay);
|
targetCard = ComputerUtilCard.getWorstCreatureAI(hPlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +719,6 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (tgt.canTgtCreature() || tgt.canTgtPlaneswalker()) {
|
} else if (tgt.canTgtCreature() || tgt.canTgtPlaneswalker()) {
|
||||||
final Card c = dealDamageChooseTgtC(ai, sa, dmg, noPrevention, enemy, mandatory);
|
final Card c = dealDamageChooseTgtC(ai, sa, dmg, noPrevention, enemy, mandatory);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
@@ -726,7 +730,13 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
}
|
}
|
||||||
tcs.add(c);
|
tcs.add(c);
|
||||||
if (divided) {
|
if (divided) {
|
||||||
final int assignedDamage = ComputerUtilCombat.getEnoughDamageToKill(c, dmg, source, false, noPrevention);
|
// if only other legal targets hurt own stuff just dump all dmg into this
|
||||||
|
final Card nextTarget = dealDamageChooseTgtC(ai, sa, dmg, noPrevention, enemy, mandatory);
|
||||||
|
boolean dump = false;
|
||||||
|
if (nextTarget != null && nextTarget.getController().equals(ai)) {
|
||||||
|
dump = true;
|
||||||
|
}
|
||||||
|
final int assignedDamage = dump ? dmg : ComputerUtilCombat.getEnoughDamageToKill(c, dmg, source, false, noPrevention);
|
||||||
if (assignedDamage <= dmg) {
|
if (assignedDamage <= dmg) {
|
||||||
sa.addDividedAllocation(c, assignedDamage);
|
sa.addDividedAllocation(c, assignedDamage);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2541,7 +2541,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
|| keyword.equals("Split second")) {
|
|| keyword.equals("Split second")) {
|
||||||
sbBefore.append(keyword).append(" (").append(inst.getReminderText()).append(")");
|
sbBefore.append(keyword).append(" (").append(inst.getReminderText()).append(")");
|
||||||
sbBefore.append("\r\n");
|
sbBefore.append("\r\n");
|
||||||
} else if(keyword.equals("Conspire") || keyword.equals("Epic")
|
} else if (keyword.equals("Conspire") || keyword.equals("Epic")
|
||||||
|| keyword.equals("Suspend") || keyword.equals("Jump-start")
|
|| keyword.equals("Suspend") || keyword.equals("Jump-start")
|
||||||
|| keyword.equals("Fuse")) {
|
|| keyword.equals("Fuse")) {
|
||||||
sbAfter.append(keyword).append(" (").append(inst.getReminderText()).append(")");
|
sbAfter.append(keyword).append(" (").append(inst.getReminderText()).append(")");
|
||||||
@@ -5918,9 +5918,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
|
|
||||||
if (sa.isSpell()) {
|
if (sa.isSpell()) {
|
||||||
// TODO replace with Static Ability
|
// TODO replace with Static Ability
|
||||||
for(KeywordInterface inst : source.getKeywords()) {
|
for (KeywordInterface inst : source.getKeywords()) {
|
||||||
String kw = inst.getOriginal();
|
String kw = inst.getOriginal();
|
||||||
if(!kw.startsWith("SpellCantTarget")) {
|
if (!kw.startsWith("SpellCantTarget")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final String[] k = kw.split(":");
|
final String[] k = kw.split(":");
|
||||||
|
|||||||
@@ -259,8 +259,7 @@ public class CardView extends GameEntityView {
|
|||||||
//store alternate type for oathbreaker or signature spell for display in card text
|
//store alternate type for oathbreaker or signature spell for display in card text
|
||||||
if (c.getPaperCard().getRules().canBeSignatureSpell()) {
|
if (c.getPaperCard().getRules().canBeSignatureSpell()) {
|
||||||
set(TrackableProperty.CommanderAltType, "Signature Spell");
|
set(TrackableProperty.CommanderAltType, "Signature Spell");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
set(TrackableProperty.CommanderAltType, "Oathbreaker");
|
set(TrackableProperty.CommanderAltType, "Oathbreaker");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -768,7 +767,7 @@ public class CardView extends GameEntityView {
|
|||||||
Set<String> cantHaveKeyword = this.getCantHaveKeyword();
|
Set<String> cantHaveKeyword = this.getCantHaveKeyword();
|
||||||
if (cantHaveKeyword != null && !cantHaveKeyword.isEmpty()) {
|
if (cantHaveKeyword != null && !cantHaveKeyword.isEmpty()) {
|
||||||
sb.append("\r\n\r\n");
|
sb.append("\r\n\r\n");
|
||||||
for(String k : cantHaveKeyword) {
|
for (String k : cantHaveKeyword) {
|
||||||
sb.append("CARDNAME can't have or gain ".replaceAll("CARDNAME", getName()));
|
sb.append("CARDNAME can't have or gain ".replaceAll("CARDNAME", getName()));
|
||||||
sb.append(k);
|
sb.append(k);
|
||||||
sb.append(".");
|
sb.append(".");
|
||||||
@@ -945,8 +944,7 @@ public class CardView extends GameEntityView {
|
|||||||
|
|
||||||
if (alternateState == null) {
|
if (alternateState == null) {
|
||||||
set(TrackableProperty.AlternateState, null);
|
set(TrackableProperty.AlternateState, null);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
CardStateView alternateStateView = alternateState.getView();
|
CardStateView alternateStateView = alternateState.getView();
|
||||||
if (getAlternateState() != alternateStateView) {
|
if (getAlternateState() != alternateStateView) {
|
||||||
set(TrackableProperty.AlternateState, alternateStateView);
|
set(TrackableProperty.AlternateState, alternateStateView);
|
||||||
|
|||||||
@@ -2890,7 +2890,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
// Vanguard
|
// Vanguard
|
||||||
if (registeredPlayer.getVanguardAvatars() != null) {
|
if (registeredPlayer.getVanguardAvatars() != null) {
|
||||||
for(PaperCard avatar:registeredPlayer.getVanguardAvatars()) {
|
for (PaperCard avatar:registeredPlayer.getVanguardAvatars()) {
|
||||||
com.add(Card.fromPaperCard(avatar, this));
|
com.add(Card.fromPaperCard(avatar, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user