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