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