rem MindMaster rem rem Author: Jacob Busby rem Jacob.Busby@hants.gov.uk rem rem Known bugs: rem rem Flicker effort on Go (DIGITS * 3) - 4. Probably rem fixable with double-buffering. rem rem String manipulation could probably be improved. rem rem Contols: rem rem Up, Down, Left, Right to choose digits. rem Shoulder buttons to move all digits to the rem left/right up/down. rem X to confirm Guess. rem Use PICK = TRUE for two player version. (See notes) rem rem Change History rem rem 21/04/01 Initial development complete rem 23/04/01 Comments added for code clarity. rem 03/05/01 Shoulder buttons added. rem Sanity variables: Define Truth/Falsehood TRUE = 1 FALSE = 0 rem PS2 controller variables EX = 16384 OH = 8192 UP = 16 DOWN = 64 LEFT = 128 RIGHT = 32 R1 = 2048 L1 = 1024 L2 = 256 R1 = 2048 R2 = 512 rem Control variables rem rem DEBUG switches on/off crude debugging mode rem (You may also wish to use PICK as well) rem DIGITS is the number of digits the player has to guess rem MAXGOES is the number of guesses the player gets rem PICK switches on/off the ability to pick own digits. rem (See below for full details) rem SCORING switches on/off the score facility. (NB With rem the variables DIGITS: 5, MAXGOES: 10, BLACK: 2 and rem WHITE: 1 you get a percentile score) FWIW My high rem score is 77. rem BLACK is the score awarded for a black peg. rem WHITE is the score awarded for a white peg. DEBUG = FALSE DIGITS = 5 MAXGOES = 10 PICK = FALSE SCORING = TRUE BLACK = 2 WHITE = 1 rem Screen variables XSIZE = 640 YSIZE = 512 X_OFFSET = 100 Y_OFFSET = 100 LINESIZE = 20 FLASHLENGTH = 0.05 rem If you want to pick your own digits use these values rem here. You may need to add extra PICK(x) variables, if rem you use more than five digits. (Effectively, this is rem the two-player version of the game) rem rem NB These variables are only used if PICK is TRUE. dim PICK(DIGITS) PICK(1) = 0 PICK(2) = 0 PICK(3) = 0 PICK(4) = 0 PICK(5) = 0 rem That's the global variables done. Let us play!!! Main() rem *** GAME ROUTINES *** rem ------------------------------------------------------ rem main rem rem This is the primary routine, from which everything rem else is run from. rem ------------------------------------------------------ sub Main() label GameStart Set_Up() Generate_Hidden_String() Go = 0 Display_Current_Board(Hidden$) while ((Win = FALSE) and (Go < MAXGOES)) Go = Go + 1 Determine_Guess() Evaluate_Guess() wend Game_Over() rem If the player is playing the PS2 then restart. if PICK = FALSE then goto GameStart fi end sub rem ------------------------------------------------------ rem Display_Current_Board rem rem This routine displays the current contents of the rem array board$. It effectively changes the current line rem in board$ by reading the text$ variable passed to it rem into board$(x), where x is the second variable passed rem to it. rem rem The board is offset by global variables (X_OFFSET, rem Y_OFFSET). The size of each line is determined by a rem third global variable, LINESIZE. rem ------------------------------------------------------ sub Display_Current_Board(Text$,Which) clear window Board$(Which + 1) = Text$ for Count = 1 to (MAXGOES + 1) if Board$(Count) <> "" then text X_OFFSET,Y_OFFSET + (Count * LINESIZE),Board$(Count) fi next Count end sub rem ------------------------------------------------------ rem Determine_Guess() rem rem This routine allows the player to choose their guess rem in arcade "Enter your name" fashion. rem ------------------------------------------------------ sub Determine_Guess() rem This section is used to prevent "Press X and miss rem three goes" syndrome. while (KeyPress = EX) KeyPress = peek("port1") wait 0.05 wend rem Let the player choose a new value. while (KeyPress <> EX) KeyPress = peek("port1") if (KeyPress = UP) then Guess_No(Current_Digit) = Guess_No(Current_Digit) + 1 if Guess_No(Current_Digit) > 9 then Guess_No(Current_Digit) = 0 fi elsif (KeyPress = DOWN) then Guess_No(Current_Digit) = Guess_No(Current_Digit) - 1 if Guess_No(Current_Digit) < 0 then Guess_No(Current_Digit) = 9 fi elsif (KeyPress = LEFT) then Current_Digit = Current_Digit - 1 if Current_Digit < 1 then Current_Digit = DIGITS fi elsif (KeyPress = RIGHT) then Current_Digit = Current_Digit + 1 if Current_Digit > DIGITS then Current_Digit = 1 fi elsif (KeyPress = R1) then for Digit = Current_Digit to DIGITS Guess_No(Digit) = Guess_No(Digit) + 1 if Guess_No(Digit) > 9 then Guess_No(Digit) = 0 fi next Digit elsif (KeyPress = L1) then for Digit = 1 to Current_Digit Guess_No(Digit) = Guess_No(Digit) + 1 if Guess_No(Digit) > 9 then Guess_No(Digit) = 0 fi next Digit elsif (KeyPress = R2) then for Digit = Current_Digit to DIGITS Guess_No(Digit) = Guess_No(Digit) - 1 if Guess_No(Digit) < 0 then Guess_No(Digit) = 9 fi next Digit elsif (KeyPress = L2) then for Digit = 1 to Current_Digit Guess_No(Digit) = Guess_No(Digit) - 1 if Guess_No(Digit) < 0 then Guess_No(Digit) = 9 fi next Digit fi wait 0.2 rem Flash the current digit, so that the player knows rem which digit they are altering. Guess$ = left$(str$(Go) + " ",4) for Index = 1 to DIGITS if Index = Current_Digit then Guess$ = Guess$ + " " + " " else Guess$ = Guess$ + str$(Guess_No(Index)) + " " fi next Index Guess$ = rtrim$(Guess$) Display_Current_Board(Guess$, Go) wait FLASHLENGTH rem Display the current guess. Guess$ = left$(str$(Go) + " ",4) for Index = 1 to DIGITS Guess$ = Guess$ + str$(Guess_No(Index)) + " " next Index Guess$ = trim$(Guess$) Display_Current_Board(Guess$, Go) wend end sub rem ------------------------------------------------------ rem Evaluate_Guess() rem rem This sub-routine determines how much of the players rem guess is correct. Scoring is defined as White if a rem peg is the correct value, but in the wrong location, rem and Black, if both value and location are correct. rem Black takes precedence over White. rem rem The score is determined by the global variables, rem BLACK and WHITE. rem ------------------------------------------------------ sub Evaluate_Guess() dim Guess_Histogram(10) Black = 0 White = 0 rem Build a blank Histogram for the current guess for Index = 1 to 10 Guess_Histogram(Index) = 0 next Index rem Work through each digit of the guess in turn. Add to rem the guess histogram, then score a black peg if the rem value matches a corresponding value in the hidden rem number. In this instance check that this peg is not rem also marked as a white peg. rem rem If the peg is not black compare histograms to see if rem it should be marked as a white peg instead. rem rem NB Zero is mapped to ten in the histograms. for Index = 1 to DIGITS Guess_Histogram(Guess_No(Index)) = Guess_Histogram(Guess_No(Index)) + 1 if Guess_No(Index) = 0 then Guess_Histogram(10) = Guess_Histogram(10) + 1 fi if Guess_No(Index) = Hidden_No(Index) then Black = Black + 1 if Guess_No(Index) = 0 then if Guess_Histogram(10) > Histogram(10) then White = White - 1 fi elsif Guess_Histogram(Guess_No(Index)) > Histogram(Guess_No(Index)) then White = White - 1 fi elsif Guess_Histogram(Guess_No(Index)) <= Histogram(Guess_No(Index)) then White = White + 1 elsif Guess_No(Index) = 0 then if Guess_Histogram(10) <= Histogram(10) then White = White + 1 fi fi next Index rem In DEBUG mode show the entire histogram. if DEBUG = TRUE then Guess$ = Guess$ + " " for Index = 1 to 10 Guess$ = Guess$ + str$(Guess_Histogram(Index)) + " " next Index Guess$ = rtrim$(Guess$) fi if Black = DIGITS then Win = TRUE Score = Score + (BLACK * (DIGITS * (MAXGOES - Go))) fi Score = Score + (WHITE * White) + (BLACK * Black) rem Show the number of Black/White pegs. Guess$ = Guess$ + " " + str$(Black) + " " + str$(White) if SCORING = TRUE then Guess$ = Guess$ + right$(" " + str$(Score),8) fi Display_Current_Board(Guess$, Go) end sub rem ------------------------------------------------------ rem Generate_Hidden_String rem rem This routine generates the hidden string, dependent rem on whether the PICK variables are used or not. In the rem latter case random integers are generatd instead. rem ------------------------------------------------------ sub Generate_Hidden_String() dim Histogram(10) dim Hidden_No(DIGITS) rem Build/Blank a histogram (bar-chart) for storing how rem many of each digit have been used. for Index = 1 to 10 Histogram(Index) = 0 next Index rem Create the hidden string. Hidden$ = "- " for digit = 1 to DIGITS Random_No = int(ran(10)) if PICK = TRUE then Random_No = PICK(digit) fi Histogram(Random_No) = Histogram(Random_No) + 1 if Random_No = 0 then Histogram(10) = Histogram(10) + 1 fi Hidden_No(digit) = Random_No if DEBUG = TRUE then Hidden$ = Hidden$ + " " + str$(Random_No) else Hidden$ = Hidden$ + " X" fi next digit rem DEBUG means we display the histogram as well. if DEBUG = TRUE then Hidden$ = Hidden$ + " " for Index = 1 to 10 Hidden$ = Hidden$ + str$(Histogram(Index)) + " " next Index fi Hidden$ = trim$(Hidden$) Hidden$ = Hidden$ + " B W" if SCORING = TRUE then Hidden$ = Hidden$ + " Score" fi end sub rem ------------------------------------------------------ rem Game_Over rem rem This routine is run when the game is over. rem ------------------------------------------------------ sub Game_Over() rem Determine the text based on whether the player won or rem not. if Win = TRUE then Game_Over$ = "You won in " + str$(Go) + " turn(s). Press O to continue." else Game_Over$ = "You lost after " + str$(Go) + " turn(s). Press O to continue." fi rem Reveal the hidden value. (Unnecessary in DEBUG mode) if DEBUG = FALSE then Hidden$ = "- " for Index = 1 to DIGITS Hidden$ = Hidden$ + str$(Hidden_No(Index)) + " " next Index Hidden$ = trim$(Hidden$) + " B W" if SCORING = TRUE then Hidden$ = trim$(Hidden$) + " Score" fi Display_Current_Board(Hidden$,0) fi rem Tell the player that they won/lost. text X_OFFSET,Y_OFFSET + ((Go + 3) * LINESIZE),Game_Over$ rem Press O to continue... KeyPress = peek("port1") while (KeyPress <> OH) KeyPress = peek("port1") wait 0.05 wend end sub rem *** ADMINISTRATION ROUTINES *** rem ------------------------------------------------------ rem Set_Up rem rem A shell routine pointing to each of the set up rem routines in turn. rem ------------------------------------------------------ sub Set_Up() Set_Up_Variables() Set_Up_Screen() end sub rem ------------------------------------------------------ rem Set_Up_Variables rem rem This routine sets up variable defaults. rem ------------------------------------------------------ sub Set_Up_Variables() Win = FALSE Score = 0 Current_Digit = 1 dim Guess_No(DIGITS) dim Board$(MAXGOES + 1) rem The first guess will always be made up of zeroes. for Index = 1 to DIGITS Guess_No(Index) = 0 next Index rem The board string array holds the contents of the rem current game. for Index = 1 to (MAXGOES + 1) Board$(Index) = "" next Index end sub rem ------------------------------------------------------ rem Set_Up_Screen rem rem This routine prepares the screen for graphical output. rem ------------------------------------------------------ sub Set_Up_Screen() close window open window XSIZE, YSIZE buffer = 0 setdrawbuf buffer setrgb 0, 0, 0, 0 clear window end sub