mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
AI: improved game stability on blocking (related to #13290)
This commit is contained in:
parent
8aa432067a
commit
7035736a6c
3 changed files with 18 additions and 20 deletions
|
|
@ -15,11 +15,7 @@ public class CombatInfo {
|
||||||
private Map<Permanent, List<Permanent>> combat = new HashMap<>();
|
private Map<Permanent, List<Permanent>> combat = new HashMap<>();
|
||||||
|
|
||||||
public void addPair(Permanent attacker, Permanent blocker) {
|
public void addPair(Permanent attacker, Permanent blocker) {
|
||||||
List<Permanent> blockers = combat.get(attacker);
|
List<Permanent> blockers = combat.computeIfAbsent(attacker, k -> new ArrayList<>());
|
||||||
if (blockers == null) {
|
|
||||||
blockers = new ArrayList<>();
|
|
||||||
combat.put(attacker, blockers);
|
|
||||||
}
|
|
||||||
blockers.add(blocker);
|
blockers.add(blocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,15 +179,15 @@ public final class CombatUtil {
|
||||||
nonBlockingDiffScore.put(s.getBlocker(), s.getDiffNonblockingScore());
|
nonBlockingDiffScore.put(s.getBlocker(), s.getDiffNonblockingScore());
|
||||||
});
|
});
|
||||||
|
|
||||||
// split blockers usage priority
|
// split blockers by usage priority
|
||||||
List<Permanent> survivedAndKillBlocker = new ArrayList<>();
|
List<Permanent> survivedAndKillBlocker = new ArrayList<>();
|
||||||
List<Permanent> survivedBlockers2 = new ArrayList<>();
|
List<Permanent> survivedBlockers = new ArrayList<>();
|
||||||
List<Permanent> diedBlockers = new ArrayList<>();
|
List<Permanent> diedBlockers = new ArrayList<>();
|
||||||
blockerStats.forEach(stats -> {
|
blockerStats.forEach(stats -> {
|
||||||
if (stats.isAttackerDied() && !stats.isBlockerDied()) {
|
if (stats.isAttackerDied() && !stats.isBlockerDied()) {
|
||||||
survivedAndKillBlocker.add(stats.getBlocker());
|
survivedAndKillBlocker.add(stats.getBlocker());
|
||||||
} else if (!stats.isBlockerDied()) {
|
} else if (!stats.isBlockerDied()) {
|
||||||
survivedBlockers2.add(stats.getBlocker());
|
survivedBlockers.add(stats.getBlocker());
|
||||||
} else {
|
} else {
|
||||||
diedBlockers.add(stats.getBlocker());
|
diedBlockers.add(stats.getBlocker());
|
||||||
}
|
}
|
||||||
|
|
@ -196,10 +196,10 @@ public final class CombatUtil {
|
||||||
int blockedCount = 0;
|
int blockedCount = 0;
|
||||||
|
|
||||||
// find good blocker
|
// find good blocker
|
||||||
Permanent blocker = getWorstCreature(survivedAndKillBlocker, survivedBlockers2);
|
Permanent blocker = getWorstCreature(survivedAndKillBlocker, survivedBlockers);
|
||||||
if (blocker != null) {
|
if (blocker != null) {
|
||||||
combatInfo.addPair(attacker, blocker);
|
combatInfo.addPair(attacker, blocker);
|
||||||
removeWorstCreature(blocker, blockers, survivedAndKillBlocker, survivedBlockers2);
|
removeWorstCreature(blocker, blockers, survivedAndKillBlocker, survivedBlockers);
|
||||||
blockedCount++;
|
blockedCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,13 +208,15 @@ public final class CombatUtil {
|
||||||
// TODO: there are many triggers on damage, attack, etc - it can't be processed without real game simulations
|
// TODO: there are many triggers on damage, attack, etc - it can't be processed without real game simulations
|
||||||
if (blocker == null) {
|
if (blocker == null) {
|
||||||
blocker = getWorstCreature(diedBlockers);
|
blocker = getWorstCreature(diedBlockers);
|
||||||
int diffBlockingScore = blockingDiffScore.getOrDefault(blocker, 0);
|
if (blocker != null) {
|
||||||
int diffNonBlockingScore = nonBlockingDiffScore.getOrDefault(blocker, 0);
|
int diffBlockingScore = blockingDiffScore.getOrDefault(blocker, 0);
|
||||||
if (diffBlockingScore >= 0 || diffBlockingScore > diffNonBlockingScore) {
|
int diffNonBlockingScore = nonBlockingDiffScore.getOrDefault(blocker, 0);
|
||||||
// it's good use case - can block and kill
|
if (diffBlockingScore >= 0 || diffBlockingScore > diffNonBlockingScore) {
|
||||||
combatInfo.addPair(attacker, blocker);
|
// it's good - can sacrifice and get better game state, also protect from game loose
|
||||||
removeWorstCreature(blocker, blockers, diedBlockers);
|
combatInfo.addPair(attacker, blocker);
|
||||||
blockedCount++;
|
removeWorstCreature(blocker, blockers, diedBlockers);
|
||||||
|
blockedCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,10 +232,10 @@ public final class CombatUtil {
|
||||||
// effects support: can't be blocked except by xxx or more creatures
|
// effects support: can't be blocked except by xxx or more creatures
|
||||||
if (blockedCount > 0 && attacker.getMinBlockedBy() > blockedCount) {
|
if (blockedCount > 0 && attacker.getMinBlockedBy() > blockedCount) {
|
||||||
// it already has 1 blocker (killer in best use case), so no needs in second killer
|
// it already has 1 blocker (killer in best use case), so no needs in second killer
|
||||||
blocker = getWorstCreature(survivedBlockers2, survivedAndKillBlocker, diedBlockers);
|
blocker = getWorstCreature(survivedBlockers, survivedAndKillBlocker, diedBlockers);
|
||||||
if (blocker != null) {
|
if (blocker != null) {
|
||||||
combatInfo.addPair(attacker, blocker);
|
combatInfo.addPair(attacker, blocker);
|
||||||
removeWorstCreature(blocker, blockers, survivedBlockers2, survivedAndKillBlocker, diedBlockers);
|
removeWorstCreature(blocker, blockers, survivedBlockers, survivedAndKillBlocker, diedBlockers);
|
||||||
blockedCount++;
|
blockedCount++;
|
||||||
continue; // try to find next required blocker
|
continue; // try to find next required blocker
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -822,7 +822,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
// too few blockers
|
// too few blockers
|
||||||
if (attacker.getMinBlockedBy() > 1 && !blockers.isEmpty() && blockers.size() < attacker.getMinBlockedBy()) {
|
if (attacker.getMinBlockedBy() > 1 && !blockers.isEmpty() && blockers.size() < attacker.getMinBlockedBy()) {
|
||||||
for (UUID blockerId : new ArrayList<>(blockers)) {
|
for (UUID blockerId : new ArrayList<>(blockers)) {
|
||||||
game.getCombat().removeBlocker(blockerId, game); // !
|
game.getCombat().removeBlocker(blockerId, game);
|
||||||
}
|
}
|
||||||
blockers.clear();
|
blockers.clear();
|
||||||
blockerOrder.clear();
|
blockerOrder.clear();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue