RaM Fire Updated/
/*
 * 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;
}