/*
* RAM $Id: random.c 43 2008-11-07 13:01:52Z quixadhal $
*/
/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include "merc.h"
#include "random.h"
/*
* I've gotten too many bad reports on OS-supplied random number generators.
* This is the Mitchell-Moore algorithm from Knuth Volume II.
* Best to leave the constants alone unless you've read Knuth.
* -- Furey
*/
/* I noticed streaking with this random number generator, so I switched
back to the system srandom call. If this doesn't work for you,
define OLD_RAND to use the old system -- Alander */
#if defined (OLD_RAND)
static int rgiState[2 + 55];
void init_random( void )
{
int *piState = NULL;
int iState = 0;
piState = &rgiState[2];
piState[-2] = 55 - 55;
piState[-1] = 55 - 24;
piState[0] = ( ( int ) current_time ) & ( ( 1 << 30 ) - 1 );
piState[1] = 1;
for ( iState = 2; iState < 55; iState++ )
{
piState[iState] = ( piState[iState - 1] + piState[iState - 2] )
& ( ( 1 << 30 ) - 1 );
}
return;
}
int number_random( void )
{
int *piState = NULL;
int iState1 = 0;
int iState2 = 0;
int iRand = 0;
piState = &rgiState[2];
iState1 = piState[-2];
iState2 = piState[-1];
iRand = ( piState[iState1] + piState[iState2] ) & ( ( 1 << 30 ) - 1 );
piState[iState1] = iRand;
if ( ++iState1 == 55 )
iState1 = 0;
if ( ++iState2 == 55 )
iState2 = 0;
piState[-2] = iState1;
piState[-1] = iState2;
return iRand >> 6;
}
#else
void init_random( void )
{
srandom( time( NULL ) ^ getpid( ) );
}
int number_random( void )
{
return random( ) >> 6;
}
#endif
/*
* Generate a random number.
*/
int number_range( int from, int to )
{
int power = 0;
int number = 0;
if ( from == 0 && to == 0 )
return 0;
if ( ( to = to - from + 1 ) <= 1 )
return from;
for ( power = 2; power < to; power <<= 1 )
;
while ( ( number = number_random( ) & ( power - 1 ) ) >= to )
;
return from + number;
}
/*
* Return a random number within a bit limit?
*/
int number_bits( int width )
{
return number_random( ) & ( ( 1 << width ) - 1 );
}
/*
* Stick a little fuzz on a number.
*/
int number_fuzzy( int number )
{
switch ( number_bits( 2 ) )
{
case 0:
number -= 1;
break;
case 3:
number += 1;
break;
}
return UMAX( 1, number );
}
/*
* Generate a percentile roll.
*/
int number_percent( void )
{
return number_range( 1, 100 );
}
/*
* Generate a random door.
*/
int number_door( void )
{
return number_range( 1, MAX_EXIT ) - 1;
}
/*
* Roll some dice.
*/
int dice( int number, int size )
{
int idice = 0;
int sum = 0;
switch ( size )
{
case 0:
return 0;
case 1:
return number;
}
for ( idice = 0, sum = 0; idice < number; idice++ )
sum += number_range( 1, size );
return sum;
}