|
|
// // MineSweeper By Andriy Doroshchuk //
global cursorOverClosed = CA.F_RED | CA.F_INTENSITY | CA.B_BLACK | CA.TRAILING_BYTE; global cursorOverOpened = CA.F_RED | CA.F_INTENSITY | CA.B_BLUE | CA.TRAILING_BYTE; global frameColor = CA.F_RED | CA.F_GREEN | CA.F_BLUE | CA.B_BLACK | CA.TRAILING_BYTE; global closedColor = CA.F_BLUE | CA.B_BLACK | CA.TRAILING_BYTE; global openedColor = CA.F_BLUE | CA.B_BLUE | CA.TRAILING_BYTE; global numberColor = CA.F_BLUE | CA.F_GREEN| CA.F_INTENSITY | CA.B_BLUE | CA.TRAILING_BYTE; global markColor = CA.F_BLUE | CA.F_RED | CA.F_INTENSITY | CA.B_BLUE | CA.TRAILING_BYTE; global mineColor = CA.F_GREEN| CA.F_RED | CA.B_BLUE | CA.TRAILING_BYTE; global helpColor = CA.F_GREEN| CA.F_RED | CA.F_BLUE |CA.B_BLUE | CA.TRAILING_BYTE; global winColor = CA.F_GREEN| CA.F_INTENSITY | CA.B_BLACK | CA.TRAILING_BYTE; global looseColor = CA.F_RED | CA.F_INTENSITY | CA.B_BLACK | CA.TRAILING_BYTE;
// wait till key will be released global WaitForKey = function(key) { for (;ISPRESSED(key);){} };
// print debug message global DebugText = function(text) { CATTRIB(frameColor); XYTEXT(0, 0, text); };
game = table( x = 15, y = 0, lx = 30, ly = 15, mineCurr = 0, mineMax = 10, currLevel = 2, cX = 0, cY = 0,
field = table(),
// index in the field Index = function(x, y) { return (y*.lx+x); },
// draw field frame DrawFrame = function() { i;
// set color CATTRIB(frameColor);
// borders for (i=.x+1; i<.x+.lx+1; i=i+1) { XYTEXT(i, .y, "-"); XYTEXT(i, .y+.ly+1, "-"); } for (i=.y+1; i<.y+.ly+1; i=i+1) { XYTEXT(.x, i, "|"); XYTEXT(.x+.lx+1, i, "|"); }
// corners XYTEXT(.x, .y, "\1"); XYTEXT(.x+.lx+1, .y, "\1"); XYTEXT(.x, .y+.ly+1, "\1"); XYTEXT(.x+.lx+1, .y+.ly+1, "\1");
// count XYTEXT(.x+3, .y, "[" + .mineCurr.String() + ":" + .mineMax.String() + "]"); },
// field cell drawing DrawCell = function(x, y, cursor) { index = .Index(x, y); // debug cell = .field[index].String(); cell = " ";
// closed cell if (.field[index] < 10) { if (cursor) { CATTRIB(cursorOverClosed); cell = "W"; } else { CATTRIB(closedColor); } } // opened cell else if (.field[index] < 20) { if (.field[index] == 10) { if (cursor) { CATTRIB(cursorOverOpened); cell = "W"; } else { CATTRIB(openedColor); } } else if (.field[index] < 19) { if (cursor) { CATTRIB(cursorOverOpened); } else { CATTRIB(numberColor); } val = .field[index] % 10; cell = val.String(); } else { CATTRIB(mineColor); cell = "@"; } } // intended mine else { if (cursor) { CATTRIB(cursorOverOpened); } else { CATTRIB(markColor); } cell = "?"; }
XYTEXT(.x+x+1, .y+y+1, cell); },
// field cell drawing DrawCurrCell = function(cursor) { .DrawCell(.cX, .cY, cursor); },
// field drawing DrawField = function() { i; j;
.DrawFrame(); for (i=0; i<.lx; i=i+1) { for (j=0; j<.ly; j=j+1) { .DrawCell(i, j, 0); } } },
// help string HelpString = function(msg, line, mode) { if (mode == 1) { CATTRIB(CA.F_BLUE | CA.F_GREEN | CA.F_INTENSITY | CA.B_BLACK | CA.TRAILING_BYTE); } else if (mode == 2) { CATTRIB(CA.F_RED | CA.B_BLACK | CA.TRAILING_BYTE); } else { CATTRIB(CA.F_GREEN | CA.B_BLACK | CA.TRAILING_BYTE); }
XYTEXT(0, 25-line, " "); XYTEXT((80-msg.Length())/2, 25-line, msg); },
// Initialise field InitField = function(level) { i; j; t1;t2; count; position; index;
// clear screen CATTRIB(frameColor); CLS();
// set current level .currLevel = level;
// field extents if (level == 1) { .lx = 10; .ly = 10; .mineMax = 8; } else if (level == 2) { .lx = 18; .ly = 15; .mineMax = 35; } else { .lx = 30; .ly = 15; .mineMax = 90; } .x = (80-.lx)/2; .mineCurr = 0;
// init field contents max = .lx*.ly; for (i=0; i<max; i=i+1) { .field[i] = 0; }
// put mines on the field for (count=1; count<=.mineMax; count=count+1) { position = randint(0, .lx*.ly+1-count); for (i=0; i<.lx; i=i+1) { for (j=0; j<.ly; j=j+1) { index = .Index(i, j); if (.field[index] == 0) { if (position == 0) { .field[index] = 9; i = .lx; j = .ly; } else { position = position - 1; } } } } }
// calculate mines environment for (i=0; i<.lx; i=i+1) { for (j=0; j<.ly; j=j+1) { if (.field[.Index(i, j)] == 9) { for (t1=i-1; t1<i+2; t1=t1+1) { for (t2=j-1; t2<j+2; t2=t2+1) { if ((t1!=i || t2!=j) && (t1>=0) && (t1<.lx) && (t2>=0) && (t2<.ly)) { index = .Index(t1, t2); if (.field[index] < 9) { .field[index] = .field[index] + 1; } } } } } } }
// draw field frame .DrawFrame();
// set current cell .cX=.lx/2; .cY=.ly/2; .DrawField(); .DrawCell(.cX, .cY, 1);
.HelpString("", 4, 0); .HelpString("F2 - beginner. F3 - intermediate. F4 - expert", 2, 0); .HelpString("Enter - open. Space - mark as a mine. Backspace - open around.", 1, 0); },
// restart current game RestartField = function() { .InitField(.currLevel); },
// restart game after finishing Restart = function(win) { .HelpString("", 2, 0); .HelpString("", 1, 0);
if (win) { .HelpString("Congratulations, you won! Press F1 to continue.", 4, 1); for (; !ISPRESSED(112);){} } else { .HelpString("Sorry, you are dead! Press F1 to continue.", 4, 2); .DrawField(); } for (; !ISPRESSED(112);){}
.RestartField(); },
// field opening when open an empty cell CheckCell = function(x, y) { i; j; index = .Index(x, y);
if (.field[index] == 0) { .field[index] = 10;
// check surrounding for (i=x-1; i<x+2; i=i+1) { for (j=y-1; j<y+2; j=j+1) { if ((i!=x || j!=y) && (i>=0) && (i<.lx) && (j>=0) && (j<.ly)) { .CheckCell(i, j); } } } } else { if (.field[index] < 9) { .field[index] = .field[index] + 10; } }
.DrawCell(x, y, 0); },
// check win condition CheckWin = function() { i; j; index; count = 0; for (i=0; i<.lx; i=i+1) { for (j=0; j<.ly; j=j+1) { index = .Index(i, j); if (.field[index] < 10) { count = 0; i = .lx; j = .ly; } else if (.field[index] >= 20) { count = count + 1; } } }
if (count == .mineMax) { .DrawCell(.cX, .cY, 0); .Restart(1); } else { .DrawCell(.cX, .cY, 1); } },
// open field cell OpenCell = function(x, y, check) { i; j; index = .Index(x, y); if (!check) { if (.field[index] >= 20) { return; } }
// check the field if (check && (.field[index] % 10) == 9) { for (i=0; i<.lx; i=i+1) { for (j=0; j<.ly; j=j+1) { index = .Index(i, j); .field[index] = (.field[index] % 10) + 10; } }
.Restart(0); } else { .CheckCell(x, y); .CheckWin(); } },
// open cells around open mine HelperCell = function() { i; j; index = .Index(.cX, .cY);
// perform the action only if the cell is already open if (.field[index]>=10 && .field[index]<20) { // calculate mines around this cell mines = 0; for (i=.cX-1; i<.cX+2; i=i+1) { for (j=.cY-1; j<.cY+2; j=j+1) { if ((i!=.cX || j!=.cY) && (i>=0) && (i<.lx) && (j>=0) && (j<.ly)) { index = .Index(i, j); if (.field[index] >= 20) { mines = mines + 1; } } } }
// check that we can open index = .Index(.cX, .cY); if (mines == (.field[index] % 10)) { for (i=.cX-1; i<.cX+2; i=i+1) { for (j=.cY-1; j<.cY+2; j=j+1) { if ((i!=.cX || j!=.cY) && (i>=0) && (i<.lx) && (j>=0) && (j<.ly)) { .OpenCell(i, j, 0); } } } } } },
// move cursor Move = function(dir) { .DrawCurrCell(0); if (dir == 1) { if (.cY > 0) { .cY = .cY - 1; } } else if (dir == 3) { if (.cY<.ly-1) { .cY = .cY + 1; } } else if (dir == 0) { if (.cX > 0) { .cX = .cX - 1; } } else if (dir == 2) { if (.cX<.lx-1) { .cX = .cX + 1; } } WaitForKey(37+dir); .DrawCurrCell(1); },
// open current cell Open = function() { WaitForKey(13); .OpenCell(.cX, .cY, 1); },
// mark current cell Mark = function() { WaitForKey(32); index = .Index(.cX, .cY); if (.field[index] < 10) { .field[index] = (.field[index] % 10) + 20; .mineCurr = .mineCurr + 1; .DrawFrame(); .CheckWin(); } else if (.field[index] >= 20) { .field[index] = .field[index] % 10; .mineCurr = .mineCurr -1; .DrawFrame(); .DrawCurrCell(1); } },
// init the game Run = function() { CURSOR(0, 0); .RestartField();
for (;!ISPRESSED(27);) { if (ISPRESSED(37)) { .Move(0); } else if (ISPRESSED(38)) { .Move(1); } else if (ISPRESSED(39)) { .Move(2); } else if (ISPRESSED(40)) { .Move(3); } else if (ISPRESSED(32)) { .Mark(); } else if (ISPRESSED(13)) { .Open(); } else if (ISPRESSED(8)) { .HelperCell(); WaitForKey(8); } else if (ISPRESSED(113)) { WaitForKey(113); .InitField(1); } else if (ISPRESSED(114)) { WaitForKey(114); .InitField(2); } else if (ISPRESSED(115)) { WaitForKey(115); .InitField(3); } else { DebugText(" "); } } }
);
game.Run();
|