Pokemon Gen IV PHP PRNG

Since PHP can't directly deal with numbers larger than signed 32bit integers, and rather than truncating the data it converts to a dodgy float instead, it's a bit of a faff to impliment the PRNG in PHP. It's fine working with 0x45 as a randomiser but when you try 0x41C64E6D it more or less dies.

So here's my method of implimenting the PRNG using the BCMATH library and some parsing...

$cseed = 0;

//Credit to artefact2 at gmail dot com for bcdechex()
//http://www.php.net/manual/en/ref.bc.php#99130
function bcdechex($dec) {
  $last = bcmod($dec, 16);
  $remain = bcdiv(bcsub($dec, $last), 16);

  if($remain == 0) {
    return dechex($last);
  } else {
    return bcdechex($remain).dechex($last);
  }
} 

function prng($randomiser,$offset,$mask) {
  global $cseed;
  $a = (string) bcmul(sprintf("%u",$randomiser),sprintf("%u",$cseed));  
  $b = (string) bcadd("$a",sprintf("%u",$offset));
  $c = bcdechex($b);

  if(strlen($c)>8) {
    $c = substr($c,strlen($c)-8,8);
  }
  
  $retval = hexdec("0x$c") & $mask;
  $cseed = $retval&0xFFFFFFFF;
  return ($retval>>16)&0xFFFF;
}

Any suggestions on how to do this in a less hacky way, let me know.

Last updated 10:39am 07/06/2011 by User
blog comments powered by Disqus