/******************************************************************************* KolibriOS 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 "kos_sys.h--" // KolibriOS system functions - ��������� ������� KolibriOS //? define DEBUG 1 ? print "\n����������������������������������������������Ŀ" ? print "\n� KolibriOS MineSweeper v0.52 �" ? print "\n� (C) Leency (leency@mail.ru) 2010,2011 �" ? 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 = 2, // ����� ���� 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<ncx; x++) { for (y=0; y<ncy; y++) { IF (get_value(x, y) == MINE) { set_mark(x, y, FALSE); // ����� ���� open_square(x, y); } ELSE IF (get_mark(x, y) == 1) // ���� ���� ���, � ������ ���� { EBX = XPX * x + XST; // x left ECX = EBX + XPX - 1; // x right EBX <<= 16; EBX += ECX; $PUSH EBX ECX = YPX * y + YST; // y top $PUSH ECX EDX = ECX + YPX - 1; // y bottom ECX <<= 16; ECX += EDX; sys_draw_line(EBX, ECX, clBlack); $POP EDX ECX = EDX + YPX - 1; ECX <<= 16; ECX += EDX; $POP EBX sys_draw_line(EBX, ECX, clBlack); CONTINUE; } } } } // end_game void main() { new_game(); draw_window(); mouse_enable(); while() { switch (sys_wait_event_timeout(100)) // wait for 1 second { case evReDraw: draw_window(); continue; case evKey: IF (sys_get_key() == 27) sys_exit_process(); continue; case evButton: EAX = sys_get_button_id(); IF (EAX == 911) // new game { new_game(); draw_squares(); draw_time(); draw_minesi(); } ELSE IF (EAX == 1001) // change mode { // mode++; mode%=3; mode++; EAX = mode; EAX++; EAX = EAX%3; EAX++; mode = AL; new_game(); window_move_size(OLD,OLD,xsize,ysize); CONTINUE; } // ELSE IF (EAX == 1002) // { // start_uf(); // } ELSE IF (EAX == 1) // close window sys_exit_process(); CONTINUE; case evMouse: IF (!mouse_en) // is mouse enabled ? CONTINUE; do_mouse(); // wait for mouse release - ����� ���������� ������ WHILE (sys_read_mouse(2) == mouse_status) { check_timer(); sys_delay(3); CONTINUE; } check_timer(); IF (stop_game) // disable mouse if game is stopped mouse_en = FALSE; CONTINUE; } check_timer(); sys_delay(2); } } // main