[
There is a bug in the randRange()
function. See this post. --admin]
I needed a PRNG for my game. I found the one provided by Mark Armbrust here:
http://nand2tetris-questions-and-answers-forum.32033.n3.nabble.com/Random-number-generator-for-hack-cpu-td4025503.htmlwhich was a good start for me. However this got me doing a bit more research and ended up implementing a Linear Congruential Generator using the Schrage Method. LCG is old, tried and tested. Not the best these days but simple enough to be implemented in Jack. The key point is selection of the A and M values. For this I used an often cited paper which lists 'good values'. See code below for references.
Code is released below under the Simplified BSD license.
Hope it may prove useful to people on this forum.
While I'm here, I must say how much I am enjoying working through the book and projects. Currently implementing my game for Project 9 which I will post about when finished.
Also a huge thanks to Mark (cadet1620) who has helped me and many others through his helpful and encouraging posts.
Rowan
------------
/* LCGRandom.jack, released under the BSD 2-Clause License, also known as Simplified BSD or FreeBSD License"
* Copyright (c) 2013, Rowan Limb
* All rights reserved.
* This software implements a PRNG based on Linear Congruential Generator (Schrage Method).
* Based on method documented here:
http://www.cems.uwe.ac.uk/~irjohnso/coursenotes/ufeen8-15-m/p1192-parkmiller.pdf * and using constants for A and M from "Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure" by Pierre L'Ecuyer, 1999 (citeseer:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.1024)
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
class LCGRandom {
static int seed;
static int A;
static int M;
static int Q;
static int R;
function void setSeed(int newSeed) {
let seed = newSeed;
if(seed=0) {
let seed=1;
}
let A=219;
let M=32749;
let Q=M/A;
let R=Utils.mod(M,A);
return;
}
/* returns a random int in range 0..(M-1) inclusive */
function int rand() {
var int test;
let test=(A*(Utils.mod(seed,Q)))-(R*(seed/Q));
if(test<0) {
let seed=test+M;
}
else {
let seed=test;
}
return seed;
}
/* returns a random int in range low..high inclusive */
function int randRange(int low, int high) {
var int scale;
let scale = (M / (high - low + 1));
return (LCGRandom.rand() / scale) + low;
}
}
/* Utils.jack, released under the BSD 2-Clause License, also known as Simplified BSD or FreeBSD License"
* Copyright (c) 2013, Rowan Limb
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
class Utils {
/* returns a % b */
function int mod(int a, int b) {
var int d;
var int r;
let d = Math.divide(a,b);
let r = a - (b * d);
return r;
}
}