Updates AI code to use MyRandom directly.

This removes java.util.Random from lots of AI code, futher making it unlikely that developers will accidentally use "new Random()" instead of MyRandom class. This will make running AI experiments easier, because there will be exactly one class that controls the randomness.
This commit is contained in:
Meerkov
2018-04-16 21:31:52 -07:00
parent 5c9a27c930
commit 857f45f9ec
24 changed files with 37 additions and 92 deletions

View File

@@ -1186,16 +1186,14 @@ public class ComputerUtil {
int activations = sa.getRestrictions().getNumberTurnActivations();
if (sa.isTemporary()) {
final Random r = MyRandom.getRandom();
return r.nextFloat() >= .95; // Abilities created by static abilities have no memory
return MyRandom.getRandom().nextFloat() >= .95; // Abilities created by static abilities have no memory
}
if (activations < 10) { //10 activations per turn should still be acceptable
return false;
}
final Random r = MyRandom.getRandom();
return r.nextFloat() >= Math.pow(.95, activations);
return MyRandom.getRandom().nextFloat() >= Math.pow(.95, activations);
}
public static boolean activateForCost(SpellAbility sa, final Player ai) {

View File

@@ -19,7 +19,6 @@ package forge.ai;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@@ -49,6 +48,7 @@ import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import forge.util.TextUtil;
import forge.util.collect.FCollection;
@@ -436,10 +436,10 @@ public class ComputerUtilCombat {
int threshold = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_THRESHOLD));
int maxTreshold = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_MAX_THRESHOLD)) - threshold;
Random rand = new Random();
int chance = rand.nextInt(80) + 5;
int chance = MyRandom.getRandom().nextInt(80) + 5;
while (maxTreshold > 0) {
if (rand.nextInt(100) < chance) {
if (MyRandom.getRandom().nextInt(100) < chance) {
threshold++;
}
maxTreshold--;

View File

@@ -12,7 +12,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class ActivateAbilityAi extends SpellAbilityAi {
@@ -23,8 +22,7 @@ public class ActivateAbilityAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Player opp = ComputerUtil.getOpponentFor(ai);
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
List<Card> list = CardLists.getType(opp.getCardsIn(ZoneType.Battlefield), sa.getParamOrDefault("Type", "Card"));
if (list.isEmpty()) {

View File

@@ -17,7 +17,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.Collections;
import java.util.Random;
public class ChangeZoneAllAi extends SpellAbilityAi {
@Override
@@ -45,9 +44,8 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
}
}
final Random r = MyRandom.getRandom();
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
// TODO targeting with ChangeZoneAll
// really two types of targeting.
@@ -283,7 +281,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
}
}
return (((r.nextFloat() < .8) || sa.isTrigger()) && chance);
return (((MyRandom.getRandom().nextFloat() < .8) || sa.isTrigger()) && chance);
}
/**

View File

@@ -11,7 +11,6 @@ import forge.util.MyRandom;
import forge.util.collect.FCollection;
import java.util.List;
import java.util.Random;
public class CharmAi extends SpellAbilityAi {
@Override
@@ -19,9 +18,7 @@ public class CharmAi extends SpellAbilityAi {
// sa is Entwined, no need for extra logic
if (sa.isEntwine()) {
return true;
}
final Random r = MyRandom.getRandom();
}
final int num = Integer.parseInt(sa.hasParam("CharmNum") ? sa.getParam("CharmNum") : "1");
final int min = sa.hasParam("MinCharmNum") ? Integer.parseInt(sa.getParam("MinCharmNum")) : num;
@@ -65,7 +62,7 @@ public class CharmAi extends SpellAbilityAi {
sa.setChosenList(chosenList);
// prevent run-away activations - first time will always return true
return r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
}
private List<AbilitySub> chooseOptionsAi(List<AbilitySub> choices, final Player ai, boolean isTrigger, int num,

View File

@@ -30,7 +30,6 @@ import forge.util.MyRandom;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class CountersPutAi extends SpellAbilityAi {
@@ -118,7 +117,6 @@ public class CountersPutAi extends SpellAbilityAi {
protected boolean checkApiLogic(Player ai, final SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on what the expected targets could be
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
@@ -514,7 +512,7 @@ public class CountersPutAi extends SpellAbilityAi {
}
} else {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
// Don't activate Curse abilities on my cards and non-curse abilites
// Don't activate Curse abilities on my cards and non-curse abilities
// on my opponents
if (cards.isEmpty() || (cards.get(0).getController().isOpponentOf(ai) && !sa.isCurse())) {
return false;
@@ -524,7 +522,7 @@ public class CountersPutAi extends SpellAbilityAi {
// each non +1/+1 counter on the card is a 10% chance of not
// activating this ability.
if (!(type.equals("P1P1") || type.equals("M1M1") || type.equals("ICE")) && (r.nextFloat() < (.1 * currCounters))) {
if (!(type.equals("P1P1") || type.equals("M1M1") || type.equals("ICE")) && (MyRandom.getRandom().nextFloat() < (.1 * currCounters))) {
return false;
}
// Instant +1/+1

View File

@@ -21,7 +21,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class CountersPutAllAi extends SpellAbilityAi {
@Override
@@ -29,7 +28,6 @@ public class CountersPutAllAi extends SpellAbilityAi {
// AI needs to be expanded, since this function can be pretty complex
// based on what
// the expected targets could be
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
List<Card> hList;
@@ -89,7 +87,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
}
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
if (curse) {
if (type.equals("M1M1")) {
@@ -139,7 +137,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
return chance;
}
return ((r.nextFloat() < .6667) && chance);
return ((MyRandom.getRandom().nextFloat() < .6667) && chance);
}
@Override

View File

@@ -15,8 +15,6 @@ import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.Random;
public class DamageAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
@@ -25,8 +23,7 @@ public class DamageAllAi extends SpellAbilityAi {
final Card source = sa.getHostCard();
// prevent run-away activations - first time will always return true
final Random r = MyRandom.getRandom();
if (r.nextFloat() > Math.pow(.9, sa.getActivationsThisTurn())) {
if (MyRandom.getRandom().nextFloat() > Math.pow(.9, sa.getActivationsThisTurn())) {
return false;
}
// abCost stuff that should probably be centralized...

View File

@@ -15,7 +15,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class DigUntilAi extends SpellAbilityAi {
@@ -34,8 +33,7 @@ public class DigUntilAi extends SpellAbilityAi {
chance = 1;
}
final Random r = MyRandom.getRandom();
final boolean randomReturn = r.nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
final boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
Player libraryOwner = ai;
Player opp = ComputerUtil.getOpponentFor(ai);

View File

@@ -16,7 +16,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class DiscardAi extends SpellAbilityAi {
@@ -142,8 +141,7 @@ public class DiscardAi extends SpellAbilityAi {
return false;
}
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(0.9, sa.getActivationsThisTurn());
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(0.9, sa.getActivationsThisTurn());
// some other variables here, like handsize vs. maxHandSize

View File

@@ -10,7 +10,6 @@ import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class DrainManaAi extends SpellAbilityAi {
@@ -21,8 +20,7 @@ public class DrainManaAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Player opp = ComputerUtil.getOpponentFor(ai);
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
if (tgt == null) {
// assume we are looking to tap human's stuff

View File

@@ -1,7 +1,6 @@
package forge.ai.ability;
import java.util.List;
import java.util.Random;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
@@ -31,8 +30,7 @@ public class EffectAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(final Player ai,final SpellAbility sa) {
final Game game = ai.getGame();
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= .6667;
boolean randomReturn = MyRandom.getRandom().nextFloat() <= .6667;
String logic = "";
if (sa.hasParam("AILogic")) {

View File

@@ -16,7 +16,6 @@ import forge.util.MyRandom;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class FightAi extends SpellAbilityAi {
@Override
@@ -240,8 +239,7 @@ public class FightAi extends SpellAbilityAi {
if (!canKill(opponent, fighter, -pumpDefense)) { // can survive
return true;
} else {
final Random r = MyRandom.getRandom();
if (r.nextInt(20)<(opponent.getCMC() - fighter.getCMC())) { // trade
if (MyRandom.getRandom().nextInt(20)<(opponent.getCMC() - fighter.getCMC())) { // trade
return true;
}
}

View File

@@ -7,8 +7,6 @@ import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
import java.util.Random;
public class LifeExchangeAi extends SpellAbilityAi {
/*
@@ -21,7 +19,6 @@ public class LifeExchangeAi extends SpellAbilityAi {
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
final Random r = MyRandom.getRandom();
final int myLife = aiPlayer.getLife();
Player opponent = ComputerUtil.getOpponentFor(aiPlayer);
final int hLife = opponent.getLife();
@@ -31,7 +28,7 @@ public class LifeExchangeAi extends SpellAbilityAi {
}
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
/*
* TODO - There is one card that takes two targets (Soul Conduit)
@@ -58,7 +55,7 @@ public class LifeExchangeAi extends SpellAbilityAi {
// cost includes sacrifice probably, so make sure it's worth it
chance &= (hLife > (myLife + 8));
return ((r.nextFloat() < .6667) && chance);
return ((MyRandom.getRandom().nextFloat() < .6667) && chance);
}
/**

View File

@@ -13,13 +13,10 @@ import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
import java.util.Random;
public class LifeSetAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Random r = MyRandom.getRandom();
// Ability_Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
final int myLife = ai.getLife();
@@ -56,7 +53,7 @@ public class LifeSetAi extends SpellAbilityAi {
}
// prevent run-away activations - first time will always return true
final boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
final boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
@@ -104,7 +101,7 @@ public class LifeSetAi extends SpellAbilityAi {
return true;
}
return ((r.nextFloat() < .6667) && chance);
return ((MyRandom.getRandom().nextFloat() < .6667) && chance);
}
@Override

View File

@@ -17,7 +17,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class PhasesAi extends SpellAbilityAi {
@Override
@@ -26,8 +25,7 @@ public class PhasesAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
List<Card> tgtCards;
if (tgt == null) {

View File

@@ -2,7 +2,6 @@ package forge.ai.ability;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.google.common.base.Predicate;
@@ -151,8 +150,7 @@ public class ProtectAi extends SpellAbilityAi {
Combat combat = ai.getGame().getCombat();
int dmg = ComputerUtilCombat.damageIfUnblocked(c, opponent, combat, true);
float ratio = 1.0f * dmg / opponent.getLife();
Random r = MyRandom.getRandom();
return r.nextFloat() < ratio;
return MyRandom.getRandom().nextFloat() < ratio;
}
}
return false;

View File

@@ -1,7 +1,5 @@
package forge.ai.ability;
import java.util.Random;
import forge.ai.AiPlayDecision;
import forge.ai.PlayerControllerAi;
import forge.ai.SpellAbilityAi;
@@ -23,8 +21,7 @@ public class RevealAi extends RevealAiBase {
return false;
}
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.667, sa.getActivationsThisTurn() + 1);
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.667, sa.getActivationsThisTurn() + 1);
if (SpellAbilityAi.playReusable(ai, sa)) {
randomReturn = true;
@@ -34,7 +31,7 @@ public class RevealAi extends RevealAiBase {
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
// logic to see if it should reveal Mircacle Card
// logic to see if it should reveal Miracle Card
if (sa.hasParam("MiracleCost")) {
final Card c = sa.getHostCard();
for (SpellAbility s : c.getBasicSpells()) {

View File

@@ -1,7 +1,5 @@
package forge.ai.ability;
import java.util.Random;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
@@ -20,8 +18,7 @@ public class RevealHandAi extends RevealAiBase {
return false;
}
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.667, sa.getActivationsThisTurn() + 1);
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.667, sa.getActivationsThisTurn() + 1);
if (SpellAbilityAi.playReusable(ai, sa)) {
randomReturn = true;

View File

@@ -15,15 +15,12 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import forge.util.TextUtil;
import java.util.Random;
public class SacrificeAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on what the expected targets could be
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
String valid = "";
@@ -52,7 +49,7 @@ public class SacrificeAllAi extends SpellAbilityAi {
}
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
// if only creatures are affected evaluate both lists and pass only if
// human creatures are more valuable
@@ -74,7 +71,7 @@ public class SacrificeAllAi extends SpellAbilityAi {
return false;
}
return ((r.nextFloat() < .9667) && chance);
return ((MyRandom.getRandom().nextFloat() < .9667) && chance);
}
@Override

View File

@@ -15,8 +15,6 @@ import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.Random;
public class ScryAi extends SpellAbilityAi {
/* (non-Javadoc)
@@ -171,8 +169,7 @@ public class ScryAi extends SpellAbilityAi {
chance = .667; // 66.7% chance for sorcery speed (since it will
// never activate EOT)
}
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
if (SpellAbilityAi.playReusable(ai, sa)) {
randomReturn = true;

View File

@@ -21,7 +21,6 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class TapAllAi extends SpellAbilityAi {
@Override
@@ -64,8 +63,7 @@ public class TapAllAi extends SpellAbilityAi {
}
}
final Random r = MyRandom.getRandom();
if (r.nextFloat() > Math.pow(.6667, sa.getActivationsThisTurn())) {
if (MyRandom.getRandom().nextFloat() > Math.pow(.6667, sa.getActivationsThisTurn())) {
return false;
}
@@ -135,9 +133,8 @@ public class TapAllAi extends SpellAbilityAi {
return true;
}
final Random r = MyRandom.getRandom();
boolean rr = false;
if (r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn())) {
if (MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn())) {
rr = true;
}

View File

@@ -8,7 +8,6 @@ import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class TapOrUntapAi extends TapAiBase {
@@ -20,8 +19,7 @@ public class TapOrUntapAi extends TapAiBase {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
if (tgt == null) {
// assume we are looking to tap human's stuff

View File

@@ -16,7 +16,6 @@ import forge.util.MyRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class UnattachAllAi extends SpellAbilityAi {
@@ -25,7 +24,6 @@ public class UnattachAllAi extends SpellAbilityAi {
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
@@ -34,7 +32,7 @@ public class UnattachAllAi extends SpellAbilityAi {
}
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= .9;
boolean chance = MyRandom.getRandom().nextFloat() <= .9;
// Attach spells always have a target
final TargetRestrictions tgt = sa.getTargetRestrictions();