Subversion Repositories Kolibri OS

Rev

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