1 /**********************************************************
2 * Version $Id: Mine_Sweeper.cpp 1921 2014-01-09 10:24:11Z oconrad $
3 *********************************************************/
4
5 ///////////////////////////////////////////////////////////
6 // //
7 // SAGA //
8 // //
9 // System for Automated Geoscientific Analyses //
10 // //
11 // Tool Library //
12 // //
13 // Mine_Sweeper //
14 // //
15 //-------------------------------------------------------//
16 // //
17 // Mine_Sweeper.cpp //
18 // //
19 // Copyright (C) 2003 Andre Ringeler //
20 // //
21 //-------------------------------------------------------//
22 // //
23 // This file is part of 'SAGA - System for Automated //
24 // Geoscientific Analyses'. SAGA is free software; you //
25 // can redistribute it and/or modify it under the terms //
26 // of the GNU General Public License as published by the //
27 // Free Software Foundation, either version 2 of the //
28 // License, or (at your option) any later version. //
29 // //
30 // SAGA is distributed in the hope that it will be //
31 // useful, but WITHOUT ANY WARRANTY; without even the //
32 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
33 // PARTICULAR PURPOSE. See the GNU General Public //
34 // License for more details. //
35 // //
36 // You should have received a copy of the GNU General //
37 // Public License along with this program; if not, see //
38 // <http://www.gnu.org/licenses/>. //
39 // //
40 //-------------------------------------------------------//
41 // //
42 // e-mail: aringel@gwdg.de //
43 // //
44 // contact: Andre Ringeler //
45 // //
46 // //
47 ///////////////////////////////////////////////////////////
48
49
50 ///////////////////////////////////////////////////////////
51 // //
52 // //
53 // //
54 ///////////////////////////////////////////////////////////
55
56 //---------------------------------------------------------
57 #include "Mine_Sweeper.h"
58
59 ///////////////////////////////////////////////////////////
60 // //
61 // Import Resourcen //
62 // //
63 ///////////////////////////////////////////////////////////
64
65 extern unsigned char mine_res[];
66 extern unsigned char mine_res_color[];
67 extern unsigned int SPRITE_SIZE;
68
69 ///////////////////////////////////////////////////////////
70 // //
71 // Defines //
72 // //
73 ///////////////////////////////////////////////////////////
74
75 #define FLAG 1
76 #define QUESTION 2
77
78 #define isBomb 1
79 #define isOpen 8
80 #define isBumm 16
81
82 #define SPRITE_CLOSE 0
83 #define SPRITE_FLAG 1
84 #define SPRITE_QUESTION 2
85 #define SPRITE_BOMB_BUMM 3
86 #define SPRITE_BOMB_NO 4
87 #define SPRITE_BOMB 5
88 #define SPRITE_OPEN 15
89
90 #define SPRITE_NUMMER(x) (15-x)
91
92 ///////////////////////////////////////////////////////////
93 // //
94 // //
95 // //
96 ///////////////////////////////////////////////////////////
97
98 //---------------------------------------------------------
CMine_Sweeper(void)99 CMine_Sweeper::CMine_Sweeper(void)
100 {
101 Set_Name (_TL("Mine Sweeper"));
102
103 Set_Author (_TL("Copyrights (c) 2003 by Andre Ringeler"));
104
105 Set_Description (_TW(
106 "A Mine Sweeper Clone\n"
107 "(created by Andre Ringeler).")
108 );
109
110 Parameters.Add_Grid_Output(
111 NULL , "GRID" , _TL("Grid"),
112 _TL("")
113 );
114
115 Parameters.Add_Choice(
116 NULL ,"LEVEL" ,_TL("Level"),
117 _TL("Game Level"),
118 _TW(
119 "Beginer|"
120 "Advanced|"
121 "Profi|") ,1
122 );
123 }
124
125 //---------------------------------------------------------
~CMine_Sweeper(void)126 CMine_Sweeper::~CMine_Sweeper(void)
127 {}
128
129
130 ///////////////////////////////////////////////////////////
131 // //
132 // //
133 // //
134 ///////////////////////////////////////////////////////////
135
136 //---------------------------------------------------------
MakeBoard(int level)137 bool CMine_Sweeper::MakeBoard(int level)
138 {
139 int i, x, y;
140 CSG_Colors Colors;
141
142 switch( level )
143 {
144 case 0: Mine_NX = 8; Mine_NY = 8; N_Mines=10;
145 break;
146
147 case 1: Mine_NX = 16; Mine_NY = 16; N_Mines=40;
148 break;
149
150 case 2: Mine_NX = 30; Mine_NY = 16; N_Mines=99;
151 break;
152 }
153
154 pInput = SG_Create_Grid(SG_DATATYPE_Int,SPRITE_SIZE*Mine_NX, SPRITE_SIZE*Mine_NY);
155 pInput->Set_Name(_TL("Mine Sweeper"));
156 Parameters("GRID")->Set_Value(pInput);
157
158 //-----------------------------------------------------
159 CSG_Parameter *pLUT = DataObject_Get_Parameter(pInput, "LUT");
160
161 if( pLUT && pLUT->asTable() )
162 {
163 pLUT->asTable()->Del_Records();
164
165 for(i=0; i<16; i++)
166 {
167 CSG_Table_Record *pRecord = pLUT->asTable()->Add_Record();
168
169 pRecord->Set_Value(0, SG_GET_RGB(mine_res_color[i*3], mine_res_color[i*3+1], mine_res_color[i*3+2]));
170 pRecord->Set_Value(3, i);
171 }
172
173 DataObject_Set_Parameter(pInput, pLUT);
174 DataObject_Set_Parameter(pInput, "COLORS_TYPE", 1); // Color Classification Type: Lookup Table
175 }
176
177 Colors.Set_Count(16);
178 for ( i=0;i<16; i++)
179 {
180 Colors.Set_Color(i, SG_GET_RGB(mine_res_color[i*3], mine_res_color[i*3+1], mine_res_color[i*3+2]));
181 }
182 DataObject_Set_Colors(pInput, Colors);
183 DataObject_Update(pInput, 0.0, 15.0, true);
184
185 //-----------------------------------------------------
186 for( y = 0; y < Mine_NY; y++)
187 for( x = 0; x < Mine_NX; x++)
188 {
189 SetSprite(x,y,SPRITE_CLOSE);
190 }
191
192 pInput->Set_Value(0, 0);
193
194 return true;
195 }
196
On_Execute(void)197 bool CMine_Sweeper::On_Execute(void)
198 {
199 MakeBoard(Parameters("LEVEL")->asInt());
200
201 GameBoard = (CSG_Grid *) new CSG_Grid(SG_DATATYPE_Int,Mine_NX,Mine_NY);
202 FlagBoard = (CSG_Grid *) new CSG_Grid(SG_DATATYPE_Int,Mine_NX,Mine_NY);
203
204 First_Click = true;
205 Time = NULL;
206
207 return( true );
208 }
209
210
On_Execute_Finish(void)211 bool CMine_Sweeper::On_Execute_Finish(void)
212 {
213 delete GameBoard;
214 delete FlagBoard;
215
216 if (Time) delete Time;
217
218 return true;
219 }
220
221
ResetBoard(int xpos,int ypos)222 void CMine_Sweeper::ResetBoard(int xpos, int ypos)
223 {
224 OpenFields = 0; MarkedMines = 0;
225
226 FlagBoard->Assign(); GameBoard->Assign();
227
228 if(Time) delete Time;
229
230 Make_GameBoard( xpos , ypos);
231
232 Time = new CTimer();
233 }
234
235 //---------------------------------------------------------
Get_Grid_Pos(int & x,int & y)236 bool CMine_Sweeper::Get_Grid_Pos(int &x, int &y)
237 {
238 bool bResult;
239
240 if( pInput && pInput->is_Valid() )
241 {
242 bResult = true;
243
244 //-------------------------------------------------
245 x = (int)(0.5 + (Get_xPosition() - pInput->Get_XMin()) / pInput->Get_Cellsize());
246
247 if( x < 0 )
248 {
249 bResult = false;
250 x = 0;
251 }
252 else if( x >= pInput->Get_NX() )
253 {
254 bResult = false;
255 x = pInput->Get_NX() - 1;
256 }
257
258 //-------------------------------------------------
259 y = (int)(0.5 + (Get_yPosition() - pInput->Get_YMin()) / pInput->Get_Cellsize());
260
261 if( y < 0 )
262 {
263 bResult = false;
264 y = 0;
265 }
266 else if( y >= pInput->Get_NY() )
267 {
268 bResult = false;
269 y = pInput->Get_NY() - 1;
270 }
271
272 return( bResult );
273 }
274
275 //-----------------------------------------------------
276 x = 0;
277 y = 0;
278
279 return( false );
280 }
281
282
On_Execute_Position(CSG_Point ptWorld,TSG_Tool_Interactive_Mode Mode)283 bool CMine_Sweeper::On_Execute_Position(CSG_Point ptWorld, TSG_Tool_Interactive_Mode Mode)
284 {
285 int ok = true;
286
287 int time;
288 int redraw = false;
289 int xpos; int ypos;
290
291 if( !Get_Grid_Pos(xpos, ypos) )
292 return( false );
293
294 xpos/=SPRITE_SIZE; ypos/=SPRITE_SIZE;
295
296 ypos=Mine_NY-1-ypos;
297
298 switch( Mode )
299 {
300 default:
301 return( false );
302
303 case TOOL_INTERACTIVE_LDOWN:
304 if(First_Click)
305 {
306 ResetBoard(xpos, ypos);
307 First_Click=false;
308 }
309
310 ok = Play(xpos, ypos, false);
311 redraw = true;
312 break;
313
314 case TOOL_INTERACTIVE_RDOWN:
315 Mark(xpos, ypos);
316 redraw = true;
317 break;
318 }
319
320 if (redraw)
321 {
322 if(ok)
323 {
324 Show_GameBoard(false);
325
326 time= Time->Time();
327
328 Message_Fmt("\nyou are a winner :-)\nTime:%ds\nMines:%d\n",time,N_Mines-MarkedMines);
329
330 if (OpenFields == Mine_NX*Mine_NY-N_Mines )
331 {
332 Message_Dlg(CSG_String::Format("you are a winner :-)\nTime:%ds\nMines:%d\n",time,N_Mines-MarkedMines));
333
334 Show_GameBoard(true);
335
336 First_Click=true;
337 }
338 }
339 else
340 {
341 Show_GameBoard(true);
342
343 Message_Dlg(CSG_String::Format("you are a loser :-(\nTime:%ds\nMines:%d\n",time,N_Mines-MarkedMines));
344
345 First_Click=true;
346 }
347 }
348 return true;
349 }
350
351
352
Make_GameBoard(int xpos,int ypos)353 void CMine_Sweeper::Make_GameBoard(int xpos,int ypos)
354 {
355 int mines = 0;
356
357 srand( (unsigned)time( NULL ) );
358
359 while(mines < N_Mines)
360 {
361 int mx,my;
362
363 mx = rand()%Mine_NX;
364 my = rand()%Mine_NY;
365
366 if( !(GameBoard->asInt(mx, my) & isBomb) && !((mx==xpos)&&(my==ypos)) )
367 {
368 GameBoard->Set_Value(mx,my,isBomb);
369 mines ++;
370 }
371 }
372 }
373
374
Show_GameBoard(bool ShowMines)375 void CMine_Sweeper::Show_GameBoard(bool ShowMines)
376 {
377 int x,y;
378
379 if (ShowMines)
380 {
381 for( y = 0; y < Mine_NY; y++)
382 for( x = 0; x < Mine_NX; x++)
383 {
384 if(GameBoard->asInt(x, y) & isBomb)
385 {
386 if (FlagBoard->asInt(x,y) == FLAG)
387 SetSprite(x,y,SPRITE_FLAG);
388 else
389 SetSprite(x,y,SPRITE_BOMB);
390 }
391 else
392 {
393 if (GameBoard->asInt(x, y) == isOpen )
394 SetSprite(x,y,SPRITE_NUMMER(Get_Number_of_Bombs(x,y)));
395 else
396 SetSprite(x,y,SPRITE_CLOSE);
397 }
398
399 if (GameBoard->asInt(x, y) & isBumm) SetSprite(x,y,SPRITE_BOMB_BUMM);
400
401 if ( !(GameBoard->asInt(x, y) & isBomb) && (FlagBoard->asInt(x,y) == FLAG))
402 SetSprite(x,y,SPRITE_BOMB_NO);
403 }
404 }
405 else
406 for( y = 0; y < Mine_NY; y++)
407 for( x = 0; x < Mine_NX; x++)
408 {
409 if(GameBoard->asInt(x, y) == isOpen)
410 {
411 SetSprite(x,y,SPRITE_NUMMER(Get_Number_of_Bombs(x,y)));
412 }
413 else
414 {
415 if(FlagBoard->asInt(x,y))
416 SetSprite(x,y,FlagBoard->asInt(x,y));
417 else
418 SetSprite(x,y,SPRITE_CLOSE);
419 }
420 }
421
422 DataObject_Update(pInput, 0.0, 15.0);
423 }
424
425
SetSprite(int xpos,int ypos,int nr)426 void CMine_Sweeper::SetSprite(int xpos, int ypos, int nr)
427 {
428 unsigned int x,y;
429
430 for(y=0;y<SPRITE_SIZE;y++)
431 for(x=0;x<SPRITE_SIZE;x++)
432 pInput->Set_Value( xpos * SPRITE_SIZE + x, pInput->Get_NY() - ypos * SPRITE_SIZE - y -1,
433 (double)mine_res[ y * SPRITE_SIZE + x + nr * SPRITE_SIZE * SPRITE_SIZE]);
434 }
435
436
Get_Number_of_Bombs(int xpos,int ypos)437 int CMine_Sweeper::Get_Number_of_Bombs(int xpos, int ypos)
438 {
439 int i;
440 int number = 0;
441
442 for( i = 0; i<8; i++)
443 if (GameBoard->is_InGrid(pInput->Get_System().Get_xTo(i,xpos),pInput->Get_System().Get_yTo(i,ypos)))
444 if (GameBoard->asInt(pInput->Get_System().Get_xTo(i,xpos),pInput->Get_System().Get_yTo(i,ypos)) & isBomb)
445 number ++;
446
447 return number;
448 }
449
Play(int xpos,int ypos,bool computer_move)450 bool CMine_Sweeper::Play(int xpos, int ypos,bool computer_move)
451 {
452 int i;
453
454 if ( (!GameBoard->is_InGrid(xpos,ypos))||
455 (FlagBoard->asInt(xpos, ypos)==1) ||
456 ((GameBoard->asInt(xpos, ypos)) & isBomb && (computer_move))
457 )
458 {
459 return true;
460 }
461
462 if ( (GameBoard->asInt(xpos, ypos)) & isBomb && (!computer_move) )
463 {
464 GameBoard->Set_Value(xpos, ypos,isBomb|isBumm);
465 return false;
466 }
467
468 if ( GameBoard->asInt(xpos, ypos) == 0 )
469 {
470 GameBoard->Set_Value(xpos, ypos, isOpen);
471
472 OpenFields ++;
473
474 if (Get_Number_of_Bombs(xpos, ypos) )
475 return true;
476
477 for( i = 0; i<8; i++)
478 Play(pInput->Get_System().Get_xTo(i,xpos),pInput->Get_System().Get_yTo(i,ypos) ,true);
479 }
480 return true;
481 }
482
483
Mark(int xpos,int ypos)484 void CMine_Sweeper::Mark(int xpos, int ypos)
485 {
486 int val;
487
488 val = FlagBoard->asInt(xpos , ypos);
489
490 if (val == FLAG) MarkedMines --;
491
492 val ++; val%=3;
493
494 if (val == FLAG) MarkedMines ++ ;
495
496 FlagBoard->Set_Value(xpos, ypos, val);
497 }
498
499
CTimer()500 CTimer::CTimer()
501 {
502 time(&starttime);
503 }
504
~CTimer()505 CTimer::~CTimer()
506 {
507 }
508
Time()509 int CTimer::Time()
510 {
511 time_t nowtime;
512
513 time(&nowtime);
514
515 return (int) (nowtime-starttime);
516 }
517