function encryptMT19937($data, $seed = 0)
{
    $seed &= 0xffff;
    $mt = new MT19937();
    $mt->init($seed);
    $dataLen = strlen($data);
    for ($i = 0; $i < $dataLen; $i++) {
        $data[$i] = chr(ord($data[$i]) ^ $mt->int32() & 0xff);
    }
    return $data;
}
    {
        if ($this->index > 623) {
            for ($i = 0; $i < 227; $i++) {
                $y = $this->MT[$i] & 0x80000000 | $this->MT[$i + 1] & 0x7fffffff;
                $this->MT[$i] = $this->MT[$i + 397] ^ $y >> 1 ^ ($y & 1) * 0x9908b0df;
            }
            for (; $i < 623; $i++) {
                $y = $this->MT[$i] & 0x80000000 | $this->MT[$i + 1] & 0x7fffffff;
                $this->MT[$i] = $this->MT[$i - 227] ^ $y >> 1 ^ ($y & 1) * 0x9908b0df;
            }
            $y = $this->MT[623] & 0x80000000 | $this->MT[0] & 0x7fffffff;
            $this->MT[623] = $this->MT[396] ^ $y >> 1 ^ ($y & 1) * 0x9908b0df;
            $this->index = 0;
        }
        $y = $this->MT[$this->index++];
        $y ^= $y >> 11;
        $y ^= $y << 7 & 0x9d2c5680;
        $y ^= $y << 15 & 0xefc60000;
        return $y ^ $y >> 18;
    }
}
// don't output if we're included into another script.
if (!debug_backtrace()) {
    $mt = new MT19937();
    $mt->init(time());
    // :D
    print "Getting some random numbers:\n";
    for ($i = 0; $i < 10; $i++) {
        print $mt->int32() . "\n";
    }
}
 *
 * Crack an MT19937 seed
 *
 * Make sure your MT19937 accepts an integer seed value. Test it (verify that you're getting the same sequence of outputs given a seed).
 *
 * Write a routine that performs the following operation:
 * - Wait a random number of seconds between, I don't know, 40 and 1000.
 * - Seeds the RNG with the current Unix timestamp
 * - Waits a random number of seconds again.
 * - Returns the first 32 bit output of the RNG.
 *
 * You get the idea. Go get coffee while it runs. Or just simulate the passage of time, although you're missing some of the fun of this exercise if you do that.
 *
 * From the 32 bit RNG output, discover the seed.
 */
require_once '21-implement-the-mt19937-mersenne-twister-rng.php';
// Sorry, going for simulated passage of time.
$now = time();
$mt = new MT19937();
$mt->init($now - mt_rand(80, 2000));
// randception
$r = $mt->int32();
print "Got first random number: {$r}\n";
print "Time is " . date('H:i:s', $now) . "\n\n";
for ($i = 0; $i <= 2000; $i++) {
    $mt->init($now - $i);
    // randception
    if ($mt->int32() === $r) {
        print "RNG was seeded at: " . date('H:i:s', $now - $i) . "\n\n";
    }
}
function untemper($value)
{
    $y = $value ^ $value >> 18;
    // Only 14 bits affected, so we can restore them all at once
    $y ^= $y << 15 & 0xefc60000;
    // Only 15 bits affected (17 remain after shift, but mask makes it 15)
    // here we have to restore 7 bits at a time
    $x = $y ^ $y << 7 & 0x9d2c5680;
    // 14
    $x = $y ^ $x << 7 & 0x9d2c5680;
    // 21
    $x = $y ^ $x << 7 & 0x9d2c5680;
    // 28
    $y ^= $x << 7 & 0x9d2c5680;
    // here we have to restore 11 bits at a time
    $x = $y ^ $y >> 11;
    return $y ^ $x >> 11;
}
$mt = new MT19937();
$mt->init(time());
// :D :D
$state = [];
for ($i = 0; $i < 624; $i++) {
    $state[] = untemper($mt->int32());
}
$mt_c23 = new MT19937_c23();
$mt_c23->splice($state);
print "Original:      Clone:\n";
for ($i = 0; $i < 10; $i++) {
    print str_pad($mt->int32(), 15) . $mt_c23->int32() . "\n";
}