Subversion Repositories Kolibri OS

Rev

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