0,0 → 1,468 |
/******************************************************************************* |
|
MenuetOS MineSweeper |
Copyright (C) 2003 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 // âêëþ÷èòü ðåæèì âûâîäà ïðåäóïðåæäåíèé |
? pragma option meos |
? jumptomain NONE |
? include "msys.h--" // MenuetOS system functions - ñèñòåìíûå ôóíêöèè MenuetOS |
|
? print "\nÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿" |
? print "\n³ MeOS MineSweeper v0.3 ³" |
? print "\n³ (C) Ivan Poddubny (ivan-yar@bk.ru) 2003 ³" |
? print "\nÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\n\n" |
|
/************************************** DATA **************************************/ |
|
? define XPX 16 // X pixels by square - ðàçìåð êëåòêè â ïèêñåëÿõ |
? define YPX 16 // Y pixels by square |
? define MINE 255 // çíà÷åíèå äëÿ ìèíû â ïîëå value |
|
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; |
|
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) 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(cmines, x, y); |
start_timer(); |
} |
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; |
|
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; |
|
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; |
|
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() |
{ |
sys_delay(5); // for old kernel only! |
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; |
|
// get window position - ïîëó÷èòü êîîðäèíàòû îêíà |
sys_process_info(#procinfo, -1); |
xpos = procinfo.xstart; |
ypos = procinfo.ystart; |
|
// start a new process and terminate this one |
sys_create_thread(#main, ESP); |
sys_exit_process(); |
} |
//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(6); |
CONTINUE; |
} |
check_timer(); |
IF (stop_game) // disable mouse if game is stopped |
mouse_en = FALSE; |
CONTINUE; |
} |
check_timer(); |
sys_delay(2); |
} |
} // main |