summaryrefslogtreecommitdiff
path: root/noncore/games/zsame/StoneField.cpp
authorzecke <zecke>2004-10-15 01:48:45 (UTC)
committer zecke <zecke>2004-10-15 01:48:45 (UTC)
commitfefeafe35f8dac30f4baab9e3bff8e2ffbd1afd0 (patch) (unidiff)
treea59a3bd9b5434657ee014dd6bbf7fbb50f5994d0 /noncore/games/zsame/StoneField.cpp
parent85ab1a8cc3935538cc1f33fef7c94ba31accb53e (diff)
downloadopie-fefeafe35f8dac30f4baab9e3bff8e2ffbd1afd0.zip
opie-fefeafe35f8dac30f4baab9e3bff8e2ffbd1afd0.tar.gz
opie-fefeafe35f8dac30f4baab9e3bff8e2ffbd1afd0.tar.bz2
Fix #1450 to clear the 'bonus' for removing every stone in the game
Diffstat (limited to 'noncore/games/zsame/StoneField.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/zsame/StoneField.cpp4
1 files changed, 4 insertions, 0 deletions
diff --git a/noncore/games/zsame/StoneField.cpp b/noncore/games/zsame/StoneField.cpp
index 49d8eca..56e9dc5 100644
--- a/noncore/games/zsame/StoneField.cpp
+++ b/noncore/games/zsame/StoneField.cpp
@@ -1,390 +1,394 @@
1/* 1/*
2 * ksame 0.4 - simple Game 2 * ksame 0.4 - simple Game
3 * Copyright (C) 1997,1998 Marcus Kreutzberger 3 * Copyright (C) 1997,1998 Marcus Kreutzberger
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or 7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version. 8 * (at your option) any later version.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, 10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * 18 *
19 */ 19 */
20 20
21#include "StoneField.h" 21#include "StoneField.h"
22#include <assert.h> 22#include <assert.h>
23 23
24StoneFieldState::StoneFieldState(const StoneField &stonefield) 24StoneFieldState::StoneFieldState(const StoneField &stonefield)
25{ 25{
26 field=new unsigned char[stonefield.maxstone]; 26 field=new unsigned char[stonefield.maxstone];
27 for (int i=0;i<stonefield.maxstone;i++) 27 for (int i=0;i<stonefield.maxstone;i++)
28 field[i]=stonefield.field[i].color; 28 field[i]=stonefield.field[i].color;
29 29
30 colors=stonefield.colors; 30 colors=stonefield.colors;
31 board=stonefield.board; 31 board=stonefield.board;
32 score=stonefield.score; 32 score=stonefield.score;
33 gameover=stonefield.gameover; 33 gameover=stonefield.gameover;
34} 34}
35 35
36StoneFieldState::~StoneFieldState() { 36StoneFieldState::~StoneFieldState() {
37 delete[] field; 37 delete[] field;
38} 38}
39 39
40void 40void
41StoneFieldState::restore(StoneField &stonefield) const { 41StoneFieldState::restore(StoneField &stonefield) const {
42 for (int i=0;i<stonefield.maxstone;i++) { 42 for (int i=0;i<stonefield.maxstone;i++) {
43 stonefield.field[i].color=field[i]; 43 stonefield.field[i].color=field[i];
44 stonefield.field[i].changed=true; 44 stonefield.field[i].changed=true;
45 stonefield.field[i].marked=false; 45 stonefield.field[i].marked=false;
46 } 46 }
47 47
48 stonefield.colors=colors; 48 stonefield.colors=colors;
49 stonefield.board=board; 49 stonefield.board=board;
50 stonefield.score=score; 50 stonefield.score=score;
51 stonefield.marked=0; 51 stonefield.marked=0;
52 stonefield.gameover=gameover; 52 stonefield.gameover=gameover;
53} 53}
54 54
55StoneField::StoneField(int width, int height, 55StoneField::StoneField(int width, int height,
56 int colors, unsigned int board, 56 int colors, unsigned int board,
57 bool undoenabled) 57 bool undoenabled)
58{ 58{
59// Q_ASSERT(width>0); 59// Q_ASSERT(width>0);
60// Q_ASSERT(height>0); 60// Q_ASSERT(height>0);
61 61
62 if (undoenabled) undolist=new QList<StoneFieldState>; 62 if (undoenabled) undolist=new QList<StoneFieldState>;
63 else undolist=0; 63 else undolist=0;
64 64
65 sizex=width; 65 sizex=width;
66 sizey=height; 66 sizey=height;
67 maxstone=sizex*sizey; 67 maxstone=sizex*sizey;
68 field=new Stone[maxstone]; 68 field=new Stone[maxstone];
69 newGame(board,colors); 69 newGame(board,colors);
70 m_gotBonus= false; 70 m_gotBonus= false;
71} 71}
72 72
73StoneField::~StoneField() { 73StoneField::~StoneField() {
74 delete[] field; 74 delete[] field;
75 delete undolist; 75 delete undolist;
76// kdDebug() << "~StoneField\n" << endl; 76// kdDebug() << "~StoneField\n" << endl;
77} 77}
78 78
79int 79int
80StoneField::width() const { 80StoneField::width() const {
81 return sizex; 81 return sizex;
82} 82}
83 83
84int 84int
85StoneField::height() const { 85StoneField::height() const {
86 return sizey; 86 return sizey;
87} 87}
88 88
89void 89void
90StoneField::newGame(unsigned int board,int colors) { 90StoneField::newGame(unsigned int board,int colors) {
91// kdDebug() << "StoneField::newgame board " 91// kdDebug() << "StoneField::newgame board "
92// << board << " colors " << colors << endl; 92// << board << " colors " << colors << endl;
93 if (colors<1) colors=3; 93 if (colors<1) colors=3;
94 if (colors>7) colors=7; 94 if (colors>7) colors=7;
95 this->colors=colors; 95 this->colors=colors;
96 this->board=board; 96 this->board=board;
97 reset(); 97 reset();
98} 98}
99 99
100void 100void
101StoneField::reset() { 101StoneField::reset() {
102 random.setSeed(board); 102 random.setSeed(board);
103 103
104 Stone *stone=field; 104 Stone *stone=field;
105 for (int i=0;i<maxstone;i++,stone++) { 105 for (int i=0;i<maxstone;i++,stone++) {
106 stone->color=1+random.getLong(colors); 106 stone->color=1+random.getLong(colors);
107 stone->marked=false; 107 stone->marked=false;
108 stone->changed=true; 108 stone->changed=true;
109 } 109 }
110 110
111 gameover=-1; 111 gameover=-1;
112 score=0; 112 score=0;
113 marked=0; 113 marked=0;
114 114
115 if (undolist) { 115 if (undolist) {
116 undolist->setAutoDelete(true); 116 undolist->setAutoDelete(true);
117 undolist->clear(); 117 undolist->clear();
118 } 118 }
119 119
120 120
121 int c[7]; 121 int c[7];
122 int j; 122 int j;
123 for (j=0;j<7;j++) c[j]=0; 123 for (j=0;j<7;j++) c[j]=0;
124 124
125 for (j=0,stone=field;j<maxstone;j++,stone++) { 125 for (j=0,stone=field;j<maxstone;j++,stone++) {
126 c[stone->color]++; 126 c[stone->color]++;
127 } 127 }
128// kdDebug() << "red " << c[1] << endl; 128// kdDebug() << "red " << c[1] << endl;
129// kdDebug() << "blue " << c[2] << endl; 129// kdDebug() << "blue " << c[2] << endl;
130// kdDebug() << "yellow " << c[3] << endl; 130// kdDebug() << "yellow " << c[3] << endl;
131// kdDebug() << "green " << c[4] << endl; 131// kdDebug() << "green " << c[4] << endl;
132 132
133} 133}
134 134
135int 135int
136StoneField::map(int x,int y) { 136StoneField::map(int x,int y) {
137 assert (!(x<0||y<0||x>=sizex||y>=sizey)); 137 assert (!(x<0||y<0||x>=sizex||y>=sizey));
138 return x+y*sizex; 138 return x+y*sizex;
139} 139}
140 140
141int 141int
142StoneField::mark(int x,int y,bool force) { 142StoneField::mark(int x,int y,bool force) {
143 int index=map(x,y); 143 int index=map(x,y);
144 144
145 if (index<0) { 145 if (index<0) {
146 unmark(); 146 unmark();
147 return 0; 147 return 0;
148 } 148 }
149 149
150 if (field[index].marked) return -1; 150 if (field[index].marked) return -1;
151 unmark(); 151 unmark();
152 152
153 mark(index,field[index].color); 153 mark(index,field[index].color);
154 154
155 if (marked==1&&!force) { 155 if (marked==1&&!force) {
156 field[index].marked=false; 156 field[index].marked=false;
157 marked=0; 157 marked=0;
158 } 158 }
159 return marked; 159 return marked;
160} 160}
161 161
162void 162void
163StoneField::mark(int index,unsigned char color) { 163StoneField::mark(int index,unsigned char color) {
164 if ( index<0 || index>=maxstone ) return; 164 if ( index<0 || index>=maxstone ) return;
165 165
166 Stone &stone=field[index]; 166 Stone &stone=field[index];
167 167
168 if (stone.marked) return; 168 if (stone.marked) return;
169 169
170 if (!stone.color || stone.color!=color) return; 170 if (!stone.color || stone.color!=color) return;
171 171
172 stone.changed=true; 172 stone.changed=true;
173 stone.marked=true; 173 stone.marked=true;
174 marked++; 174 marked++;
175 175
176 // mark left 176 // mark left
177 if ((index%sizex)!=0) mark(index-1,color); 177 if ((index%sizex)!=0) mark(index-1,color);
178 // mark right 178 // mark right
179 if (((index+1)%sizex)!=0) mark(index+1,color); 179 if (((index+1)%sizex)!=0) mark(index+1,color);
180 // mark upward 180 // mark upward
181 if (index>=sizex) mark(index-sizex,color); 181 if (index>=sizex) mark(index-sizex,color);
182 // mark downward 182 // mark downward
183 if (index<(sizex-1)*sizey) mark(index+sizex,color); 183 if (index<(sizex-1)*sizey) mark(index+sizex,color);
184} 184}
185 185
186void 186void
187StoneField::unmark() { 187StoneField::unmark() {
188 if (!marked) return; 188 if (!marked) return;
189 189
190 Stone *stone=field; 190 Stone *stone=field;
191 for (int i=0;i<maxstone;i++,stone++) { 191 for (int i=0;i<maxstone;i++,stone++) {
192 stone->marked=false; 192 stone->marked=false;
193 stone->changed=true; 193 stone->changed=true;
194 } 194 }
195 marked=0; 195 marked=0;
196} 196}
197 197
198int 198int
199StoneField::remove(int x,int y,bool force) { 199StoneField::remove(int x,int y,bool force) {
200 int index=map(x,y); 200 int index=map(x,y);
201 201
202 if (index<0) return 0; 202 if (index<0) return 0;
203 203
204 if (!field[index].marked) { 204 if (!field[index].marked) {
205 mark(x,y,force); 205 mark(x,y,force);
206 } 206 }
207 207
208 if (!marked) return 0; 208 if (!marked) return 0;
209 209
210 // remove a single stone?? 210 // remove a single stone??
211 if (marked==1&&!force) return 0; 211 if (marked==1&&!force) return 0;
212 212
213 // add current field to undolist 213 // add current field to undolist
214 if (undolist) 214 if (undolist)
215 undolist->append(new StoneFieldState(*this)); 215 undolist->append(new StoneFieldState(*this));
216 216
217 // increase score 217 // increase score
218 if (marked>2) 218 if (marked>2)
219 score+=(marked-2)*(marked-2); 219 score+=(marked-2)*(marked-2);
220 220
221 // remove marked stones 221 // remove marked stones
222 Stone *stone=field; 222 Stone *stone=field;
223 for (int i=0;i<maxstone;i++,stone++) { 223 for (int i=0;i<maxstone;i++,stone++) {
224 if (stone->marked) { 224 if (stone->marked) {
225 stone->color=0; 225 stone->color=0;
226 stone->changed=true; 226 stone->changed=true;
227 stone->marked=false; 227 stone->marked=false;
228 } 228 }
229 } 229 }
230 int removed=marked; 230 int removed=marked;
231 marked=0; 231 marked=0;
232 232
233 for (int col=0;col<sizex;col++) { 233 for (int col=0;col<sizex;col++) {
234 int i1=col+maxstone-sizex; 234 int i1=col+maxstone-sizex;
235 while ( i1>=0 && field[i1].color ) i1-=sizex; 235 while ( i1>=0 && field[i1].color ) i1-=sizex;
236 int i2=i1; 236 int i2=i1;
237 while (i2>=0) { 237 while (i2>=0) {
238 while ( i2>=0 && !field[i2].color ) i2-=sizex; 238 while ( i2>=0 && !field[i2].color ) i2-=sizex;
239 while ( i2>=0 && field[i2].color ) { 239 while ( i2>=0 && field[i2].color ) {
240 field[i1].color=field[i2].color; 240 field[i1].color=field[i2].color;
241 field[i1].changed=true; 241 field[i1].changed=true;
242 field[i2].color=0; 242 field[i2].color=0;
243 field[i2].changed=true; 243 field[i2].changed=true;
244 i1-=sizex; 244 i1-=sizex;
245 i2-=sizex; 245 i2-=sizex;
246 } 246 }
247 } 247 }
248 } 248 }
249 249
250 // find the last column that has something 250 // find the last column that has something
251 int lastcol = sizex; 251 int lastcol = sizex;
252 while (lastcol > 0 && !field[map(lastcol-1, sizey-1)].color) { 252 while (lastcol > 0 && !field[map(lastcol-1, sizey-1)].color) {
253 lastcol--; 253 lastcol--;
254 } 254 }
255 255
256 for (int col=0;col<lastcol-1;) { 256 for (int col=0;col<lastcol-1;) {
257 bool empty = true; 257 bool empty = true;
258 for (int row = 0; row < sizey; row++) 258 for (int row = 0; row < sizey; row++)
259 if (field[map(col, row)].color) { 259 if (field[map(col, row)].color) {
260 empty = false; 260 empty = false;
261 break; 261 break;
262 } 262 }
263 if (!empty) { 263 if (!empty) {
264 col++; 264 col++;
265 continue; 265 continue;
266 } 266 }
267 int nextfullcol = col + 1; 267 int nextfullcol = col + 1;
268 while (nextfullcol < sizex && 268 while (nextfullcol < sizex &&
269 !field[map(nextfullcol, sizey - 1)].color) 269 !field[map(nextfullcol, sizey - 1)].color)
270 nextfullcol++; 270 nextfullcol++;
271 271
272 if (nextfullcol > sizex - 1) 272 if (nextfullcol > sizex - 1)
273 break; // we're ready 273 break; // we're ready
274 274
275 for (int row=0; row < sizey; row++) { 275 for (int row=0; row < sizey; row++) {
276 int source = map(nextfullcol, row); 276 int source = map(nextfullcol, row);
277 int dest = map(col, row); 277 int dest = map(col, row);
278 field[dest].color=field[source].color; 278 field[dest].color=field[source].color;
279 field[dest].changed=true; 279 field[dest].changed=true;
280 field[source].color=0; 280 field[source].color=0;
281 field[source].changed=true; 281 field[source].changed=true;
282 } 282 }
283 } 283 }
284 284
285 // add a bonus, if field is empty 285 // add a bonus, if field is empty
286 if (!field[map(0, sizey-1)].color) { 286 if (!field[map(0, sizey-1)].color) {
287 score+=1000; 287 score+=1000;
288 m_gotBonus= true; 288 m_gotBonus= true;
289 } 289 }
290 290
291 // gameover is undefined 291 // gameover is undefined
292 gameover=-1; 292 gameover=-1;
293 return removed; 293 return removed;
294} 294}
295 295
296bool StoneField::undoPossible() const { 296bool StoneField::undoPossible() const {
297 return !(!undolist||undolist->isEmpty()); 297 return !(!undolist||undolist->isEmpty());
298} 298}
299 299
300int 300int
301StoneField::undo(int count) { 301StoneField::undo(int count) {
302 if (!undoPossible()) 302 if (!undoPossible())
303 return 0; 303 return 0;
304 if (count <= 0) 304 if (count <= 0)
305 return 0; 305 return 0;
306 int undocount=1; 306 int undocount=1;
307 StoneFieldState *state=0; 307 StoneFieldState *state=0;
308 undolist->setAutoDelete(true); 308 undolist->setAutoDelete(true);
309 while (--count>0) { 309 while (--count>0) {
310 if (undolist->count()==1) break; 310 if (undolist->count()==1) break;
311 undolist->removeLast(); 311 undolist->removeLast();
312 undocount++; 312 undocount++;
313 } 313 }
314 state=undolist->getLast(); 314 state=undolist->getLast();
315// Q_ASSERT(state); 315// Q_ASSERT(state);
316 state->restore(*this); 316 state->restore(*this);
317 undolist->removeLast(); 317 undolist->removeLast();
318 return undocount; 318 return undocount;
319} 319}
320 320
321bool 321bool
322StoneField::isGameover() const { 322StoneField::isGameover() const {
323 register int i=maxstone-1;; 323 register int i=maxstone-1;;
324 register unsigned char color; 324 register unsigned char color;
325 325
326 if (gameover>=0) return (bool)gameover; 326 if (gameover>=0) return (bool)gameover;
327 // kdDebug() << "-->gameover" << endl; 327 // kdDebug() << "-->gameover" << endl;
328 328
329 while (i>=0) { 329 while (i>=0) {
330 // kdDebug() << i << " " << field[i].color << endl; 330 // kdDebug() << i << " " << field[i].color << endl;
331 // ignore empty fields 331 // ignore empty fields
332 while ( i>=0 && field[i].color==0 ) i--; 332 while ( i>=0 && field[i].color==0 ) i--;
333 // Wenn Stein gefunden, 333 // Wenn Stein gefunden,
334 // dann die Nachbarn auf gleiche Farbe pruefen. 334 // dann die Nachbarn auf gleiche Farbe pruefen.
335 while ( i>=0 && (color=field[i].color) ) { 335 while ( i>=0 && (color=field[i].color) ) {
336 // check left 336 // check left
337 if ( (i%sizex)!=0 && field[i-1].color==color) 337 if ( (i%sizex)!=0 && field[i-1].color==color)
338 goto check_gameover; 338 goto check_gameover;
339 // check upward 339 // check upward
340 if ( i>=sizex && field[i-sizex].color==color) 340 if ( i>=sizex && field[i-sizex].color==color)
341 goto check_gameover; 341 goto check_gameover;
342 i--; 342 i--;
343 } 343 }
344 } 344 }
345 check_gameover: 345 check_gameover:
346 gameover=(i<0); 346 gameover=(i<0);
347 // kdDebug() << "<--gameover" << endl; 347 // kdDebug() << "<--gameover" << endl;
348 return (bool)gameover; 348 return (bool)gameover;
349} 349}
350 350
351bool StoneField::gotBonus() const { 351bool StoneField::gotBonus() const {
352 return m_gotBonus; 352 return m_gotBonus;
353} 353}
354 354
355void StoneField::clearBonus() {
356 m_gotBonus = false;
357}
358
355int 359int
356StoneField::getBoard() const { 360StoneField::getBoard() const {
357 return board; 361 return board;
358} 362}
359 363
360int 364int
361StoneField::getScore() const { 365StoneField::getScore() const {
362 return score; 366 return score;
363} 367}
364 368
365int 369int
366StoneField::getColors() const { 370StoneField::getColors() const {
367 return colors; 371 return colors;
368} 372}
369 373
370int 374int
371StoneField::getMarked() const { 375StoneField::getMarked() const {
372 return marked; 376 return marked;
373} 377}
374 378
375int 379int
376StoneField::getFieldSize() const { 380StoneField::getFieldSize() const {
377 return maxstone; 381 return maxstone;
378} 382}
379 383
380struct Stone * 384struct Stone *
381StoneField::getField() const { 385StoneField::getField() const {
382 return field; 386 return field;
383} 387}
384 388
385 389
386 390
387 391
388 392
389 393
390 394