Subversion Repositories Kolibri OS

Rev

Rev 2060 | Rev 6166 | 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
3979 Asper 88
  $mov ebx,0xC0000027
31 halyavin 89
  $int 0x40
90
}
91
 
126 poddubny 92
 
31 halyavin 93
inline void fastcall mouse_disable()
94
{
95
  $mov eax,40
3979 Asper 96
  $mov ebx,0xC0000007
31 halyavin 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