package builtin.random;
import builtin.BuiltinSub;
import java.util.Random;
import gui.Constants;
import gui.Heap;
import gui.Mint;
import gui.MintException;
import gui.Pointer;
import gui.PointerTools;
import gui.SmartList;
/**
* A coin is a random number generator that will
* be weighted in a certain direction.
* A coin will return heads or tails, with the Double
* passed to the coin determining how often you get heads.
*
* 0.5 = fair coin
* 0.0 = always tails
* 1.0 = always heads
* 0.9 = 90% heads
* 0.2 = 80% tails
* @author Oliver Chu
*/
public class Coin extends BuiltinSub {
private static final Pointer HEADS = Heap.allocateString("heads");
private static final Pointer TAILS = Heap.allocateString("tails");
private double normalize(double d) {
if (d > 0.99) {
return 0.99;
} else if (d < 0.01) {
return 0.01;
}
return d;
}
@Override
public Pointer apply(SmartList<Pointer> args) throws MintException {
try {
Double d = null;
Pointer p = args.get(0);
if (args != null && args.size() != 0) {
if (p.type == Constants.REAL_TYPE) {
d = Heap.dereferenceReal(p.value);
} else {
d = PointerTools.dereferenceReal(p);
}
}
if (d == null) {
System.out.println("Argument " + args.get(0).toString() +
" is not a decimal-point number.");
d = 0.5;
}
Random rng = new Random();
rng.setSeed(System.nanoTime());
if (d > 0.985) {
return HEADS;
} else if (d < 0.015) {
return TAILS;
}
boolean b = normalize(rng.nextDouble()) < d;
return b ? HEADS : TAILS;
} catch (Throwable t) {
System.err.println(t);
Mint.printStackTrace(t.getStackTrace());
return TAILS;
}
}
}