summaryrefslogtreecommitdiff
authorandyq <andyq>2002-12-09 20:30:46 (UTC)
committer andyq <andyq>2002-12-09 20:30:46 (UTC)
commitb9a448e0687558c1cb79f801161966e15d589132 (patch) (unidiff)
tree4f485b85b8bc03546008dd2003c75bf60f7acd9b
parentaccc4e231dc34744e75d32af77eeb98f46006c27 (diff)
downloadopie-b9a448e0687558c1cb79f801161966e15d589132.zip
opie-b9a448e0687558c1cb79f801161966e15d589132.tar.gz
opie-b9a448e0687558c1cb79f801161966e15d589132.tar.bz2
Added replay function and included own random method for replay functionality
Diffstat (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
@@ -1,6 +1,7 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <math.h> 3#include <math.h>
4#include <time.h>
4 5
5#ifdef QWS 6#ifdef QWS
6#include <qpe/qpeapplication.h> 7#include <qpe/qpeapplication.h>
@@ -26,6 +27,7 @@
26#define STATE_CRASHED 3 27#define STATE_CRASHED 3
27#define STATE_NEWGAME 4 28#define STATE_NEWGAME 4
28#define STATE_MENU 5 29#define STATE_MENU 5
30#define STATE_REPLAY 6
29 31
30// Menus 32// Menus
31#define MENU_MAIN_MENU 0 33#define MENU_MAIN_MENU 0
@@ -127,6 +129,7 @@ SFCave :: SFCave( int spd, QWidget *w, char *name )
127 : QMainWindow( w, name ) 129 : QMainWindow( w, name )
128 130
129{ 131{
132 replayIt = 0;
130#ifdef QWS 133#ifdef QWS
131 showMaximized(); 134 showMaximized();
132#else 135#else
@@ -164,8 +167,10 @@ SFCave :: SFCave( int spd, QWidget *w, char *name )
164 offscreen = new QPixmap( sWidth, sHeight ); 167 offscreen = new QPixmap( sWidth, sHeight );
165 offscreen->fill( Qt::black ); 168 offscreen->fill( Qt::black );
166 169
167 setUp(); 170// setUp();
168 crashLineLength = -1; 171 crashLineLength = -1;
172 state = STATE_MENU;
173 prevState = STATE_MENU;
169 174
170 gameTimer = new QTimer( this, "game timer" ); 175 gameTimer = new QTimer( this, "game timer" );
171 connect( gameTimer, SIGNAL( timeout() ), 176 connect( gameTimer, SIGNAL( timeout() ),
@@ -182,16 +187,25 @@ void SFCave :: start()
182 187
183} 188}
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}
189 206
190void SFCave :: setUp() 207void SFCave :: setUp()
191{ 208{
192 state = STATE_MENU;
193 prevState = STATE_MENU;
194
195 score = 0; 209 score = 0;
196 offset = 0; 210 offset = 0;
197 nrFrames = 0; 211 nrFrames = 0;
@@ -221,6 +235,7 @@ void SFCave :: setUp()
221 } 235 }
222 236
223 crashLineLength = 0; 237 crashLineLength = 0;
238 lastGateBottomY = 0;
224 239
225 user.setRect( 50, sWidth/2, 4, 4 ); 240 user.setRect( 50, sWidth/2, 4, 4 );
226 241
@@ -254,6 +269,7 @@ void SFCave :: setUp()
254 } 269 }
255 for ( int i = 0 ; i < BLOCKSIZE ; ++i ) 270 for ( int i = 0 ; i < BLOCKSIZE ; ++i )
256 blocks[i].setY( -1 ); 271 blocks[i].setY( -1 );
272
257} 273}
258 274
259void SFCave :: run() 275void SFCave :: run()
@@ -264,10 +280,22 @@ void SFCave :: run()
264 displayMenu(); 280 displayMenu();
265 break; 281 break;
266 case STATE_NEWGAME: 282 case STATE_NEWGAME:
283 setSeed( -1 );
267 setUp(); 284 setUp();
268 draw(); 285 draw();
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:
272 drawBoss(); 300 drawBoss();
273 break; 301 break;
@@ -284,6 +312,16 @@ void SFCave :: run()
284 312
285 // Apply Game rules 313 // Apply Game rules
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 )
288 handleGameSFCave(); 326 handleGameSFCave();
289 else if ( CURRENT_GAME_TYPE == GATES_GAME ) 327 else if ( CURRENT_GAME_TYPE == GATES_GAME )
@@ -523,12 +561,13 @@ void SFCave :: addGate()
523 int b1Height = nextInt(mapBottom[50] - mapTop[50] - gapHeight); 561 int b1Height = nextInt(mapBottom[50] - mapTop[50] - gapHeight);
524 562
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;
530 lastGateBottomY = b1Height; 568 lastGateBottomY = b1Height;
531 569
570
532 int x2 = sWidth; 571 int x2 = sWidth;
533 int y2 = y1 + b1Height + gapHeight; 572 int y2 = y1 + b1Height + gapHeight;
534 int b2Height = mapBottom[50] - y2; 573 int b2Height = mapBottom[50] - y2;
@@ -773,7 +812,11 @@ void SFCave :: keyPressEvent( QKeyEvent *e )
773 case Qt::Key_Up: 812 case Qt::Key_Up:
774 case Qt::Key_F9: 813 case Qt::Key_F9:
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;
778 case Qt::Key_M: 821 case Qt::Key_M:
779 case Qt::Key_Return: 822 case Qt::Key_Return:
@@ -804,22 +847,26 @@ void SFCave :: keyReleaseEvent( QKeyEvent *e )
804 { 847 {
805 case Qt::Key_F9: 848 case Qt::Key_F9:
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:
824 e->ignore(); 871 e->ignore();
825 break; 872 break;
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
@@ -4,13 +4,16 @@
4#include <qpoint.h> 4#include <qpoint.h>
5#include <qrect.h> 5#include <qrect.h>
6#include <qtimer.h> 6#include <qtimer.h>
7#include <qlist.h>
7 8
8 9#include "random.h"
9 10
10#define MAPSIZE 52 11#define MAPSIZE 52
11#define BLOCKSIZE 6 12#define BLOCKSIZE 6
12#define TRAILSIZE 30 13#define TRAILSIZE 30
13 14
15
16
14class SFCave : public QMainWindow 17class SFCave : public QMainWindow
15{ 18{
16Q_OBJECT 19Q_OBJECT
@@ -20,6 +23,12 @@ public:
20 int sHeight; 23 int sHeight;
21 int segSize; 24 int segSize;
22 25
26 int currentSeed;
27
28 QList<int> replayList;
29 QListIterator<int> *replayIt;
30 bool replay;
31
23 int blockWidth; 32 int blockWidth;
24 int blockHeight; 33 int blockHeight;
25 int gapHeight; 34 int gapHeight;
@@ -79,6 +88,7 @@ public:
79 SFCave( int speed = 3, QWidget *p = 0, char *name = 0 ); 88 SFCave( int speed = 3, QWidget *p = 0, char *name = 0 );
80 ~SFCave(); 89 ~SFCave();
81 void start(); 90 void start();
91 void setSeed( int seed );
82 int nextInt( int range ); 92 int nextInt( int range );
83 void setUp(); 93 void setUp();
84 void handleGameSFCave(); 94 void handleGameSFCave();
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
@@ -1,8 +1,8 @@
1 TEMPLATE= app 1 TEMPLATE= app
2 CONFIG += qt warn_on release 2 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
7 INCLUDEPATH += $(OPIEDIR)/include 7 INCLUDEPATH += $(OPIEDIR)/include
8 DEPENDPATH+= $(OPIEDIR)/include 8 DEPENDPATH+= $(OPIEDIR)/include