* AI: improved support of "as though mana" abilities (now computer can choose correct mana ability to pay, example: Draugr Necromancer);

* Dev: added card's LKI support of multi part cards (mdf/split/adventure);
* Dev: improved support of adding/removing counters from mdf cards;
* Draugr Necromancer - fixed support of mdf/split/adventure cards (#7620);
This commit is contained in:
Oleg Agafonov 2021-02-27 20:14:12 +04:00
parent adc945748b
commit dda69cd009
12 changed files with 227 additions and 65 deletions

View file

@ -44,6 +44,7 @@ import mage.game.tournament.Tournament;
import mage.player.ai.simulators.CombatGroupSimulator;
import mage.player.ai.simulators.CombatSimulator;
import mage.player.ai.simulators.CreatureSimulator;
import mage.players.ManaPoolItem;
import mage.players.Player;
import mage.players.PlayerImpl;
import mage.players.net.UserData;
@ -1423,6 +1424,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1441,6 +1445,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1456,6 +1463,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1471,6 +1481,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1486,6 +1499,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1501,6 +1517,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1516,6 +1535,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) {
continue;
}
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1555,6 +1577,56 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return false;
}
boolean canUseAsThoughManaToPayManaCost(ManaCost checkCost, Ability abilityToPay, Mana manaOption, Ability manaAbility, MageObject manaProducer, Game game) {
// asThoughMana can change producing mana type, so you must check it here
// cause some effects adds additional checks in getAsThoughManaType (example: Draugr Necromancer with snow mana sources)
// simulate real asThoughMana usage
ManaPoolItem possiblePoolItem;
if (manaOption instanceof ConditionalMana) {
ConditionalMana conditionalNetMana = (ConditionalMana) manaOption;
possiblePoolItem = new ManaPoolItem(
conditionalNetMana,
manaAbility.getSourceObject(game),
conditionalNetMana.getManaProducerOriginalId() != null ? conditionalNetMana.getManaProducerOriginalId() : manaAbility.getOriginalId()
);
} else {
possiblePoolItem = new ManaPoolItem(
manaOption.getRed(),
manaOption.getGreen(),
manaOption.getBlue(),
manaOption.getWhite(),
manaOption.getBlack(),
manaOption.getGeneric() + manaOption.getColorless(),
manaProducer,
manaAbility.getOriginalId(),
manaOption.getFlag()
);
}
// cost can contains multiple mana types, must check each type (is it possible to pay a cost)
for (ManaType checkType : ManaUtil.getManaTypesInCost(checkCost)) {
// affected asThoughMana effect must fit a checkType with pool mana
ManaType possibleAsThoughPoolManaType = game.getContinuousEffects().asThoughMana(checkType, possiblePoolItem, abilityToPay.getSourceId(), abilityToPay, abilityToPay.getControllerId(), game);
if (possibleAsThoughPoolManaType == null) {
continue; // no affected asThough effects
}
boolean canPay;
if (possibleAsThoughPoolManaType == ManaType.COLORLESS) {
// colorless can be payed by any color from the pool
canPay = possiblePoolItem.count() > 0;
} else {
// colored must be payed by specific color from the pool (AsThough already changed it to fit with mana pool)
canPay = possiblePoolItem.get(possibleAsThoughPoolManaType) > 0;
}
if (canPay) {
return true;
}
}
return false;
}
private Abilities<ActivatedManaAbilityImpl> getManaAbilitiesSortedByManaCount(MageObject mageObject, final Game game) {
Abilities<ActivatedManaAbilityImpl> manaAbilities = mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, playerId, game);
if (manaAbilities.size() > 1) {