* Reworked calculation of available mana that can be a source of heavy server load.

This commit is contained in:
LevelX2 2015-02-07 18:16:35 +01:00
parent 8a6a615250
commit e0b17eacc7
3 changed files with 129 additions and 14 deletions

View file

@ -170,6 +170,10 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
public int count() { public int count() {
return red + green + blue + white + black + colorless + any; return red + green + blue + white + black + colorless + any;
} }
public int countColored() {
return red + green + blue + white + black + any;
}
public int count(FilterMana filter) { public int count(FilterMana filter) {
if (filter == null) { if (filter == null) {
@ -506,4 +510,74 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
return flag; return flag;
} }
public void setToMana(Mana mana) {
this.any = mana.any;
this.red = mana.red;
this.green = mana.green;
this.white = mana.white;
this.blue = mana.blue;
this.black = mana.black;
this.colorless = mana.colorless;
}
public boolean equalManaValue(Mana mana) {
return this.any == mana.any &&
this.red == mana.red &&
this.green == mana.green &&
this.white == mana.white &&
this.blue == mana.blue &&
this.black == mana.black &&
this.colorless == mana.colorless;
}
/**
* Don't takes any mana into account to be usable in calculating available mana
* @param mana
* @return
*/
public boolean includesMana(Mana mana) {
return this.green >= mana.green &&
this.blue >= mana.blue &&
this.white >= mana.white &&
this.black >= mana.black &&
this.red >= mana.red &&
(
this.colorless >= mana.colorless ||
this.countColored() >= mana.countColored() + mana.colorless
);
}
/**
* Returns the mana that is more colored but does not contain
* one less mana in any color but colorless
* if you call with {1}{W}{R} and {G}{W}{R} you get back {G}{W}{R}
* if you call with {G}{W}{R} and {G}{W}{R} you get back {G}{W}{R}
* if you call with {G}{W}{B} and {G}{W}{R} you get back null
*
* @param mana1
* @param mana2
* @return
*/
public static Mana getMoreValuableMana(Mana mana1, Mana mana2) {
Mana moreMana;
Mana lessMana;
if (mana2.count() > mana1.count() || mana2.getAny() > mana1.getAny() || mana2.getColorless() < mana1.getColorless()) {
moreMana = mana2;
lessMana = mana1;
} else {
moreMana = mana1;
lessMana = mana2;
}
if (lessMana.getWhite() > moreMana.getWhite() ||
lessMana.getRed() > moreMana.getRed() ||
lessMana.getGreen() > moreMana.getGreen() ||
lessMana.getBlue() > moreMana.getBlue() ||
lessMana.getBlack() > moreMana.getBlack() ||
lessMana.getAny() > moreMana.getAny()
) {
return null;
}
return moreMana;
}
} }

View file

