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