This is MiscRandom.m in view mode; [Download] [Up]
/* MiscRandom.h Copyright 1996 Gregor Purdy. This notice may not be removed from this source code. The use and distribution of this software is governed by the terms of the MiscKit license agreement. Refer to the license document included with the MiscKit distribution for the terms. Converted to OpenStep, August 1996, Uwe Hoffmann. */ #ifdef WIN32 #import <ntunix.h> #else #import <sys/time.h> #endif #import "MiscRandom.h" @implementation MiscRandom /*" The MiscRandom class provides services for random number generation and die rolling. It implements its own random number generator with a cycle length of 8.8 trillion. The algorithm used by the MiscRandom class is that given in the article: %{ªA Higly Random Random±Number Generatorº} by T.A. Elkins Computer Language, Volume 6, Number 12 (December 1989), Pages 59-65 Published by: Miller Freeman Publications 500 Howard Street San Francisco, CA 94105 (415) 397-1881 "*/ - init /*"Initializes the Random with seeds from the milliseconds count of the system clock (uses #newSeeds)."*/ { [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 /*"Initializes the Random with the seeds given (uses #setSeeds:::)."*/ { [super init]; [self setSeeds:s1 :s2 :s3]; return self; } - newSeeds /*"Sets the seeds from the milliseconds count of the system clock."*/ { 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; } - getSeeds:(int *)s1 :(int *)s2 :(int *)s3 /*"Puts the values of the seeds into the integer variables pointed to."*/ { if((s1 == NULL) || (s2 == NULL) || (s3 == NULL)) return nil; *s1 = h1; *s2 = h2; *s3 = h3; return self; } - setSeeds:(int)s1 :(int)s2 :(int)s3 /*"Sets the seeds to the values given."*/ { h1 = s1; // Set the seeds to the values given h2 = s2; h3 = s3; 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 /*"Returns an int in the range [0, 32767]."*/ { 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 /*"Returns an int in the range [0, max]."*/ { return (int)((float)[self rand] / (float)RANGE * (float)(max + 1)); } - (int)randMin:(int)min max:(int)max /*"Returns an int in the range [min, max]."*/ { return min + [self randMax:(max - min)]; } - (float)percent /*"Returns a float in the range [0.0, 1.0]."*/ { return ((float)[self rand] / (float)RANGE); } - (int)rollDie:(int)numSides /*"Returns an int in the range [1, numSides]."*/ { return [self randMax:(numSides - 1)] + 1; } - (int)roll:(int)numRolls die:(int)numSides /*"Returns an int in the range [numRolls, numRolls * 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 /*"Returns the sum of the best numWanted rolls."*/ { 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 } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.