You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
608 lines
11 KiB
608 lines
11 KiB
// |
|
// 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(); |
|
|
|
|
|
|