summaryrefslogtreecommitdiff
path: root/noncore/games/sfcave
Unidiff
Diffstat (limited to 'noncore/games/sfcave') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/sfcave/random.cpp179
-rw-r--r--noncore/games/sfcave/random.h19
-rw-r--r--noncore/games/sfcave/sfcave.cpp79
-rw-r--r--noncore/games/sfcave/sfcave.h12
-rw-r--r--noncore/games/sfcave/sfcave.pro4
5 files changed, 274 insertions, 19 deletions
diff --git a/noncore/games/sfcave/random.cpp b/noncore/games/sfcave/random.cpp
new file mode 100644
index 0000000..c4c10bb
--- a/dev/null
+++ b/noncore/games/sfcave/random.cpp
@@ -0,0 +1,179 @@
1/* -------------------------------------------------------------------------
2 * This is an ANSI C library for multi-stream random number generation.
3 * The use of this library is recommended as a replacement for the ANSI C
4 * rand() and srand() functions, particularly in simulation applications
5 * where the statistical 'goodness' of the random number generator is
6 * important. The library supplies 256 streams of random numbers; use
7 * SelectStream(s) to switch between streams indexed s = 0,1,...,255.
8 *
9 * The streams must be initialized. The recommended way to do this is by
10 * using the function PlantSeeds(x) with the value of x used to initialize
11 * the default stream and all other streams initialized automatically with
12 * values dependent on the value of x. The following convention is used
13 * to initialize the default stream:
14 * if x > 0 then x is the state
15 * if x < 0 then the state is obtained from the system clock
16 * if x = 0 then the state is to be supplied interactively.
17 *
18 * The generator used in this library is a so-called 'Lehmer random number
19 * generator' which returns a pseudo-random number uniformly distributed
20 * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the
21 * smallest and largest possible values are (1 / m) and 1 - (1 / m)
22 * respectively. For more details see:
23 *
24 * "Random Number Generators: Good Ones Are Hard To Find"
25 * Steve Park and Keith Miller
26 * Communications of the ACM, October 1988
27 *
28 * Name : rngs.c (Random Number Generation - Multiple Streams)
29 * Authors : Steve Park & Dave Geyer
30 * Language : ANSI C
31 * Latest Revision : 09-22-98
32 * -------------------------------------------------------------------------
33 */
34
35#include <stdio.h>
36#include <time.h>
37#include "random.h"
38
39#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */
40#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */
41#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */
42#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */
43#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */
44#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */
45
46static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */
47static int stream = 0; /* stream index, 0 is the default */
48static int initialized = 0; /* test for stream initialization */
49
50
51 double Random(void)
52/* ----------------------------------------------------------------
53 * Random returns a pseudo-random real number uniformly distributed
54 * between 0.0 and 1.0.
55 * ----------------------------------------------------------------
56 */
57{
58 const long Q = MODULUS / MULTIPLIER;
59 const long R = MODULUS % MULTIPLIER;
60 long t;
61
62 t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q);
63 if (t > 0)
64 seed[stream] = t;
65 else
66 seed[stream] = t + MODULUS;
67 return ((double) seed[stream] / MODULUS);
68}
69
70
71 void PlantSeeds(long x)
72/* ---------------------------------------------------------------------
73 * Use this function to set the state of all the random number generator
74 * streams by "planting" a sequence of states (seeds), one per stream,
75 * with all states dictated by the state of the default stream.
76 * The sequence of planted states is separated one from the next by
77 * 8,367,782 calls to Random().
78 * ---------------------------------------------------------------------
79 */
80{
81 const long Q = MODULUS / A256;
82 const long R = MODULUS % A256;
83 int j;
84 int s;
85
86 initialized = 1;
87 s = stream; /* remember the current stream */
88 SelectStream(0); /* change to stream 0 */
89 PutSeed(x); /* set seed[0] */
90 stream = s; /* reset the current stream */
91 for (j = 1; j < STREAMS; j++) {
92 x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q);
93 if (x > 0)
94 seed[j] = x;
95 else
96 seed[j] = x + MODULUS;
97 }
98}
99
100
101 void PutSeed(long x)
102/* ---------------------------------------------------------------
103 * Use this function to set the state of the current random number
104 * generator stream according to the following conventions:
105 * if x > 0 then x is the state (unless too large)
106 * if x < 0 then the state is obtained from the system clock
107 * if x = 0 then the state is to be supplied interactively
108 * ---------------------------------------------------------------
109 */
110{
111 char ok = 0;
112
113 if (x > 0)
114 x = x % MODULUS; /* correct if x is too large */
115 if (x < 0)
116 x = ((unsigned long) time((time_t *) NULL)) % MODULUS;
117 if (x == 0)
118 while (!ok) {
119 printf("\nEnter a positive integer seed (9 digits or less) >> ");
120 scanf("%ld", &x);
121 ok = (0 < x) && (x < MODULUS);
122 if (!ok)
123 printf("\nInput out of range ... try again\n");
124 }
125 seed[stream] = x;
126}
127
128
129 void GetSeed(long *x)
130/* ---------------------------------------------------------------
131 * Use this function to get the state of the current random number
132 * generator stream.
133 * ---------------------------------------------------------------
134 */
135{
136 *x = seed[stream];
137}
138
139
140 void SelectStream(int index)
141/* ------------------------------------------------------------------
142 * Use this function to set the current random number generator
143 * stream -- that stream from which the next random number will come.
144 * ------------------------------------------------------------------
145 */
146{
147 stream = ((unsigned int) index) % STREAMS;
148 if ((initialized == 0) && (stream != 0)) /* protect against */
149 PlantSeeds(DEFAULT); /* un-initialized streams */
150}
151
152
153 void TestRandom(void)
154/* ------------------------------------------------------------------
155 * Use this (optional) function to test for a correct implementation.
156 * ------------------------------------------------------------------
157 */
158{
159 long i;
160 long x;
161 double u;
162 char ok = 0;
163
164 SelectStream(0); /* select the default stream */
165 PutSeed(1); /* and set the state to 1 */
166 for(i = 0; i < 10000; i++)
167 u = Random();
168 GetSeed(&x); /* get the new state value */
169 ok = (x == CHECK); /* and check for correctness */
170
171 SelectStream(1); /* select stream 1 */
172 PlantSeeds(1); /* set the state of all streams */
173 GetSeed(&x); /* get the state of stream 1 */
174 ok = ok && (x == A256); /* x should be the jump multiplier */
175 if (ok)
176 printf("\n The implementation of rngs.c is correct.\n\n");
177 else
178 printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n");
179}
diff --git a/noncore/games/sfcave/random.h b/noncore/games/sfcave/random.h
new file mode 100644
index 0000000..4bc7c06
--- a/dev/null
+++ b/noncore/games/sfcave/random.h
@@ -0,0 +1,19 @@
1/* -----------------------------------------------------------------------
2 * Name : rngs.h (header file for the library file rngs.c)
3 * Author : Steve Park & Dave Geyer
4 * Language : ANSI C
5 * Latest Revision : 09-22-98
6 * -----------------------------------------------------------------------
7 */
8
9#if !defined( _RNGS_ )
10#define _RNGS_
11
12double Random(void);
13void PlantSeeds(long x);
14void GetSeed(long *x);
15void PutSeed(long x);
16void SelectStream(int index);
17void TestRandom(void);
18
19#endif
diff --git a/noncore/games/sfcave/sfcave.cpp b/noncore/games/sfcave/sfcave.cpp
index 788606f..b5bc736 100644
--- a/noncore/games/sfcave/sfcave.cpp
+++ b/noncore/games/sfcave/sfcave.cpp
@@ -3,2 +3,3 @@
3#include <math.h> 3#include <math.h>
4#include <time.h>
4 5
@@ -28,2 +29,3 @@
28#define STATE_MENU 5 29#define STATE_MENU 5
30#define STATE_REPLAY 6
29 31
@@ -129,2 +131,3 @@ SFCave :: SFCave( int spd, QWidget *w, char *name )
129{ 131{
132 replayIt = 0;
130#ifdef QWS 133#ifdef QWS
@@ -166,4 +169,6 @@ SFCave :: SFCave( int spd, QWidget *w, char *name )
166 169
167 setUp(); 170// setUp();
168 crashLineLength = -1; 171 crashLineLength = -1;
172 state = STATE_MENU;
173 prevState = STATE_MENU;
169 174
@@ -184,5 +189,17 @@ void SFCave :: start()
184 189
190void SFCave :: setSeed( int seed )
191{
192 if ( seed == -1 )
193 currentSeed = ((unsigned long) time((time_t *) NULL));
194 else
195 currentSeed = seed;
196 PutSeed( currentSeed );
197}
198
185int SFCave :: nextInt( int range ) 199int SFCave :: nextInt( int range )
186{ 200{
187 return rand() % range; 201 int val = (int)(Random( ) * range);
202
203 return val;
204
188} 205}
@@ -191,5 +208,2 @@ void SFCave :: setUp()
191{ 208{
192 state = STATE_MENU;
193 prevState = STATE_MENU;
194
195 score = 0; 209 score = 0;
@@ -223,2 +237,3 @@ void SFCave :: setUp()
223 crashLineLength = 0; 237 crashLineLength = 0;
238 lastGateBottomY = 0;
224 239
@@ -256,2 +271,3 @@ void SFCave :: setUp()
256 blocks[i].setY( -1 ); 271 blocks[i].setY( -1 );
272
257} 273}
@@ -266,2 +282,3 @@ void SFCave :: run()
266 case STATE_NEWGAME: 282 case STATE_NEWGAME:
283 setSeed( -1 );
267 setUp(); 284 setUp();
@@ -269,3 +286,14 @@ void SFCave :: run()
269 state = STATE_RUNNING; 286 state = STATE_RUNNING;
287 replay = false;
288 replayList.clear();
270 break; 289 break;
290 case STATE_REPLAY:
291 setSeed( currentSeed );
292 setUp();
293 draw();
294 state = STATE_RUNNING;
295 replay = true;
296 if ( replayIt )
297 delete replayIt;
298 replayIt = new QListIterator<int>( replayList );
271 case STATE_BOSS: 299 case STATE_BOSS:
@@ -286,2 +314,12 @@ void SFCave :: run()
286 nrFrames ++; 314 nrFrames ++;
315
316 if ( replay )
317 {
318 while( replayIt->current() && *(replayIt->current()) == nrFrames )
319 {
320 press = !press;
321 ++(*replayIt);
322 }
323 }
324
287 if ( CURRENT_GAME_TYPE == SFCAVE_GAME ) 325 if ( CURRENT_GAME_TYPE == SFCAVE_GAME )
@@ -525,5 +563,5 @@ void SFCave :: addGate()
525 // See if height between last gate and this one is too big 563 // See if height between last gate and this one is too big
526 if ( b1Height - 200 > lastGateBottomY ) 564 if ( b1Height - 100 > lastGateBottomY )
527 b1Height -= 25; 565 b1Height -= 25;
528 else if ( b1Height + 200 < lastGateBottomY ) 566 else if ( b1Height + 100 < lastGateBottomY )
529 b1Height += 25; 567 b1Height += 25;
@@ -531,2 +569,3 @@ void SFCave :: addGate()
531 569
570
532 int x2 = sWidth; 571 int x2 = sWidth;
@@ -775,3 +814,7 @@ void SFCave :: keyPressEvent( QKeyEvent *e )
775 case Qt::Key_Space: 814 case Qt::Key_Space:
776 press = true; 815 if ( !press )
816 {
817 press = true;
818 replayList.append( new int( nrFrames ) );
819 }
777 break; 820 break;
@@ -806,18 +849,22 @@ void SFCave :: keyReleaseEvent( QKeyEvent *e )
806 case Qt::Key_Space: 849 case Qt::Key_Space:
807 press = false; 850 case Qt::Key_Up:
851 if ( press )
852 {
853 press = false;
854
855 replayList.append( new int( nrFrames ) );
856 }
808 break; 857 break;
809 858
810 case Qt::Key_Up:
811 press = false;
812
813 case Qt::Key_R: 859 case Qt::Key_R:
814 case Qt::Key_Down:
815 if ( state == STATE_CRASHED ) 860 if ( state == STATE_CRASHED )
816 { 861 {
817 state = STATE_NEWGAME; 862 state = STATE_REPLAY;
818 } 863 }
819 else
820 movel = true;
821 break; 864 break;
822 865
866 case Qt::Key_Down:
867 if ( state == STATE_CRASHED )
868 state = STATE_NEWGAME;
869 break;
823 default: 870 default:
diff --git a/noncore/games/sfcave/sfcave.h b/noncore/games/sfcave/sfcave.h
index 69a0e13..0d9a626 100644
--- a/noncore/games/sfcave/sfcave.h
+++ b/noncore/games/sfcave/sfcave.h
@@ -6,4 +6,5 @@
6#include <qtimer.h> 6#include <qtimer.h>
7#include <qlist.h>
7 8
8 9#include "random.h"
9 10
@@ -13,2 +14,4 @@
13 14
15
16
14class SFCave : public QMainWindow 17class SFCave : public QMainWindow
@@ -22,2 +25,8 @@ public:
22 25
26 int currentSeed;
27
28 QList<int> replayList;
29 QListIterator<int> *replayIt;
30 bool replay;
31
23 int blockWidth; 32 int blockWidth;
@@ -81,2 +90,3 @@ public:
81 void start(); 90 void start();
91 void setSeed( int seed );
82 int nextInt( int range ); 92 int nextInt( int range );
diff --git a/noncore/games/sfcave/sfcave.pro b/noncore/games/sfcave/sfcave.pro
index f4b9e5d..5f49330 100644
--- a/noncore/games/sfcave/sfcave.pro
+++ b/noncore/games/sfcave/sfcave.pro
@@ -3,4 +3,4 @@ CONFIG += qt warn_on release
3 DESTDIR = $(OPIEDIR)/bin 3 DESTDIR = $(OPIEDIR)/bin
4 SOURCES = sfcave.cpp helpwindow.cpp 4 SOURCES = sfcave.cpp helpwindow.cpp random.cpp
5 HEADERS = sfcave.h helpwindow.h 5 HEADERS = sfcave.h helpwindow.h random.h
6 TARGET = sfcave 6 TARGET = sfcave