!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! ! MINE ! ! ! ! Mine is the classic game where a field of hidden mines is presented, and the ! ! user tries to find the mines based on mine counts in adjacent squares. ! ! ! ! Derived from the Pascal version. ! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! helper defines false% = 0 true% = -1 ! colors black% = 0 white% = 1 red% = 2 green% = 3 blue% = 4 cyan% = 5 yellow% = 6 magenta% = 7 ! events etchar% = 0 ! ANSI character returned etup% = 1 ! cursor up one line etdown% = 2 ! down one line etleft% = 3 ! left one character etright% = 4 ! right one character etleftw% = 5 ! left one word etrightw% = 6 ! right one word ethome% = 7 ! home of document ethomes% = 8 ! home of screen ethomel% = 9 ! home of line etend% = 10 ! end of document etends% = 11 ! end of screen etendl% = 12 ! end of line etscrl% = 13 ! scroll left one character etscrr% = 14 ! scroll right one character etscru% = 15 ! scroll up one line etscrd% = 16 ! scroll down one line etpagd% = 17 ! page down etpagu% = 18 ! page up ettab% = 19 ! tab etenter% = 20 ! enter line etinsert% = 21 ! insert block etinsertl% = 22 ! insert line etinsertt% = 23 ! insert toggle etdel% = 24 ! delete block etdell% = 25 ! delete line etdelcf% = 26 ! delete character forward etdelcb% = 27 ! delete character backward etcopy% = 28 ! copy block etcopyl% = 29 ! copy line etcan% = 30 ! cancel current operation etstop% = 31 ! stop current operation etcont% = 32 ! continue current operation etprint% = 33 ! print document etprintb% = 34 ! print block etprints% = 35 ! print screen etfun% = 36 ! function key etmenu% = 46 ! display menu etmouba% = 47 ! mouse button assertion etmoubd% = 51 ! mouse button deassertion etmoumov% = 55 ! mouse move ettim% = 56 ! timer matures etjoyba% = 57 ! joystick button assertion etjoybd% = 58 ! joystick button deassertion etjoymov% = 59 ! joystick move etterm% = 60 ! terminate program ! program defines maxxs% = 8 ! size of grid maxys% = 8 maxmine% = 10 ! number of mines to place dim mine%(maxxs%, maxys%) ! mine exists map dim vis%(maxxs%, maxys%) ! square is uncovered map dim flag%(maxxs%, maxys%) ! square is flagged map ! Contruct table to calculate adjacent squares dim xoff%(8) ! x offset table dim yoff%(8) ! y offset table xoff%(1) = 0: yoff%(1) = -1 ! up xoff%(2) = +1: yoff%(2) = -1 ! upper right xoff%(3) = +1: yoff%(3) = 0 ! right xoff%(4) = +1: yoff%(4) = +1 ! lower right xoff%(5) = 0: yoff%(5) = +1 ! down xoff%(6) = -1: yoff%(6) = +1 ! lower left xoff%(7) = -1: yoff%(7) = 0 ! left xoff%(8) = -1: yoff%(8) = -1 ! upper left ! declares, not required but nice dim x%, y% ! user move coordinates dim done% ! game over dim centerx% ! center of screen position x dim centery% ! center of screen position y dim cursorx% ! cursor location x dim cursory% ! cursor location y dim badguess% ! bad guess display flag dim mousex% ! mouse position x dim mousey% ! mouse position y !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Find adjacent mines ! ! Finds the number of mines adjacent to a given square. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function adjacent%(x%, y%) dim mines% ! number of mines dim xn%, yn% ! neighbor coordinates } dim i% ! index for move array } mines% = 0 ! clear mine count for i% = 1 to 8 ! process points of the compass xn% = x%+xoff%(i%) ! find neighbor locations yn% = y%+yoff%(i%) if xn% >= 1 and xn% <= maxxs% and yn% >= 1 and yn% <= maxys% then ! valid location if mine%(xn%, yn%) then mines% = mines%+1 ! count mines endif next i% endfunc mines% ! return the number of mines !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Set adjacent squares visable ! ! Sets all of the valid adjacent squares visable. If any of those squares are ! not adjacent to a mine, then the neighbors of that square are set visable, etc. ! (recursively). ! This is done to "rip" grids of obviously empty neighbors off the board. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure visadj(x%, y%) dim xn%, yn% ! neighbor coordinates dim i% ! index for move array for i% = 1 to 8 ! process points of the compass xn% = x%+xoff%(i%) ! find neighbor locations yn% = y%+yoff%(i%) if xn% >= 1 and xn% <= maxxs% and yn% >= 1 and yn% <= maxys% then if not vis%(xn%, yn%) then ! not already visable ! valid location vis%(xn%, yn%) = true% ! set visable if adjacent%(xn%, yn%) = 0 then visadj(xn%, yn%) ! perform recursively endif endif next i% endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Display board ! ! Displays the playing board. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure display dim x% dim y% dim cnt% ! count of adjacent mines ! scan screen bcolor(yellow%) ! set background color for y% = 1 to maxys% for x% = 1 to maxxs% cursor(centerx%+x%-1, centery%+y%-1) ! set start of next line if vis%(x%, y%) then if mine%(x%, y%) then print "*"; else cnt% = adjacent%(x%, y%) ! find adjacent mine count if cnt% = 0 then print "." ! no adjacent else print chr$(cnt%+asc("0")); ! place the number endif endif else if flag%(x%, y%) then ! display flagged location if badguess% then print "X"; else print "M"; else print "="; endif next x% next y% print endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Initalize board ! ! Clears all board squares to no mines, invisible and not flagged. ! Then, the specified number of mines are layed on the board at random. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure clrbrd dim x% dim y% dim n% for x% = 1 to maxxs% ! clear minefield for y% = 1 to maxys% mine%(x%, y%) = false ! set no mine vis%(x%, y%) = false ! set not visible flag%(x%, y%) = false ! set not flagged next y% next x% for n% = 1 to maxmine ! place mine repeat x% = rnd(0)*maxxs% y% = rnd(0)*maxys% until not mine%(x%, y%) ! no mine exists at square mine%(x%, y%) = true ! place mine next n% endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Clear line ! ! Clears the specified line to spaces in the specified color. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure clrlin(y%, clr%) dim i% cursor(1, y%) ! position to specified line bcolor(clr%) ! set color for i% = 1 to maxx% do print " "; ! clear line endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Print centered string ! ! Prints the given string centered on the given line. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure prtmid(y%, s$) cursor(maxx% div 2-len(s$) div 2, y%) ! position to start print s$; ! output the string endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Draw character box ! ! Draws a box of the given color and character to the location. ! The colors are not saved or restored. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure tbox(sx%, sy%, ex%, ey%, c$, bclr%, fclr%) dim x%, y% ! coordinates bcolor(bclr%) fcolor(fclr%) cursor(sx%, sy%) ! position at box top left for x% = sx% to ex%: print c$;: next x% ! draw box top cursor(sx%, ey%) ! position at box lower left for x% = sx% to ex%: print c$;: next x% ! draw box bottom for y% = sy%+1 to ey%-1 ! draw box left side cursor(sx%, y%) ! place cursor print c$; ! place character next y% for y% = sy%+1 to ey%-1 ! draw box left side cursor(ex%, y%) ! place cursor print c$; ! place character next y% endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Check coordinates on board ! ! Checks if the given x, y coordinates are in the valid playing area.. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function insquare%(x%, y%) dim inx% ! inside x dim iny% ! inside y inx% = mousex% >= centerx% and mousex% <= centerx%+maxxs%-1 ! find x iny% = mousey% >= centery% and mousey% <= centery%+maxys%-1 ! find y endfunc inx% and iny% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Check replay ! ! Asks the user if a replay is desired, then either cancels the game, or ! sets up a new game as requested. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure replay ! ask user for replay bcolor(cyan%) prtmid(maxy%, "PLAY AGAIN (Y/N) ?") repeat ! wait for response ! wait till a character is pressed repeat event(nextevent) until nextevent.etype = etchar% or nextevent.etype = etterm% if nextevent.etype = etterm% then done% = true% ! force a quit until lcase(nextevent.char$) = "y" or lcase(nextevent.char) = "n" or done% if lcase(nextevent.char$) = "n" or done% then done% = true% else ! clear old messages clrlin(maxy%-2, cyan%) clrlin(maxy%, cyan%) ! start new game clrbrd ! set up board cursorx% = centerx% ! set inital cursor position cursory% = centery% badguess% = false% ! set bad guesses invisible endif endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Process square "hit" ! ! Processes a "hit" on a square, which means revealing that square, and possibly ! triggering a mine. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! procedure hit(x%, y%) dim xi%, yi% ! indexes for board dim viscnt% ! visable squares count vis%(x%, y%) = true% ! set that location visable if mine%(x%, y%) then ! mine found ! make all mines visable, and bad guesses too. for yi% = 1 to maxys% for xi = 1 to maxxs% if mine%(xi%, yi%) then vis%(xi%, yi%) = true% next xi% next yi% badguess% = true% ! set bad guesses visable display ! redisplay board ! announce that to the player bcolor(red%) prtmid(maxy%-2, "*** YOU HIT A MINE ! ***") replay ! process replay else ! valid hit if adjacent%(x%, y%) = 0 then visadj(x%, y%) ! clean up adjacent spaces ! now, the player may have won. we find this out by counting all of the ! visable squares, and seeing if the number of squares left is equal ! to the number of mines viscnt% = 0 for yi% = 1 to maxys% for xi% = 1 to maxxs% if vis%(xi%, yi%) then viscnt% = viscnt%+1 ! count visible next xi% next yi% if maxxs%*maxys%-viscnt% = maxmine% then ! player wins display ! redisplay board ! announce that to the player bcolor(red%) prtmid(maxy%-2, "*** YOU WIN ! ***") replay ! process replay endif endif display ! redisplay board endproc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Main process ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! auto(false%) ! turn off scrolling bcolor(cyan%) ! color the background clear ! clear to that bcolor(magenta%) prtmid(1, "******* Mine game 1.0 ********") ! output title ! find center board position centerx% = maxx% div 2-maxxs% div 2 centery% = maxy% div 2-maxys% div 2 ! draw a border around that tbox(centerx%-1, centery%-1, centerx%+maxxs%, centery%+maxys%, " ", blue%, black%) bcolor(white%) ! restore the background clrbrd ! set up board display ! display board } done% = false% ! set game in progress cursorx% = centerx% ! set inital cursor position cursory% = centery% badguess% = false% ! set bad guesses invisible repeat ! enter user moves cursor(cursorx%, cursory%) ! place cursor x% = cursorx%-centerx%+1 ! set location on board y% = cursory-centery+1 event(nextevent) ! get the next event select nextevent.etype% ! event case ettab% ! process flag ! reverse flagging on location flag(x%, y%) = not flag(x%, y%) display ! redisplay board case etenter%: hit(x%, y%) ! process hit ! move up case etup%: if cursory% > centery% then cursory% = cursory%-1 ! move left case etleft%: if cursorx% > centerx% then cursorx% = cursorx%-1 ! move down case etdown%: if cursory% < centery%+maxys%-1 then cursory% = cursory%+1 ! move right case etright%: if cursorx% < centerx%+maxxs%-1 then cursorx% = cursorx%+1 case etmoumov% ! mouse movement mousex% = nextevent.moupx% ! set new mouse position mousey% = nextevent.moupy% case etmouba ! mouse button 1, hit if nextevent.amoubn% = 1 and onboard%(mousex%, mousey%) then ! mouse postion inside valid square cursorx% = mousex% ! set current position to that cursory% = mousey% x% = cursorx%-centerx%+1 ! set location on board y% = cursory%-centery%+1 hit(x%, y%) ! process hit else if nextevent.amoubn% = 2 and onboard%(mousex%, mousey%) then ! mouse postion inside valid square cursorx% = mousex% ! set current position to that cursory% = mousey% x% = cursorx%-centerx%+1 ! set location on board y% = cursory%-centery%+1 ! reverse flagging on location flag(x%, y%) = flag(x%, y%) display ! redisplay board endif endsel until done% or nextevent.etype% = etterm% ! game complete auto(true%) ! turn off scrolling bcolor(white%) ! restore colors fcolor(black%) clear ! clear screen end