1 #include <sys/time.h>
2 #include <signal.h>
3 #include <fcntl.h>
4 #include <X11/Xlib.h>
5 #include "xmines.h"
6
7 #define Neighbors(func, x, y) func(x-1,y-1);func(x,y-1);func(x+1,y-1);\
8 func(x-1,y ); func(x+1,y );\
9 func(x-1,y+1);func(x,y+1);func(x+1,y+1)
10
11
12 void fillBlanks();
13
14 #define AWIDTH 10
15 #define AHEIGHT 10
16
17 #define MISSMARKED 10
18 #define BOOM 11
19 /*
20 bit 5 : Marked
21 bit 4 : Cover/uncovered
22 bit 3-0 : number of mines in adjoining cells
23 */
24
25 int minefield[50][20];
26 int numcells = 0;
27 int nummines = 10;
28 int numuncovered = 0;
29 int nummarked;
30
31 int done;
32 int interval;
33 int height;
34 int width;
35
36 int start_time;
37
ticktock()38 void ticktock()
39 {
40 }
41
delay(time)42 delay(time)
43 int time;
44 {
45 struct itimerval value,ovalue;
46
47 signal(SIGALRM,ticktock);
48 value.it_interval.tv_sec = time/1000;
49 value.it_interval.tv_usec = (time %1000)*1000;
50 value.it_value.tv_sec = time/1000;
51 value.it_value.tv_usec = (time %1000)*1000;
52 setitimer(ITIMER_REAL,&value,&ovalue);
53 pause();
54 value.it_interval.tv_sec = 0;
55 value.it_interval.tv_usec = 0;
56 value.it_value.tv_sec = 0;
57 value.it_value.tv_usec = 0;
58 setitimer(ITIMER_REAL,&value,&ovalue);
59 }
60
61
setdoneflag(i)62 setdoneflag(i)
63 {
64 done = i;
65 }
66
67
setup_signals()68 setup_signals()
69 {
70 int flags;
71 extern Display *display;
72
73 signal(SIGIO, ticktock);
74
75 flags = fcntl(ConnectionNumber(display), F_GETFL, 0);
76 /* flags |= FASYNC; */
77 fcntl(ConnectionNumber(display), F_SETFL, flags);
78 fcntl(ConnectionNumber(display), F_SETOWN, getpid());
79 }
80
main(argc,argv)81 main(argc,argv)
82 int argc;
83 char **argv;
84 {
85 openScores();
86
87 parseOptions(argc,argv);
88 nummines = 99;
89 height = 16;
90 width = 30;
91 XStuff(argc,argv);
92
93 srandom(getpid());
94 setup_signals();
95
96 while(1)
97 {
98 nummarked = 0;
99 numcells = height*width;
100 numuncovered = 0;
101 newscreen();
102 draw_screen();
103 done = 0;
104 start_time = 0;
105 while(!done)
106 {
107 CheckforEvent();
108 if(numuncovered)
109 {
110 if (start_time == 0) start_time = time(0);
111 show_score(0);
112 }
113 delay(100);
114 }
115 if(done == 1)
116 {
117 newScore(getscore());
118 }
119 else
120 {
121 showallmines();
122 }
123 show_high_scores(0);
124 }
125 }
126
getscore()127 getscore()
128 {
129 static int frozen = -1;
130 if (done) {
131 if (frozen < 0) {
132 frozen = (start_time ? time(0) - start_time : 0);
133 }
134 return frozen;
135 }
136 else {
137 frozen = -1;
138 return (start_time ? time(0) - start_time : 0);
139 }
140 }
141
getminesleft()142 getminesleft()
143 {
144 return nummines - nummarked;
145 }
146
147
cntmines(x,y)148 cntmines(x,y)
149 {
150 return IsMine(x-1,y-1) + IsMine(x-1,y) + IsMine(x-1,y+1) +
151 IsMine(x,y-1) + IsMine(x,y+1) +
152 IsMine(x+1,y-1) + IsMine(x+1,y) + IsMine(x+1,y+1);
153 }
154
Number(x,y)155 Number(x,y)
156 {
157 return minefield[x][y] & 0xf;
158 }
159
MissmarkCell(x,y)160 MissmarkCell(x,y)
161 {
162 minefield[x][y] = MISSMARKED;
163 }
164
MarkCell(x,y)165 MarkCell(x,y)
166 {
167 if(InArray(x,y) && !IsVisible(x,y))
168 {
169 if(IsMarked(x,y))
170 {
171 minefield[x][y] &= ~MARKED;
172 nummarked--;
173 }
174 else
175 {
176 minefield[x][y] |= MARKED;
177 nummarked++;
178 }
179 }
180 DrawCell(x,y);
181 }
182
BoomCell(x,y)183 BoomCell(x,y)
184 {
185 minefield[x][y] = BOOM;
186 DrawCell(x,y);
187 }
188
UncoverCell(x,y)189 UncoverCell(x,y)
190 {
191 minefield[x][y] &= 0xf;
192 numuncovered++;
193 }
194
WriteCell(x,y,val)195 WriteCell(x,y,val)
196 {
197 minefield[x][y] = val;
198 }
199
ReadCell(x,y)200 ReadCell(x,y)
201 {
202 return minefield[x][y];
203 }
204
newscreen()205 newscreen()
206 {
207 int i,j,k;
208 int x,y;
209
210 for(i=0; i < width; i++)
211 {
212 for(j=0; j < height; j++)
213 {
214 WriteCell(i,j,0);
215 }
216 }
217 for(k=0; k < nummines; k++)
218 {
219 do
220 {
221 x = random() % width;
222 y = random() % height;
223 } while(IsMine(x,y));
224 WriteCell(x,y,MINE + COVERED);
225 }
226 for(i=0; i < width; i++)
227 {
228 for(j=0; j < height; j++)
229 {
230 if(!IsMine(i,j))
231 {
232 WriteCell(i,j,COVERED + cntmines(i,j));
233 }
234 }
235 }
236 }
237
showallmines()238 showallmines()
239 {
240 int x,y;
241
242 for(x=0; x < width; x++)
243 {
244 for(y=0; y < height; y++)
245 {
246 if(!IsVisible(x,y))
247 {
248 if(!IsMine(x,y) && IsMarked(x,y))
249 {
250 MissmarkCell(x,y);
251 DrawCell(x,y);
252 }
253 if(IsMine(x,y) && !IsMarked(x,y))
254 {
255 UncoverCell(x,y);
256 DrawCell(x,y);
257 }
258 }
259 }
260 }
261 }
262
263
Highlight(x,y)264 Highlight(x,y)
265 {
266 if(!IsMarked(x,y) && !IsVisible(x,y))
267 {
268 DrawHighlight(x,y);
269 }
270 }
271
unHighlight(x,y)272 unHighlight(x,y)
273 {
274 if(!IsMarked(x,y) && !IsVisible(x,y))
275 {
276 DrawCell(x,y);
277 }
278 }
279
280
Show(x,y)281 void Show(x,y)
282 int x,y;
283 {
284 if(InArray(x,y) && !IsVisible(x,y) && !IsMarked(x,y))
285 {
286 if(IsMine(x,y))
287 {
288 BoomCell(x,y);
289 DrawCell(x,y);
290 setdoneflag(-1);
291 }
292 else
293 {
294 UncoverCell(x,y);
295 fillBlanks(x,y);
296 DrawCell(x,y);
297 if(numuncovered == numcells - nummines)
298 {
299 setdoneflag(1);
300 }
301 }
302 }
303 }
304
305 /* fill blanks starting at x, y */
306 void
fillBlanks(x,y)307 fillBlanks( x, y )
308 int x,y;
309 {
310 if (IsBlank (x, y)) {
311 Neighbors (Show, x, y);
312 }
313 }
314
315 /* highlight neighbors which are invisible (two button down) */
316 void
highlightInvisible(x,y)317 highlightInvisible(x,y)
318 int x, y;
319 {
320 Highlight(x,y);
321 Neighbors( Highlight, x, y);
322 }
323
unhighlightInvisible(x,y)324 unhighlightInvisible(x,y)
325 int x, y;
326 {
327 unHighlight(x,y);
328 Neighbors( unHighlight, x, y);
329 }
330
331
332 int
foundMines(x,y)333 foundMines(x,y)
334 int x,y;
335 {
336 int visibleMineCount;
337
338 visibleMineCount = 0;
339
340 Neighbors (visibleMineCount += IsMarked, x, y);
341
342 return visibleMineCount;
343 }
344
345
346 /* fill numbers if all mines are already discovered (two button up) */
347 void
fillNumbers(x,y)348 fillNumbers( x, y )
349 int x,y;
350 {
351 if(IsVisible(x, y))
352 {
353 if (foundMines (x, y) == Number (x, y))
354 {
355 Neighbors (Show, x, y);
356 }
357 }
358 unhighlightInvisible(x,y);
359 }
360
361