Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
31 | halyavin | 1 | /******************************************************************************* |
2 | |||
3 | MenuetOS MineSweeper |
||
4 | Copyright (C) 2003 Ivan Poddubny |
||
5 | |||
6 | This program is free software; you can redistribute it and/or modify |
||
7 | it under the terms of the GNU General Public License as published by |
||
8 | the Free Software Foundation; either version 2 of the License, or |
||
9 | (at your option) any later version. |
||
10 | |||
11 | This program is distributed in the hope that it will be useful, |
||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | GNU General Public License for more details. |
||
15 | |||
16 | You should have received a copy of the GNU General Public License |
||
17 | along with this program; if not, write to the Free Software |
||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
19 | |||
20 | *******************************************************************************/ |
||
21 | |||
22 | //? pragma option LST // generate ASM listing file - создать ассемблерный листинг |
||
23 | //? warning TRUE // включить режим вывода предупреждений |
||
24 | ? pragma option meos |
||
25 | ? jumptomain NONE |
||
26 | ? include "msys.h--" // MenuetOS system functions - системные функции MenuetOS |
||
27 | |||
28 | ? print "\nЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї" |
||
29 | ? print "\nі MeOS MineSweeper v0.3 і" |
||
30 | ? print "\nі (C) Ivan Poddubny (ivan-yar@bk.ru) 2003 і" |
||
31 | ? print "\nАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ\n\n" |
||
32 | |||
33 | /************************************** DATA **************************************/ |
||
34 | |||
35 | ? define XPX 16 // X pixels by square - размер клетки в пикселях |
||
36 | ? define YPX 16 // Y pixels by square |
||
37 | ? define MINE 255 // значение для мины в поле value |
||
38 | |||
39 | struct |
||
40 | { |
||
41 | byte value; // number of mines - количество мин в окружающих клетках |
||
42 | byte open; // square is open - клетка открыта |
||
43 | byte press; // reserved - зарезервировано |
||
44 | byte mark; // square is marked - клетка помечена |
||
45 | } massiv[30*30]; |
||
46 | |||
47 | struct |
||
48 | { |
||
49 | byte a_inc; |
||
50 | byte b_inc; |
||
51 | } matrix[8] = {-1,-1,1,0,1,0,0,1,-2,0,0,1,1,0,1,0}; |
||
52 | |||
53 | struct |
||
54 | { |
||
55 | byte x_size; |
||
56 | byte y_size; |
||
57 | byte nmines; |
||
58 | } stdmodes[3] = {9,9,10, 16,16,40, 30,16,99}; // {x,y,m} |
||
59 | |||
60 | int XST, // offset of first pixel X - смещение поля от границы окна |
||
61 | YST, |
||
62 | ncx, // number of squares in X - размер пол |
||
63 | ncy, |
||
64 | cmines, // mines discovered - количество неоткрытых мин |
||
65 | initmines, // number of initial mines - изначальное количество мин |
||
66 | sqclosed; // squares still closed - количество закрытых клеток |
||
67 | |||
68 | dword xpos = 100, // window coordinates - координаты окна |
||
69 | ypos = 100, |
||
70 | xsize, // window size |
||
71 | ysize; |
||
72 | |||
73 | byte stop_game = FALSE, // game stopped - признак конца игры |
||
74 | mouse_en = TRUE, // mouse enabled - мышь |
||
75 | mode = 3, // режим игры 1-новичок 2-любитель 3-эксперт (0 особый) |
||
76 | mouse_status, |
||
77 | firstmine; |
||
78 | |||
79 | ProcessInfo procinfo; |
||
80 | SystemColors colors; |
||
81 | |||
82 | /************************************** CODE **************************************/ |
||
83 | |||
84 | inline void fastcall mouse_enable() |
||
85 | { |
||
86 | $mov eax,40 |
||
87 | $mov ebx,100111b |
||
88 | $int 0x40 |
||
89 | } |
||
90 | |||
91 | inline void fastcall mouse_disable() |
||
92 | { |
||
93 | $mov eax,40 |
||
94 | $mov ebx,000111b |
||
95 | $int 0x40 |
||
96 | } |
||
97 | |||
98 | ? include "timer.h--" // timer functions |
||
99 | ? include "draw.h--" // drawing functions |
||
100 | ? include "access.h--" // get & set functions |
||
101 | ? include "random.h--" // random number generator |
||
102 | //? include "uf.h--" // user field window |
||
103 | |||
104 | void init() |
||
105 | // Инициализаци |
||
106 | { |
||
107 | XST = 10; YST = 52; // FIELD POSITION IN WINDOW |
||
108 | |||
109 | ECX = mode; |
||
110 | IF (ECX != 0) |
||
111 | { |
||
112 | //ncx = stdmodes[ECX-1].x_size; |
||
113 | //ncy = stdmodes[ECX-1].y_size; |
||
114 | //cmines = initmines = stdmodes[ECX-1].nmines; |
||
115 | |||
116 | EBX = #stdmodes; |
||
117 | ECX--; ECX *= 3; |
||
118 | EBX += ECX; |
||
119 | |||
120 | ncx = DSBYTE[EBX]; EBX++; |
||
121 | ncy = DSBYTE[EBX]; EBX++; |
||
122 | cmines = initmines = DSBYTE[EBX]; |
||
123 | } |
||
124 | |||
125 | xsize = ncx * XPX + XST + XST; |
||
126 | ysize = ncy * YPX + YST + XST; |
||
127 | } // init |
||
128 | |||
129 | void clear_all() |
||
130 | // Очистить поле |
||
131 | { |
||
132 | EAX = 0; |
||
133 | EDI = #massiv; |
||
134 | ECX = ncx * ncy; |
||
135 | $REP $STOSD |
||
136 | } // clear_all |
||
137 | |||
138 | void new_game() |
||
139 | // Новая игра |
||
140 | { |
||
141 | init(); // инициализаци |
||
142 | randomize(); // генератор случайных чисел |
||
143 | clear_all(); // очистить поле |
||
144 | |||
145 | firstmine = TRUE; // игра не начата |
||
146 | mouse_en = TRUE; // мышь разрешена |
||
147 | stop_game = FALSE; // игра не закончена |
||
148 | stop_timer(); |
||
149 | time = 0; // время = 0 |
||
150 | } // new_game |
||
151 | |||
152 | void set_mines(int nminas, no_x, no_y) |
||
153 | // Расставить мины |
||
154 | { |
||
155 | int i, x, y, a, b; |
||
156 | |||
157 | sqclosed = ncx * ncy - nminas; // количество НЕоткрытых клеток = площадь поля - кол-во мин |
||
158 | |||
159 | FOR (i = nminas; i > 0; i--) // расставить мины |
||
160 | { |
||
161 | x = random(ncx); y = random(ncy); |
||
162 | WHILE ((get_value(x, y) == MINE) || ((x == no_x) && (y == no_y))) |
||
163 | { |
||
164 | x = random(ncx); |
||
165 | y = random(ncy); |
||
166 | } |
||
167 | set_value(x, y, MINE); |
||
168 | } |
||
169 | |||
170 | for (x = ncx-1; x >= 0; x--) // расставить цифры |
||
171 | { |
||
172 | for (y = ncy-1; y >= 0; y--) |
||
173 | { |
||
174 | IF (get_value(x, y) == MINE) |
||
175 | continue; |
||
176 | EDX = x * ncy + y*4 + #massiv; |
||
177 | a = x; b = y; |
||
178 | FOR (i = 0; i < 8; i++) |
||
179 | { |
||
180 | AL = matrix[i].a_inc; |
||
181 | $movsx eax,al |
||
182 | a += EAX; |
||
183 | AL = matrix[i].b_inc; |
||
184 | $movsx eax,al |
||
185 | b += EAX; |
||
186 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_value(a, b) == MINE)) |
||
187 | DSBYTE[EDX]++; |
||
188 | } |
||
189 | } |
||
190 | } |
||
191 | } // set_mines |
||
192 | |||
193 | inline void do_mouse(void) |
||
194 | // Обработчик мыши |
||
195 | { |
||
196 | int x,y; |
||
197 | |||
198 | EAX = sys_read_mouse(2); // мышь не нажата -> выход |
||
199 | IF (EAX == 0) return; |
||
200 | |||
201 | mouse_status = AL; |
||
202 | |||
203 | EAX = sys_read_mouse(1); // мышь вне поля -> выход |
||
204 | EBX = EAX; EAX >>= 16; EBX &= 0xffff; |
||
205 | ECX = ncx * XPX + XST - 1; |
||
206 | EDX = ncy * YPX + YST - 1; |
||
207 | IF ((EAX < XST) || (EBX < YST) || (EAX > ECX) || (EBX > EDX)) return; |
||
208 | |||
209 | EAX -= XST; EAX /= XPX; x = EAX; // вычислить x и y |
||
210 | EBX -= YST; EBX /= YPX; y = EBX; |
||
211 | |||
212 | IF ((mouse_status == 1) && (!get_open(x, y)) && (get_mark(x, y) != 1)) |
||
213 | { |
||
214 | // на неоткрытой клетке без флажка нажата левая кнопка мыши |
||
215 | // left mouse button is pressed |
||
216 | IF (firstmine == TRUE) |
||
217 | { |
||
218 | firstmine = FALSE; |
||
219 | set_mines(cmines, x, y); |
||
220 | start_timer(); |
||
221 | } |
||
222 | IF (get_value(x, y) == MINE) |
||
223 | { |
||
224 | end_game(); |
||
225 | return; |
||
226 | } |
||
227 | open_square(x, y); |
||
228 | } |
||
229 | else IF ((mouse_status == 2) && (!get_open(x, y))) |
||
230 | { |
||
231 | // на неоткрытой клетке нажата правая кнопка мыши |
||
232 | // right mouse button is pressed |
||
233 | EBX = get_mark(x, y); EBX++; |
||
234 | EBX = EBX%3; |
||
235 | SWITCH (EBX) |
||
236 | { |
||
237 | CASE 2: cmines++; BREAK; |
||
238 | CASE 1: cmines--; |
||
239 | } |
||
240 | |||
241 | set_mark(x, y, EBX); |
||
242 | |||
243 | draw_minesi(); |
||
244 | draw_square(x, y); |
||
245 | return; |
||
246 | } |
||
247 | ELSE IF ((mouse_status == 3) && (get_open(x, y))) |
||
248 | { |
||
249 | // на открытой клетке нажаты обе кнопки мыши |
||
250 | // both mouse buttons are pressed |
||
251 | IF (open_near_squares(x, y) == TRUE) |
||
252 | end_game(); |
||
253 | } |
||
254 | |||
255 | if (sqclosed == 0) |
||
256 | // открыты все клетки |
||
257 | // all squares are opened |
||
258 | { |
||
259 | mouse_en = FALSE; // запретить мышь |
||
260 | stop_timer(); |
||
261 | stop_game = TRUE; // игра завершена |
||
262 | |||
263 | // поставить нерасставленные мины |
||
264 | FOR (x = 0; x < ncx; x++) |
||
265 | FOR (y = 0; y < ncy; y++) |
||
266 | IF ((get_value(x, y) == MINE) && (get_mark(x, y) != 1)) |
||
267 | { |
||
268 | set_mark(x, y, 1); |
||
269 | cmines--; |
||
270 | draw_square(x, y); |
||
271 | } |
||
272 | draw_minesi(); |
||
273 | } |
||
274 | } // do_mouse |
||
275 | |||
276 | void open_square(int x, y) |
||
277 | // Открыть клетку |
||
278 | { |
||
279 | int a, b, i; |
||
280 | |||
281 | set_open(x, y, TRUE); |
||
282 | sqclosed--; |
||
283 | |||
284 | IF (get_value(x, y) != 0) |
||
285 | { |
||
286 | draw_square(x, y); |
||
287 | } |
||
288 | else |
||
289 | { |
||
290 | draw_square(x, y); |
||
291 | a = x; b = y; |
||
292 | FOR (i = 0; i < 8; i++) |
||
293 | { |
||
294 | //a += matrix[i].a_inc; |
||
295 | //b += matrix[i].b_inc; |
||
296 | AL = matrix[i].a_inc; |
||
297 | $movsx eax,al |
||
298 | a += EAX; |
||
299 | AL = matrix[i].b_inc; |
||
300 | $movsx eax,al |
||
301 | b += EAX; |
||
302 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1)) |
||
303 | open_square(a, b); |
||
304 | } |
||
305 | } |
||
306 | } // open_square |
||
307 | |||
308 | int open_near_squares(int x, y) |
||
309 | // Открыть близлежащие клетки (обе кнопки мыши вместе) |
||
310 | { |
||
311 | int a, b, i; |
||
312 | dword suma = 0; |
||
313 | |||
314 | a = x; |
||
315 | b = y; |
||
316 | FOR (i = 0; i < 8; i++) |
||
317 | { |
||
318 | //a+=matrix[i].a_inc; |
||
319 | //b+=matrix[i].b_inc; |
||
320 | AL = matrix[i].a_inc; |
||
321 | $movsx eax,al |
||
322 | a += EAX; |
||
323 | AL = matrix[i].b_inc; |
||
324 | $movsx eax,al |
||
325 | b += EAX; |
||
326 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_mark(a, b) == 1)) |
||
327 | suma++; |
||
328 | } |
||
329 | |||
330 | if (suma == get_value(x, y)) |
||
331 | { |
||
332 | suma = 0; |
||
333 | a = x; |
||
334 | b = y; |
||
335 | for (i = 0; i < 8; i++) |
||
336 | { |
||
337 | //a+=matrix[i].a_inc; |
||
338 | //b+=matrix[i].b_inc; |
||
339 | AL = matrix[i].a_inc; |
||
340 | $movsx eax,al |
||
341 | a += EAX; |
||
342 | AL = matrix[i].b_inc; |
||
343 | $movsx eax,al |
||
344 | b += EAX; |
||
345 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1)) |
||
346 | { |
||
347 | IF (get_value(a, b) == MINE) |
||
348 | suma = 1; |
||
349 | open_square(a, b); |
||
350 | } |
||
351 | } |
||
352 | RETURN suma; |
||
353 | } |
||
354 | ELSE |
||
355 | RETURN 0; |
||
356 | } // open_near_squares |
||
357 | |||
358 | void end_game() |
||
359 | { |
||
360 | int x,y; |
||
361 | |||
362 | stop_game = TRUE; |
||
363 | stop_timer(); |
||
364 | for (x=0; x |
||
365 | { |
||
366 | for (y=0; y |
||
367 | { |
||
368 | IF (get_value(x, y) == MINE) |
||
369 | { |
||
370 | set_mark(x, y, FALSE); // снять флаг |
||
371 | open_square(x, y); |
||
372 | } |
||
373 | ELSE IF (get_mark(x, y) == 1) // если мины нет, а флажок есть |
||
374 | { |
||
375 | EBX = XPX * x + XST; // x left |
||
376 | ECX = EBX + XPX - 1; // x right |
||
377 | EBX <<= 16; EBX += ECX; |
||
378 | $PUSH EBX |
||
379 | |||
380 | ECX = YPX * y + YST; // y top |
||
381 | $PUSH ECX |
||
382 | EDX = ECX + YPX - 1; // y bottom |
||
383 | ECX <<= 16; ECX += EDX; |
||
384 | sys_draw_line(EBX, ECX, clBlack); |
||
385 | |||
386 | $POP EDX |
||
387 | ECX = EDX + YPX - 1; |
||
388 | ECX <<= 16; ECX += EDX; |
||
389 | $POP EBX |
||
390 | sys_draw_line(EBX, ECX, clBlack); |
||
391 | CONTINUE; |
||
392 | } |
||
393 | } |
||
394 | } |
||
395 | } // end_game |
||
396 | |||
397 | |||
398 | void main() |
||
399 | { |
||
400 | sys_delay(5); // for old kernel only! |
||
401 | new_game(); |
||
402 | draw_window(); |
||
403 | |||
404 | mouse_enable(); |
||
405 | while() |
||
406 | { |
||
407 | switch (sys_wait_event_timeout(100)) // wait for 1 second |
||
408 | { |
||
409 | CASE evReDraw: |
||
410 | draw_window(); |
||
411 | continue; |
||
412 | |||
413 | CASE evKey: |
||
414 | IF (sys_get_key() == 27) |
||
415 | sys_exit_process(); |
||
416 | continue; |
||
417 | |||
418 | CASE evButton: |
||
419 | EAX = sys_get_button_id(); |
||
420 | IF (EAX == 911) // new game |
||
421 | { |
||
422 | new_game(); |
||
423 | draw_squares(); |
||
424 | draw_time(); |
||
425 | draw_minesi(); |
||
426 | } |
||
427 | ELSE IF (EAX == 1001) // change mode |
||
428 | { |
||
429 | // mode++; mode%=3; mode++; |
||
430 | EAX = mode; EAX++; EAX = EAX%3; EAX++; mode = AL; |
||
431 | |||
432 | // get window position - получить координаты окна |
||
433 | sys_process_info(#procinfo, -1); |
||
434 | xpos = procinfo.xstart; |
||
435 | ypos = procinfo.ystart; |
||
436 | |||
437 | // start a new process and terminate this one |
||
438 | sys_create_thread(#main, ESP); |
||
439 | sys_exit_process(); |
||
440 | } |
||
441 | //ELSE IF (EAX == 1002) |
||
442 | //{ |
||
443 | // start_uf(); |
||
444 | //} |
||
445 | ELSE IF (EAX == 1) // close window |
||
446 | sys_exit_process(); |
||
447 | CONTINUE; |
||
448 | |||
449 | case evMouse: |
||
450 | IF (!mouse_en) // is mouse enabled ? |
||
451 | CONTINUE; |
||
452 | do_mouse(); |
||
453 | // wait for mouse release - ждать отпускания кнопки |
||
454 | WHILE (sys_read_mouse(2) == mouse_status) |
||
455 | { |
||
456 | check_timer(); |
||
457 | sys_delay(6); |
||
458 | CONTINUE; |
||
459 | } |
||
460 | check_timer(); |
||
461 | IF (stop_game) // disable mouse if game is stopped |
||
462 | mouse_en = FALSE; |
||
463 | CONTINUE; |
||
464 | } |
||
465 | check_timer(); |
||
466 | sys_delay(2); |
||
467 | } |
||
468 | } // main=><=>=><=>=><=>>>>>>>>>>>>>>>>> |