Rev 963 | Rev 2060 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
31 | halyavin | 1 | /******************************************************************************* |
2 | |||
3 | MenuetOS MineSweeper |
||
126 | poddubny | 4 | Copyright (C) 2003, 2004 Ivan Poddubny |
31 | halyavin | 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 | |||
1771 | clevermous | 22 | //? pragma option LST // generate ASM listing file - создать ассемблерный листинг |
126 | poddubny | 23 | ? warning TRUE // включить режим вывода предупреждений |
31 | halyavin | 24 | ? jumptomain NONE |
963 | leency | 25 | ? include "kos_sys.h--" // MenuetOS system functions - системные функции MenuetOS |
126 | poddubny | 26 | //? define DEBUG 1 |
31 | halyavin | 27 | |
126 | poddubny | 28 | ? print "\nЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї" |
29 | ? print "\nі MenuetOS MineSweeper v0.4 і" |
||
30 | ? print "\nі (C) Ivan Poddubny (ivan-yar@bk.ru) 2003,2004 і" |
||
31 | ? print "\nАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ\n\n" |
||
31 | halyavin | 32 | |
33 | /************************************** DATA **************************************/ |
||
34 | |||
35 | ? define XPX 16 // X pixels by square - размер клетки в пикселях |
||
36 | ? define YPX 16 // Y pixels by square |
||
126 | poddubny | 37 | ? define MINE 255 // в клетке мина, если value = MINE |
31 | halyavin | 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, |
||
126 | poddubny | 62 | ncx, // number of squares in X - размер поля |
31 | halyavin | 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 | |||
126 | poddubny | 91 | |
31 | halyavin | 92 | inline void fastcall mouse_disable() |
93 | { |
||
94 | $mov eax,40 |
||
95 | $mov ebx,000111b |
||
96 | $int 0x40 |
||
97 | } |
||
98 | |||
126 | poddubny | 99 | |
963 | leency | 100 | # include "timer.h--" // timer functions |
101 | # include "draw.h--" // drawing functions |
||
102 | # include "access.h--" // get & set functions |
||
103 | # include "random.h--" // random number generator |
||
31 | halyavin | 104 | //? include "uf.h--" // user field window |
105 | |||
126 | poddubny | 106 | |
31 | halyavin | 107 | void init() |
126 | poddubny | 108 | // Инициализация |
31 | halyavin | 109 | { |
110 | XST = 10; YST = 52; // FIELD POSITION IN WINDOW |
||
111 | |||
112 | ECX = mode; |
||
113 | IF (ECX != 0) |
||
114 | { |
||
115 | //ncx = stdmodes[ECX-1].x_size; |
||
116 | //ncy = stdmodes[ECX-1].y_size; |
||
117 | //cmines = initmines = stdmodes[ECX-1].nmines; |
||
118 | |||
119 | EBX = #stdmodes; |
||
120 | ECX--; ECX *= 3; |
||
121 | EBX += ECX; |
||
122 | |||
123 | ncx = DSBYTE[EBX]; EBX++; |
||
124 | ncy = DSBYTE[EBX]; EBX++; |
||
125 | cmines = initmines = DSBYTE[EBX]; |
||
126 | } |
||
127 | |||
128 | xsize = ncx * XPX + XST + XST; |
||
129 | ysize = ncy * YPX + YST + XST; |
||
130 | } // init |
||
131 | |||
126 | poddubny | 132 | |
31 | halyavin | 133 | void clear_all() |
134 | // Очистить поле |
||
135 | { |
||
136 | EAX = 0; |
||
137 | EDI = #massiv; |
||
138 | ECX = ncx * ncy; |
||
139 | $REP $STOSD |
||
140 | } // clear_all |
||
141 | |||
126 | poddubny | 142 | |
31 | halyavin | 143 | void new_game() |
144 | // Новая игра |
||
145 | { |
||
126 | poddubny | 146 | init(); // инициализация |
31 | halyavin | 147 | randomize(); // генератор случайных чисел |
148 | clear_all(); // очистить поле |
||
149 | |||
150 | firstmine = TRUE; // игра не начата |
||
151 | mouse_en = TRUE; // мышь разрешена |
||
152 | stop_game = FALSE; // игра не закончена |
||
153 | stop_timer(); |
||
154 | time = 0; // время = 0 |
||
155 | } // new_game |
||
156 | |||
126 | poddubny | 157 | |
31 | halyavin | 158 | void set_mines(int nminas, no_x, no_y) |
159 | // Расставить мины |
||
160 | { |
||
161 | int i, x, y, a, b; |
||
162 | |||
126 | poddubny | 163 | #ifdef DEBUG |
164 | sys_debug_write_string("MINE: set_mines called\n"); |
||
165 | #endif |
||
166 | |||
31 | halyavin | 167 | sqclosed = ncx * ncy - nminas; // количество НЕоткрытых клеток = площадь поля - кол-во мин |
168 | |||
169 | FOR (i = nminas; i > 0; i--) // расставить мины |
||
170 | { |
||
126 | poddubny | 171 | x = random(ncx); |
172 | y = random(ncy); |
||
31 | halyavin | 173 | WHILE ((get_value(x, y) == MINE) || ((x == no_x) && (y == no_y))) |
174 | { |
||
175 | x = random(ncx); |
||
176 | y = random(ncy); |
||
177 | } |
||
178 | set_value(x, y, MINE); |
||
179 | } |
||
180 | |||
181 | for (x = ncx-1; x >= 0; x--) // расставить цифры |
||
182 | { |
||
183 | for (y = ncy-1; y >= 0; y--) |
||
184 | { |
||
185 | IF (get_value(x, y) == MINE) |
||
186 | continue; |
||
187 | EDX = x * ncy + y*4 + #massiv; |
||
188 | a = x; b = y; |
||
189 | FOR (i = 0; i < 8; i++) |
||
190 | { |
||
191 | AL = matrix[i].a_inc; |
||
192 | $movsx eax,al |
||
193 | a += EAX; |
||
194 | AL = matrix[i].b_inc; |
||
195 | $movsx eax,al |
||
196 | b += EAX; |
||
197 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_value(a, b) == MINE)) |
||
198 | DSBYTE[EDX]++; |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | } // set_mines |
||
203 | |||
126 | poddubny | 204 | |
31 | halyavin | 205 | inline void do_mouse(void) |
206 | // Обработчик мыши |
||
207 | { |
||
208 | int x,y; |
||
209 | |||
210 | EAX = sys_read_mouse(2); // мышь не нажата -> выход |
||
126 | poddubny | 211 | IF (EAX == 0) |
212 | { |
||
213 | // sys_debug_write_string("Strange\n"); |
||
214 | return; |
||
215 | } |
||
31 | halyavin | 216 | |
217 | mouse_status = AL; |
||
218 | |||
219 | EAX = sys_read_mouse(1); // мышь вне поля -> выход |
||
220 | EBX = EAX; EAX >>= 16; EBX &= 0xffff; |
||
221 | ECX = ncx * XPX + XST - 1; |
||
222 | EDX = ncy * YPX + YST - 1; |
||
223 | IF ((EAX < XST) || (EBX < YST) || (EAX > ECX) || (EBX > EDX)) return; |
||
224 | |||
225 | EAX -= XST; EAX /= XPX; x = EAX; // вычислить x и y |
||
226 | EBX -= YST; EBX /= YPX; y = EBX; |
||
227 | |||
228 | IF ((mouse_status == 1) && (!get_open(x, y)) && (get_mark(x, y) != 1)) |
||
229 | { |
||
230 | // на неоткрытой клетке без флажка нажата левая кнопка мыши |
||
231 | // left mouse button is pressed |
||
232 | IF (firstmine == TRUE) |
||
233 | { |
||
234 | firstmine = FALSE; |
||
126 | poddubny | 235 | set_mines(initmines, x, y); |
31 | halyavin | 236 | start_timer(); |
126 | poddubny | 237 | time = 1; |
238 | draw_time(); |
||
31 | halyavin | 239 | } |
240 | IF (get_value(x, y) == MINE) |
||
241 | { |
||
242 | end_game(); |
||
243 | return; |
||
244 | } |
||
245 | open_square(x, y); |
||
246 | } |
||
247 | else IF ((mouse_status == 2) && (!get_open(x, y))) |
||
248 | { |
||
249 | // на неоткрытой клетке нажата правая кнопка мыши |
||
250 | // right mouse button is pressed |
||
251 | EBX = get_mark(x, y); EBX++; |
||
252 | EBX = EBX%3; |
||
253 | SWITCH (EBX) |
||
254 | { |
||
255 | CASE 2: cmines++; BREAK; |
||
256 | CASE 1: cmines--; |
||
257 | } |
||
258 | |||
259 | set_mark(x, y, EBX); |
||
260 | |||
261 | draw_minesi(); |
||
262 | draw_square(x, y); |
||
263 | return; |
||
264 | } |
||
265 | ELSE IF ((mouse_status == 3) && (get_open(x, y))) |
||
266 | { |
||
267 | // на открытой клетке нажаты обе кнопки мыши |
||
268 | // both mouse buttons are pressed |
||
269 | IF (open_near_squares(x, y) == TRUE) |
||
270 | end_game(); |
||
271 | } |
||
272 | |||
126 | poddubny | 273 | IF (sqclosed == 0) |
31 | halyavin | 274 | { |
126 | poddubny | 275 | // открыты все клетки |
276 | // all squares are opened |
||
31 | halyavin | 277 | mouse_en = FALSE; // запретить мышь |
278 | stop_timer(); |
||
279 | stop_game = TRUE; // игра завершена |
||
280 | |||
281 | // поставить нерасставленные мины |
||
282 | FOR (x = 0; x < ncx; x++) |
||
283 | FOR (y = 0; y < ncy; y++) |
||
284 | IF ((get_value(x, y) == MINE) && (get_mark(x, y) != 1)) |
||
285 | { |
||
286 | set_mark(x, y, 1); |
||
287 | cmines--; |
||
288 | draw_square(x, y); |
||
289 | } |
||
290 | draw_minesi(); |
||
291 | } |
||
292 | } // do_mouse |
||
293 | |||
126 | poddubny | 294 | |
31 | halyavin | 295 | void open_square(int x, y) |
296 | // Открыть клетку |
||
297 | { |
||
298 | int a, b, i; |
||
299 | |||
126 | poddubny | 300 | #ifdef DEBUG |
301 | sys_debug_write_string("MINE: open_square called\n"); |
||
302 | #endif |
||
303 | |||
31 | halyavin | 304 | set_open(x, y, TRUE); |
305 | sqclosed--; |
||
306 | |||
307 | IF (get_value(x, y) != 0) |
||
308 | { |
||
309 | draw_square(x, y); |
||
310 | } |
||
311 | else |
||
312 | { |
||
313 | draw_square(x, y); |
||
314 | a = x; b = y; |
||
315 | FOR (i = 0; i < 8; i++) |
||
316 | { |
||
317 | //a += matrix[i].a_inc; |
||
318 | //b += matrix[i].b_inc; |
||
319 | AL = matrix[i].a_inc; |
||
320 | $movsx eax,al |
||
321 | a += EAX; |
||
322 | AL = matrix[i].b_inc; |
||
323 | $movsx eax,al |
||
324 | b += EAX; |
||
325 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1)) |
||
326 | open_square(a, b); |
||
327 | } |
||
328 | } |
||
329 | } // open_square |
||
330 | |||
126 | poddubny | 331 | |
31 | halyavin | 332 | int open_near_squares(int x, y) |
333 | // Открыть близлежащие клетки (обе кнопки мыши вместе) |
||
334 | { |
||
335 | int a, b, i; |
||
336 | dword suma = 0; |
||
337 | |||
126 | poddubny | 338 | #ifdef DEBUG |
339 | sys_debug_write_string("MINE: open_near_squares called\n"); |
||
340 | #endif |
||
341 | |||
31 | halyavin | 342 | a = x; |
343 | b = y; |
||
344 | FOR (i = 0; i < 8; i++) |
||
345 | { |
||
346 | //a+=matrix[i].a_inc; |
||
347 | //b+=matrix[i].b_inc; |
||
348 | AL = matrix[i].a_inc; |
||
349 | $movsx eax,al |
||
350 | a += EAX; |
||
351 | AL = matrix[i].b_inc; |
||
352 | $movsx eax,al |
||
353 | b += EAX; |
||
354 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_mark(a, b) == 1)) |
||
355 | suma++; |
||
356 | } |
||
357 | |||
358 | if (suma == get_value(x, y)) |
||
359 | { |
||
360 | suma = 0; |
||
361 | a = x; |
||
362 | b = y; |
||
363 | for (i = 0; i < 8; i++) |
||
364 | { |
||
365 | //a+=matrix[i].a_inc; |
||
366 | //b+=matrix[i].b_inc; |
||
367 | AL = matrix[i].a_inc; |
||
368 | $movsx eax,al |
||
369 | a += EAX; |
||
370 | AL = matrix[i].b_inc; |
||
371 | $movsx eax,al |
||
372 | b += EAX; |
||
373 | IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1)) |
||
374 | { |
||
375 | IF (get_value(a, b) == MINE) |
||
376 | suma = 1; |
||
377 | open_square(a, b); |
||
378 | } |
||
379 | } |
||
963 | leency | 380 | RETURN suma; |
31 | halyavin | 381 | } |
382 | ELSE |
||
963 | leency | 383 | RETURN 0; |
31 | halyavin | 384 | } // open_near_squares |
385 | |||
126 | poddubny | 386 | |
31 | halyavin | 387 | void end_game() |
388 | { |
||
389 | int x,y; |
||
390 | |||
126 | poddubny | 391 | #ifdef DEBUG |
392 | sys_debug_write_string("MINE: end_game called\n"); |
||
393 | #endif |
||
394 | |||
31 | halyavin | 395 | stop_game = TRUE; |
396 | stop_timer(); |
||
397 | for (x=0; x |
||
398 | { |
||
399 | for (y=0; y |
||
400 | { |
||
401 | IF (get_value(x, y) == MINE) |
||
402 | { |
||
403 | set_mark(x, y, FALSE); // снять флаг |
||
404 | open_square(x, y); |
||
405 | } |
||
406 | ELSE IF (get_mark(x, y) == 1) // если мины нет, а флажок есть |
||
407 | { |
||
408 | EBX = XPX * x + XST; // x left |
||
409 | ECX = EBX + XPX - 1; // x right |
||
410 | EBX <<= 16; EBX += ECX; |
||
411 | $PUSH EBX |
||
412 | |||
413 | ECX = YPX * y + YST; // y top |
||
414 | $PUSH ECX |
||
415 | EDX = ECX + YPX - 1; // y bottom |
||
416 | ECX <<= 16; ECX += EDX; |
||
417 | sys_draw_line(EBX, ECX, clBlack); |
||
418 | |||
419 | $POP EDX |
||
420 | ECX = EDX + YPX - 1; |
||
421 | ECX <<= 16; ECX += EDX; |
||
422 | $POP EBX |
||
423 | sys_draw_line(EBX, ECX, clBlack); |
||
424 | CONTINUE; |
||
425 | } |
||
426 | } |
||
427 | } |
||
428 | } // end_game |
||
429 | |||
430 | |||
431 | void main() |
||
432 | { |
||
433 | new_game(); |
||
434 | draw_window(); |
||
435 | |||
436 | mouse_enable(); |
||
437 | while() |
||
438 | { |
||
439 | switch (sys_wait_event_timeout(100)) // wait for 1 second |
||
440 | { |
||
126 | poddubny | 441 | case evReDraw: |
31 | halyavin | 442 | draw_window(); |
443 | continue; |
||
444 | |||
126 | poddubny | 445 | case evKey: |
31 | halyavin | 446 | IF (sys_get_key() == 27) |
447 | sys_exit_process(); |
||
448 | continue; |
||
449 | |||
126 | poddubny | 450 | case evButton: |
31 | halyavin | 451 | EAX = sys_get_button_id(); |
452 | IF (EAX == 911) // new game |
||
453 | { |
||
454 | new_game(); |
||
455 | draw_squares(); |
||
456 | draw_time(); |
||
457 | draw_minesi(); |
||
458 | } |
||
459 | ELSE IF (EAX == 1001) // change mode |
||
460 | { |
||
461 | // mode++; mode%=3; mode++; |
||
462 | EAX = mode; EAX++; EAX = EAX%3; EAX++; mode = AL; |
||
463 | |||
126 | poddubny | 464 | new_game(); |
963 | leency | 465 | window_move_size(OLD,OLD,xsize,ysize); |
466 | CONTINUE; |
||
31 | halyavin | 467 | } |
126 | poddubny | 468 | // ELSE IF (EAX == 1002) |
469 | // { |
||
470 | // start_uf(); |
||
471 | // } |
||
31 | halyavin | 472 | ELSE IF (EAX == 1) // close window |
473 | sys_exit_process(); |
||
963 | leency | 474 | CONTINUE; |
31 | halyavin | 475 | |
476 | case evMouse: |
||
477 | IF (!mouse_en) // is mouse enabled ? |
||
963 | leency | 478 | CONTINUE; |
31 | halyavin | 479 | do_mouse(); |
480 | // wait for mouse release - ждать отпускания кнопки |
||
481 | WHILE (sys_read_mouse(2) == mouse_status) |
||
482 | { |
||
483 | check_timer(); |
||
126 | poddubny | 484 | sys_delay(3); |
31 | halyavin | 485 | CONTINUE; |
486 | } |
||
487 | check_timer(); |
||
488 | IF (stop_game) // disable mouse if game is stopped |
||
489 | mouse_en = FALSE; |
||
490 | CONTINUE; |
||
491 | } |
||
492 | check_timer(); |
||
493 | sys_delay(2); |
||
494 | } |
||
963 | leency | 495 | } // main=><=>=><=>=><=>>>>>>>>>>>>>>>>> |