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