// // 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=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=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();