@ -82,10 +82,22 @@ public class ManaOptions extends ArrayList<Mana> {
this.clear(); this.clear();
for (ManaAbility ability: abilities) { for (ManaAbility ability: abilities) {
for (Mana netMana: ability.getNetMana(game)) { for (Mana netMana: ability.getNetMana(game)) {
SkipAddMana:
for (Mana mana: copy) { for (Mana mana: copy) {
Mana newMana = new Mana(); Mana newMana = new Mana();
newMana.add(mana); newMana.add(mana);
newMana.add(netMana); newMana.add(netMana);
for(Mana existingMana: this) {
if (existingMana.equalManaValue(newMana)) {
continue SkipAddMana;
}
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
if (moreValuable != null) {
// only keep the more valuable mana
existingMana.setToMana(newMana);
continue SkipAddMana;
}
}
this.add(newMana); this.add(newMana);
} }
} }
@ -103,6 +115,7 @@ public class ManaOptions extends ArrayList<Mana> {
//if there is only one mana option available add it to all the existing options //if there is only one mana option available add it to all the existing options
ManaAbility ability = abilities.get(0); ManaAbility ability = abilities.get(0);
List<Mana> netManas = abilities.get(0).getNetMana(game); List<Mana> netManas = abilities.get(0).getNetMana(game);
// no mana costs
if (ability.getManaCosts().isEmpty()) { if (ability.getManaCosts().isEmpty()) {
if (netManas.size() == 1) { if (netManas.size() == 1) {
addMana(netManas.get(0)); addMana(netManas.get(0));
@ -121,7 +134,7 @@ public class ManaOptions extends ArrayList<Mana> {
} }
else { else {
if (netManas.size() == 1) { if (netManas.size() == 1) {
addMana(ability.getManaCosts().getMana(), netManas.get(0)); subtractCostAddMana(ability.getManaCosts().getMana(), netManas.get(0), ability.getCosts().isEmpty());
} else { } else {
List<Mana> copy = copy(); List<Mana> copy = copy();
this.clear(); this.clear();
@ -130,7 +143,7 @@ public class ManaOptions extends ArrayList<Mana> {
Mana newMana = new Mana(); Mana newMana = new Mana();
newMana.add(mana); newMana.add(mana);
newMana.add(netMana); newMana.add(netMana);
addMana(ability.getManaCosts().getMana(), netMana); subtractCostAddMana(ability.getManaCosts().getMana(), netMana, ability.getCosts().isEmpty());
} }
} }
} }
@ -208,14 +221,21 @@ public class ManaOptions extends ArrayList<Mana> {
return new ManaOptions(this); return new ManaOptions(this);
} }
public void addMana(Mana cost, Mana addMana) { public void subtractCostAddMana(Mana cost, Mana addMana, boolean onlyManaCosts) {
if (isEmpty()) { if (isEmpty()) {
this.add(new Mana()); this.add(new Mana());
} }
boolean addAny = false;
if (addMana.getAny() == 1 && addMana.count() == 1) {
addAny = true; // only replace to any will be repeated
}
for (Mana mana: this) { for (Mana mana: this) {
if (mana.contains(cost)) { while (mana.includesMana(cost)) {
mana.subtract(cost); mana.subtract(cost);
mana.add(addMana); mana.add(addMana);
if (!addAny) {
break;
}
} }
} }
} }

View file

@ -2099,14 +2099,35 @@ public abstract class PlayerImpl implements Player, Serializable {
protected ManaOptions getManaAvailable(Game game) { protected ManaOptions getManaAvailable(Game game) {
ManaOptions available = new ManaOptions(); ManaOptions available = new ManaOptions();
List<Permanent> manaPerms = this.getAvailableManaProducers(game); List<Abilities<ManaAbility>> sourceWithoutCosts = new ArrayList<>();
for (Permanent perm: manaPerms) { List<Abilities<ManaAbility>> sourceWithCosts = new ArrayList<>();
available.addMana(perm.getAbilities().getAvailableManaAbilities(Zone.BATTLEFIELD, game), game); for (Permanent permanent: game.getBattlefield().getAllActivePermanents(playerId)) {
boolean canAdd = false;
boolean withCost = false;
Abilities<ManaAbility> manaAbilities = permanent.getAbilities().getAvailableManaAbilities(Zone.BATTLEFIELD, game);
for (ManaAbility ability: manaAbilities) {
if (ability.canActivate(playerId, game)) {
canAdd = true;
if (!ability.getManaCosts().isEmpty()) {
withCost = true;
break;
}
}
}
if (canAdd) {
if (withCost) {
sourceWithCosts.add(manaAbilities);
} else {
sourceWithoutCosts.add(manaAbilities);
}
}
} }
List<Permanent> manaPermsWithCost = this.getAvailableManaProducersWithCost(game); for (Abilities<ManaAbility> manaAbilities: sourceWithoutCosts) {
for (Permanent perm: manaPermsWithCost) { available.addMana(manaAbilities, game);
available.addManaWithCost(perm.getAbilities().getAvailableManaAbilities(Zone.BATTLEFIELD, game), game); }
for (Abilities<ManaAbility> manaAbilities: sourceWithCosts) {
available.addManaWithCost(manaAbilities, game);
} }
return available; return available;
} }
@ -2117,13 +2138,13 @@ public abstract class PlayerImpl implements Player, Serializable {
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(playerId)) { for (Permanent permanent: game.getBattlefield().getAllActivePermanents(playerId)) {
boolean canAdd = false; boolean canAdd = false;
for (ManaAbility ability: permanent.getAbilities().getManaAbilities(Zone.BATTLEFIELD)) { for (ManaAbility ability: permanent.getAbilities().getManaAbilities(Zone.BATTLEFIELD)) {
if (ability.canActivate(playerId, game)) {
canAdd = true;
}
if (!ability.getManaCosts().isEmpty()) { if (!ability.getManaCosts().isEmpty()) {
canAdd = false; canAdd = false;
break; break;
} }
if (ability.canActivate(playerId, game)) {
canAdd = true;
}
} }
if (canAdd) { if (canAdd) {
result.add(permanent); result.add(permanent);
@ -2203,7 +2224,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
protected boolean canPlayCardByAlternateCost(Card sourceObject, ManaOptions available, Ability ability, Game game) { protected boolean canPlayCardByAlternateCost(Card sourceObject, ManaOptions available, Ability ability, Game game) {
if (!(sourceObject instanceof Permanent)) { if (sourceObject != null && !(sourceObject instanceof Permanent)) {
for (Ability alternateSourceCostsAbility : sourceObject.getAbilities()) { for (Ability alternateSourceCostsAbility : sourceObject.getAbilities()) {
// if cast for noMana no Alternative costs are allowed // if cast for noMana no Alternative costs are allowed
if (alternateSourceCostsAbility instanceof AlternativeSourceCosts) { if (alternateSourceCostsAbility instanceof AlternativeSourceCosts) {