home *** CD-ROM | disk | FTP | other *** search
- //
- // Random
- //
- // <<See the file Random.h for more information>>.
- //
- // Version 1.0, 1991 May 30
- //
- // Written by Gregor Purdy
- // gregor@oit.itd.umich.edu
- //
- // See the README and COPYING files included for
- // information and distribution and usage rights.
- //
-
-
- #import <sys/time.h>
- #import "Random.h"
-
-
- @implementation Random
-
- - init
- {
- [super init]; // Make a new instance using superclass' method
- [self newSeeds]; // Get a new seed for ourselves
-
- return self;
- }
-
- - initSeeds:(int)s1 :(int)s2 :(int)s3
- {
- [super init];
- [self setSeeds:s1 :s2 :s3];
-
- return self;
- }
-
- - newSeeds
- {
- struct timeval theTime; // gettimeofday return structure
-
- gettimeofday(&theTime,0); // Get the time of day in seconds and microseconds
- h1 = theTime.tv_usec; // Set seed 1 by microseconds past second
- gettimeofday(&theTime,0); // Get the time of day in seconds and microseconds
- h2 = theTime.tv_usec; // Set seed 2 by microseconds past second
- gettimeofday(&theTime,0); // Get the time of day in seconds and microseconds
- h3 = theTime.tv_usec; // Set seed 3 by microseconds past second
-
- return self;
- }
-
- - setSeeds:(int) s1 :(int) s2 :(int) s3
- {
- h1 = s1; // Set the seeds to the values given
- h2 = s2;
- h3 = s3;
-
- return self;
- }
-
- - getSeeds:(int *)s1 :(int *)s2 :(int *)s3
- {
- if((s1 == NULL) || (s2 == NULL) || (s3 == NULL))
- return nil;
-
- *s1 = h1;
- *s2 = h2;
- *s3 = h3;
-
- return self;
- }
-
- //
- // See the Source article for the explanations of these constants
- //
- #define M1 32771
- #define M2 32779
- #define M3 32783
- #define F1 179
- #define F2 183
- #define F3 182
-
- #define MAXNUM 32767
- #define RANGE 32768
-
- - (int) rand
- {
- h1 = (F1 * h1) % M1; // Update the sections
- h2 = (F2 * h2) % M2;
- h3 = (F2 * h3) % M3;
-
- if ((h1 > MAXNUM) || (h2 > MAXNUM) || (h3 > MAXNUM)) // If a section is out of range,
- return [self rand]; // return next result
- else // Otherwise,
- return (h1 + h2 + h3) % RANGE; // Return this result
- }
-
- - (int) randMax:(int)max
- {
- return (int)((float)[self rand] / (float)RANGE * (float)(max + 1));
- }
-
- - (int) randMin:(int)min max:(int)max
- {
- return min + [self randMax:(max - min)];
- }
-
- - (float) percent
- {
- return ((float)[self rand] / (float)RANGE);
- }
-
- - (int) rollDie:(int) numSides
- {
- return [self randMax:(numSides - 1)] + 1;
- }
-
- - (int) roll:(int) numRolls die:(int) numSides
- {
- int temp = 0;
- int loop;
-
- for (loop = 1 ; loop <= numRolls ; loop++ )
- temp += [self rollDie:numSides];
-
- return temp;
- }
-
- - (int) rollBest:(int)numWanted of:(int)numRolls die:(int)numSides
- {
- int temp[numRolls]; // Array of rolls
- int loop1; // First loop control variable
- int loop2; // Second loop control variable
- int highest; // Index of highest found roll
- int accumulator = 0; // Accumulates total best roll
-
- for (loop1 = 1 ; loop1 <= numRolls ; loop1++) // Fill an array with rolls
- temp[loop1] = [self rollDie:numSides];
-
- for (loop1 = 1 ; loop1 <= numWanted; loop1++) {
- highest = 1; // Start off as if first is highest
- for (loop2 = 2 ; loop2 <= numRolls ; loop2++) // Scan array for higher rolls
- if (temp[loop2] > temp[highest]) // If temp[loop2] is higher, then
- highest = loop2; // remember that fact
- accumulator += temp[highest]; // Add highest roll to accumulator
- temp[highest] = 0; // Clear highest roll so we don't find it again
- }
-
- return accumulator; // Return what we found
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
-
- NXReadTypes(stream, "iii", &h1, &h2, &h3);
-
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
-
- NXWriteTypes(stream, "iii", &h1, &h2, &h3);
-
- return self;
- }
-
-
- @end
-
-
- //
- // End of file.
- //