/******************************************************************************* * Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control; import static net.sf.robocode.io.Logger.logError; import static net.sf.robocode.io.Logger.logWarning; import java.lang.reflect.Field; import java.util.Random; /** * The RandomFactory is used for controlling the generation of random numbers, * and supports generating random numbers that are deterministic, which is * useful for testing purposes. * * @author Pavel Savara (original) * @since 1.6.1 */ public class RandomFactory { private static Random randomNumberGenerator; private static boolean warningNotSupportedLogged; private static boolean isDeterministic; static { randomNumberGenerator = new Random(); } public boolean isDeterministic() { return isDeterministic; } /** * Returns the random number generator used for generating a stream of * random numbers. * * @return a {@link java.util.Random} instance. * @see java.util.Random */ public static Random getRandom() { if (randomNumberGenerator == null) { try { Math.random(); final Field field = Math.class.getDeclaredField("randomNumberGenerator"); final boolean savedFieldAccessible = field.isAccessible(); field.setAccessible(true); randomNumberGenerator = (Random) field.get(null); field.setAccessible(savedFieldAccessible); } catch (NoSuchFieldException e) { logWarningNotSupported(); randomNumberGenerator = new Random(); } catch (IllegalAccessException e) { logError(e); randomNumberGenerator = new Random(); } } return randomNumberGenerator; } /** * Sets the random number generator instance used for generating a * stream of random numbers. * * @param random a {@link java.util.Random} instance. * @see java.util.Random */ public static void setRandom(Random random) { randomNumberGenerator = random; try { Math.random(); final Field field = Math.class.getDeclaredField("randomNumberGenerator"); final boolean savedFieldAccessible = field.isAccessible(); field.setAccessible(true); field.set(null, randomNumberGenerator); field.setAccessible(savedFieldAccessible); } catch (NoSuchFieldException e) { logWarningNotSupported(); } catch (IllegalAccessException e) { logError(e); } // TODO ZAMO using Robot classloader inject seed also for all instances being created by robots } /** * Resets the random number generator instance to be deterministic when * generating random numbers. * * @param seed the seed to use for the new deterministic random generator. */ public static void resetDeterministic(long seed) { setRandom(new Random(seed)); isDeterministic = true; } /** * Logs a warning that the deterministic random feature is not supported by the JVM. */ private static void logWarningNotSupported() { if (!(warningNotSupportedLogged || System.getProperty("RANDOMSEED", "none").equals("none"))) { logWarning( "The deterministic random generator feature is not supported by this JVM:\n" + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " " + System.getProperty("java.vm.version")); warningNotSupportedLogged = true; } } }