/******************************************************************************* MenuetOS MineSweeper Copyright (C) 2003, 2004 Ivan Poddubny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *******************************************************************************/ ? pragma option LST // generate ASM listing file - создать ассемблерный листинг ? warning TRUE // включить режим вывода предупреждений ? jumptomain NONE ? include "msys.h--" // MenuetOS system functions - системные функции MenuetOS //? define DEBUG 1 ? print "\nЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї" ? print "\nі MenuetOS MineSweeper v0.4 і" ? print "\nі (C) Ivan Poddubny (ivan-yar@bk.ru) 2003,2004 і" ? print "\nАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ\n\n" /************************************** DATA **************************************/ ? define XPX 16 // X pixels by square - размер клетки в пикселях ? define YPX 16 // Y pixels by square ? define MINE 255 // в клетке мина, если value = MINE struct { byte value; // number of mines - количество мин в окружающих клетках byte open; // square is open - клетка открыта byte press; // reserved - зарезервировано byte mark; // square is marked - клетка помечена } massiv[30*30]; struct { byte a_inc; byte b_inc; } matrix[8] = {-1,-1,1,0,1,0,0,1,-2,0,0,1,1,0,1,0}; struct { byte x_size; byte y_size; byte nmines; } stdmodes[3] = {9,9,10, 16,16,40, 30,16,99}; // {x,y,m} int XST, // offset of first pixel X - смещение поля от границы окна YST, ncx, // number of squares in X - размер поля ncy, cmines, // mines discovered - количество неоткрытых мин initmines, // number of initial mines - изначальное количество мин sqclosed; // squares still closed - количество закрытых клеток dword xpos = 100, // window coordinates - координаты окна ypos = 100, xsize, // window size ysize; byte stop_game = FALSE, // game stopped - признак конца игры mouse_en = TRUE, // mouse enabled - мышь mode = 3, // режим игры 1-новичок 2-любитель 3-эксперт (0 особый) mouse_status, firstmine; ProcessInfo procinfo; SystemColors colors; /************************************** CODE **************************************/ inline void fastcall mouse_enable() { $mov eax,40 $mov ebx,100111b $int 0x40 } inline void fastcall mouse_disable() { $mov eax,40 $mov ebx,000111b $int 0x40 } ? include "timer.h--" // timer functions ? include "draw.h--" // drawing functions ? include "access.h--" // get & set functions ? include "random.h--" // random number generator //? include "uf.h--" // user field window void init() // Инициализация { XST = 10; YST = 52; // FIELD POSITION IN WINDOW ECX = mode; IF (ECX != 0) { //ncx = stdmodes[ECX-1].x_size; //ncy = stdmodes[ECX-1].y_size; //cmines = initmines = stdmodes[ECX-1].nmines; EBX = #stdmodes; ECX--; ECX *= 3; EBX += ECX; ncx = DSBYTE[EBX]; EBX++; ncy = DSBYTE[EBX]; EBX++; cmines = initmines = DSBYTE[EBX]; } xsize = ncx * XPX + XST + XST; ysize = ncy * YPX + YST + XST; } // init void clear_all() // Очистить поле { EAX = 0; EDI = #massiv; ECX = ncx * ncy; $REP $STOSD } // clear_all void new_game() // Новая игра { init(); // инициализация randomize(); // генератор случайных чисел clear_all(); // очистить поле firstmine = TRUE; // игра не начата mouse_en = TRUE; // мышь разрешена stop_game = FALSE; // игра не закончена stop_timer(); time = 0; // время = 0 } // new_game void set_mines(int nminas, no_x, no_y) // Расставить мины { int i, x, y, a, b; #ifdef DEBUG sys_debug_write_string("MINE: set_mines called\n"); #endif sqclosed = ncx * ncy - nminas; // количество НЕоткрытых клеток = площадь поля - кол-во мин FOR (i = nminas; i > 0; i--) // расставить мины { x = random(ncx); y = random(ncy); WHILE ((get_value(x, y) == MINE) || ((x == no_x) && (y == no_y))) { x = random(ncx); y = random(ncy); } set_value(x, y, MINE); } for (x = ncx-1; x >= 0; x--) // расставить цифры { for (y = ncy-1; y >= 0; y--) { IF (get_value(x, y) == MINE) continue; EDX = x * ncy + y*4 + #massiv; a = x; b = y; FOR (i = 0; i < 8; i++) { AL = matrix[i].a_inc; $movsx eax,al a += EAX; AL = matrix[i].b_inc; $movsx eax,al b += EAX; IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_value(a, b) == MINE)) DSBYTE[EDX]++; } } } } // set_mines inline void do_mouse(void) // Обработчик мыши { int x,y; EAX = sys_read_mouse(2); // мышь не нажата -> выход IF (EAX == 0) { // sys_debug_write_string("Strange\n"); return; } mouse_status = AL; EAX = sys_read_mouse(1); // мышь вне поля -> выход EBX = EAX; EAX >>= 16; EBX &= 0xffff; ECX = ncx * XPX + XST - 1; EDX = ncy * YPX + YST - 1; IF ((EAX < XST) || (EBX < YST) || (EAX > ECX) || (EBX > EDX)) return; EAX -= XST; EAX /= XPX; x = EAX; // вычислить x и y EBX -= YST; EBX /= YPX; y = EBX; IF ((mouse_status == 1) && (!get_open(x, y)) && (get_mark(x, y) != 1)) { // на неоткрытой клетке без флажка нажата левая кнопка мыши // left mouse button is pressed IF (firstmine == TRUE) { firstmine = FALSE; set_mines(initmines, x, y); start_timer(); time = 1; draw_time(); } IF (get_value(x, y) == MINE) { end_game(); return; } open_square(x, y); } else IF ((mouse_status == 2) && (!get_open(x, y))) { // на неоткрытой клетке нажата правая кнопка мыши // right mouse button is pressed EBX = get_mark(x, y); EBX++; EBX = EBX%3; SWITCH (EBX) { CASE 2: cmines++; BREAK; CASE 1: cmines--; } set_mark(x, y, EBX); draw_minesi(); draw_square(x, y); return; } ELSE IF ((mouse_status == 3) && (get_open(x, y))) { // на открытой клетке нажаты обе кнопки мыши // both mouse buttons are pressed IF (open_near_squares(x, y) == TRUE) end_game(); } IF (sqclosed == 0) { // открыты все клетки // all squares are opened mouse_en = FALSE; // запретить мышь stop_timer(); stop_game = TRUE; // игра завершена // поставить нерасставленные мины FOR (x = 0; x < ncx; x++) FOR (y = 0; y < ncy; y++) IF ((get_value(x, y) == MINE) && (get_mark(x, y) != 1)) { set_mark(x, y, 1); cmines--; draw_square(x, y); } draw_minesi(); } } // do_mouse void open_square(int x, y) // Открыть клетку { int a, b, i; #ifdef DEBUG sys_debug_write_string("MINE: open_square called\n"); #endif set_open(x, y, TRUE); sqclosed--; IF (get_value(x, y) != 0) { draw_square(x, y); } else { draw_square(x, y); a = x; b = y; FOR (i = 0; i < 8; i++) { //a += matrix[i].a_inc; //b += matrix[i].b_inc; AL = matrix[i].a_inc; $movsx eax,al a += EAX; AL = matrix[i].b_inc; $movsx eax,al b += EAX; IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1)) open_square(a, b); } } } // open_square int open_near_squares(int x, y) // Открыть близлежащие клетки (обе кнопки мыши вместе) { int a, b, i; dword suma = 0; #ifdef DEBUG sys_debug_write_string("MINE: open_near_squares called\n"); #endif a = x; b = y; FOR (i = 0; i < 8; i++) { //a+=matrix[i].a_inc; //b+=matrix[i].b_inc; AL = matrix[i].a_inc; $movsx eax,al a += EAX; AL = matrix[i].b_inc; $movsx eax,al b += EAX; IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_mark(a, b) == 1)) suma++; } if (suma == get_value(x, y)) { suma = 0; a = x; b = y; for (i = 0; i < 8; i++) { //a+=matrix[i].a_inc; //b+=matrix[i].b_inc; AL = matrix[i].a_inc; $movsx eax,al a += EAX; AL = matrix[i].b_inc; $movsx eax,al b += EAX; IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1)) { IF (get_value(a, b) == MINE) suma = 1; open_square(a, b); } } return suma; } ELSE return 0; } // open_near_squares void end_game() { int x,y; #ifdef DEBUG sys_debug_write_string("MINE: end_game called\n"); #endif stop_game = TRUE; stop_timer(); for (x=0; x