mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Merge branch 'ai-updates' into 'master'
Some updates to Flash and PermanentCreatureAi logic. See merge request core-developers/forge!1159
This commit is contained in:
@@ -958,6 +958,22 @@ public class ComputerUtil {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we have non-persistent mana in our pool, would be good to try to use it and not waste it
|
||||||
|
if (ai.getManaPool().willManaBeLostAtEndOfPhase()) {
|
||||||
|
boolean canUseToPayCost = false;
|
||||||
|
for (byte color : MagicColor.WUBRGC) {
|
||||||
|
if (ai.getManaPool().getAmountOfColor(color) > 0
|
||||||
|
&& ((card.getManaCost().getColorProfile() & color) == color)) {
|
||||||
|
canUseToPayCost = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canUseToPayCost) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (card.isCreature() && !card.hasKeyword(Keyword.DEFENDER)
|
if (card.isCreature() && !card.hasKeyword(Keyword.DEFENDER)
|
||||||
&& (card.hasKeyword(Keyword.HASTE) || ComputerUtil.hasACardGivingHaste(ai, true) || sa.isDash())) {
|
&& (card.hasKeyword(Keyword.HASTE) || ComputerUtil.hasACardGivingHaste(ai, true) || sa.isDash())) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -161,6 +161,15 @@ public class PermanentCreatureAi extends PermanentAi {
|
|||||||
int chanceToCastForETB = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_CAST_DUE_TO_ETB_EFFECTS);
|
int chanceToCastForETB = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_CAST_DUE_TO_ETB_EFFECTS);
|
||||||
int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB);
|
int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB);
|
||||||
int chanceToProcETBBeforeMain1 = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_CAST_FOR_ETB_BEFORE_MAIN1);
|
int chanceToProcETBBeforeMain1 = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_CAST_FOR_ETB_BEFORE_MAIN1);
|
||||||
|
boolean canCastAtOppTurn = true;
|
||||||
|
for (Card c : ai.getGame().getCardsIn(ZoneType.Battlefield)) {
|
||||||
|
for (StaticAbility s : c.getStaticAbilities()) {
|
||||||
|
if ("CantBeCast".equals(s.getParam("Mode")) && "True".equals(s.getParam("NonCasterTurn"))) {
|
||||||
|
canCastAtOppTurn = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (hasFloatMana || willDiscardNow || willDieNow) {
|
if (hasFloatMana || willDiscardNow || willDieNow) {
|
||||||
// Will lose mana in pool or about to discard a card in cleanup or about to die in combat, so use this opportunity
|
// Will lose mana in pool or about to discard a card in cleanup or about to die in combat, so use this opportunity
|
||||||
@@ -170,7 +179,7 @@ public class PermanentCreatureAi extends PermanentAi {
|
|||||||
return isMyMain1OrLater;
|
return isMyMain1OrLater;
|
||||||
} else if (hasAmbushAI && MyRandom.percentTrue(chanceToObeyAmbushAI)) {
|
} else if (hasAmbushAI && MyRandom.percentTrue(chanceToObeyAmbushAI)) {
|
||||||
// Is an ambusher, so try to hold for declare blockers in combat where the AI defends, if possible
|
// Is an ambusher, so try to hold for declare blockers in combat where the AI defends, if possible
|
||||||
return defOnlyAmbushAI ? isOppDeclareAttackers : (isOppDeclareAttackers || isMyDeclareBlockers);
|
return defOnlyAmbushAI && canCastAtOppTurn ? isOppDeclareAttackers : (isOppDeclareAttackers || isMyDeclareBlockers);
|
||||||
} else if (valuableBlocker && isOppDeclareAttackers && MyRandom.percentTrue(chanceToAddBlocker)) {
|
} else if (valuableBlocker && isOppDeclareAttackers && MyRandom.percentTrue(chanceToAddBlocker)) {
|
||||||
// Might serve as a valuable blocker in a combat where we are behind on untapped blockers
|
// Might serve as a valuable blocker in a combat where we are behind on untapped blockers
|
||||||
return true;
|
return true;
|
||||||
@@ -182,21 +191,11 @@ public class PermanentCreatureAi extends PermanentAi {
|
|||||||
} else if (hasETBTrigger && canRespondToStack && MyRandom.percentTrue(chanceToRespondToStack)) {
|
} else if (hasETBTrigger && canRespondToStack && MyRandom.percentTrue(chanceToRespondToStack)) {
|
||||||
// Try to do something meaningful in response to an opposing effect on stack. Note that this is currently
|
// Try to do something meaningful in response to an opposing effect on stack. Note that this is currently
|
||||||
// too random to likely be meaningful, serious improvement might be needed.
|
// too random to likely be meaningful, serious improvement might be needed.
|
||||||
return true;
|
return canCastAtOppTurn || ph.getPlayerTurn().equals(ai);
|
||||||
} else {
|
} else {
|
||||||
boolean canCastAtOppEOT = true;
|
|
||||||
for (Card c : ai.getGame().getCardsIn(ZoneType.Battlefield)) {
|
|
||||||
for (StaticAbility s : c.getStaticAbilities()) {
|
|
||||||
if ("CantBeCast".equals(s.getParam("Mode")) && "True".equals(s.getParam("NonCasterTurn"))) {
|
|
||||||
canCastAtOppEOT = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doesn't have a ETB trigger and doesn't seem to be good as an ambusher, try to surprise the opp before my turn
|
// Doesn't have a ETB trigger and doesn't seem to be good as an ambusher, try to surprise the opp before my turn
|
||||||
// TODO: maybe implement a way to reserve mana for this
|
// TODO: maybe implement a way to reserve mana for this
|
||||||
return canCastAtOppEOT ? isEOTBeforeMyTurn : isOwnEOT;
|
return canCastAtOppTurn ? isEOTBeforeMyTurn : isOwnEOT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user