//This program tried to distribute all windows messages just like an
//object oriented language: events are handled according to what window
//they address and what the event type is. There is only one event loop
//for everything. Therefore the program must use certain variables,
//(Game! and PlayerMode&) to decide how to react to the events in different phases
//of the games. This is awkward sometimes, but must be more familiar to VB users.
//The interface is rather simple (and crude), but I was much more interested
//in how to program MakeComputerGuess. So if you want to program games, look there.
//You'll need to peek at FillPossibleTable, and SwitchComputerTurn.
//(And, if some variables are confusing, at Constants.)
//The next game to follow is Nine Men's Morris with some built-in strategy.


//There is no copyright for this game; take parts of it if you like, or just some ideas.
//If you need any further explanation, my CompuServe number is 71021,335.
//You can find me in some programming forums (the GFA area, IBM programming,
//Microsoft BASIC, games).

//Send no shareware fees, please. But if you like some solutions here and you happen
//to have heard about a job involving GFA, VB or Access programming, I'd be most
//grateful if you'd let me know about it...

//The Procedures are in alphabetical order. I found it was easier to locate them.
@Init
DO
  GETEVENT
  IF MENU(11) THEN @Events
LOOP
> PROCEDURE Celebrate(mode|) //Game over in one way or another.
  LOCAL t$=STR$((TIMER-ClockTime%)/1000), dummy|
  LOCAL n$=STR$(G|(0))+STR$(G|(1))+STR$(G|(2))+STR$(G|(3))
  //mode: 0,1: 4 "Blacks" achieved
  //           2:       the Computer guessed the number
  //           3:       the User made a mistake in the answers to the Computer,
  //                     so it is not possible to guess the number.
  SWITCH mode|
  CASE 0,1
    ALERT 3,"Congratulations. The number was:|"+n$+"|You used "+t$+" seconds.",1,"&Ok",dummy|
  CASE 2
    ALERT 3,"Aha, I guessed, using "+t$+" seconds.",1,"&Ok",dummy|
  CASE 3
    ALERT 3,"Due to contradictory answers, no clear solution exists.",1,"&Ok",dummy|
  ENDSWITCH
  Game!=FALSE
  KILLTIMER 1,1
  @UpdateClock
RETURN
> PROCEDURE Constants
  LOCAL i|
  Null$=""
  XOffset&=34,YOffset&=64, YGap&=26,XGap&=50,BWGap&=20 //Board dimensions
  DIM n|(9), G|(3),s|(3),cg|(3),Possible!(3,9),PreviousGuess|(3)     //needed for
  DIM Guess|(9,3),ReWard|(9,1), TempS|(3),TempG|(3)                 //the game

  OPENW #1,10,10,160,374,&X1110000
  TITLEW #1,"MasterMind"
  CTEXT "00:00:00",90,51,4,58,24,WS_BORDER                         //Clock Window
  clock&=DLGITEM(-1,90)

  FOR i|=0 TO 9                                                                              //we'll randomize
    n|(i|)=i|                                                                                        //the order of these
  NEXT i|                                                                                         //to make the Computer's
RETURN                                                                                         //guesses look random

> PROCEDURE DisableEditTexts //so User has just one window for next entry
  LOCAL i|
  FOR i|=0 TO 9
    ~SetWindowLong(DLGITEM(-1,i|+100),GWL_STYLE,DisAbledStyle%)
    _WIN$(DLGITEM(-1,i|+100))="____"
    ~SetWindowLong(DLGITEM(-1,i|+200),GWL_STYLE,DisAbledStyle%)
    _WIN$(DLGITEM(-1,i|+200))="_"
    ~SetWindowLong(DLGITEM(-1,i|+300),GWL_STYLE,DisAbledStyle%)
    _WIN$(DLGITEM(-1,i|+300))="_"
  NEXT i|
RETURN
> PROCEDURE Events                     //All messages are sent here for distribution
  SWITCH MENU(1)
  CASE 4                                        //WM_CLOSE
    @QuitApplication
  CASE 20                                      //Drop-down Menu
    @EventMenu
  ENDSWITCH
  SWITCH MENU(11)
  CASE WM_CHAR                        //Key Pressed
    @EventKeyBoard
  CASE WM_TIMER                       //Clock to be updated every second while playing
    @UpdateClock
  ENDSWITCH
RETURN
> PROCEDURE EventKeyBoard
  //There is a more logical way of distributing events,
  //but with all these Object Oriented Programmig Systems(OOPS) around,
  //why not follow their structure? (this Procedure
  //would be invisible in VB...)
  IF MENU(15)=DLGITEM(-1,Turn&+100)          //Check window handle number
    @EventKeyBoardGuessWindows
  ELSE IF MENU(15)=DLGITEM(-1,0)
    @EventKeyBoardSecretNumberWindow
  ELSE IF (MENU(15)=DLGITEM(-1,Turn&+200))
    @EventKeyBoardHumanInputAnswer(TRUE)
  ELSE IF (MENU(15)=DLGITEM(-1,Turn&+300))
    @EventKeyBoardHumanInputAnswer(FALSE)
  ENDIF
RETURN
> PROCEDURE EventKeyBoardGuessWindows
  LOCAL s$
  IF Game!
    SWITCH PlayerMode&
    CASE 0,1
      IF MENU(12)=13              //Human player hit the Return key: guess completed
        IF @Numeric(DLGITEM(-1,Turn&+100)) THEN SwitchHumanVsAnythingTurn
      ENDIF
    ENDSWITCH
  ENDIF
RETURN
> PROCEDURE EventKeyBoardHumanInputAnswer(black!)
  LOCAL dummy|
  //The Computer is guessing: the Human challenger entered either the Black or the
  //White value. When both are between 0 and 4, we regard the answers complete
  //and compute the next guess.

  IF PlayerMode&<>300 THEN GOTO SkipEventKeyBoardHumanInputAnswer
  IF MENU(12)<>13 THEN GOTO SkipEventKeyBoardHumanInputAnswer

  SWITCH black!
  CASE -1
    IF VAL?(_WIN$(DLGITEM(-1,Turn&+200)))=0 THEN GOTO SkipEventKeyBoardHumanInputAnswer
    ReWard|(Turn&,0)=VAL(_WIN$(DLGITEM(-1,Turn&+200)))
    SWITCH ReWard|(Turn&,0)
    CASE TO -1, 5 TO
      GOTO SkipEventKeyBoardHumanInputAnswer
    ENDSWITCH
    IF VAL?(_WIN$(DLGITEM(-1,Turn&+300)))=0
      ~SetFocus(DLGITEM(-1,Turn&+300))
      GOTO SkipEventKeyBoardHumanInputAnswer
    ENDIF
  DEFAULT
    IF VAL?(_WIN$(DLGITEM(-1,Turn&+300)))=0 THEN GOTO SkipEventKeyBoardHumanInputAnswer
    ReWard|(Turn&,1)=VAL(_WIN$(DLGITEM(-1,Turn&+300)))
    SWITCH ReWard|(Turn&,1)
    CASE TO -1, 5 TO
      GOTO SkipEventKeyBoardHumanInputAnswer
    ENDSWITCH
    IF VAL?(_WIN$(DLGITEM(-1,Turn&+200)))=0
      ~SetFocus(DLGITEM(-1,Turn&+200))
      GOTO SkipEventKeyBoardHumanInputAnswer
    ENDIF
  ENDSWITCH
  SWITCH ReWard|(Turn&,0)
  CASE 4
    @Celebrate(2)
  DEFAULT
    SWITCH ReWard|(Turn&,0)+ReWard|(Turn&,1)
      GOTO SkipEventKeyBoardHumanInputAnswer
    CASE 5 TO
      ALERT 3,"Impossible. Black+White can't exceed 4. Try again.",1,"&Ok",dummy|
      GOTO SkipEventKeyBoardHumanInputAnswer
    ENDSWITCH
  ENDSWITCH

  ~SetWindowLong(DLGITEM(-1,Turn&+200),GWL_STYLE,DisAbledStyle%)
  ~SetWindowLong(DLGITEM(-1,Turn&+300),GWL_STYLE,DisAbledStyle%)
  @FillPossibleTable
  PlayerMode&=2
  ADD ClockTime%,(TIMER-AnswerClockTime%)
  @SwitchComputerTurn

  SkipEventKeyBoardHumanInputAnswer:
RETURN
> PROCEDURE EventKeyBoardSecretNumberWindow
  IF PlayerMode&=100
    @EventHumanInputSecretNumberForHuman
  ELSE IF PlayerMode&=200
    @EventHumanInputSecretNumberForComputer
  ENDIF
RETURN

> PROCEDURE EventHumanInputSecretNumberForComputer
  IF MENU(12)=13
    PlayerMode&=2
    @InitComputerGame
  ENDIF
RETURN
> PROCEDURE EventHumanInputSecretNumberForHuman
  LOCAL s$
  IF MENU(12)=13
    IF @Numeric(DLGITEM(-1,0))
      s$=_WIN$(DLGITEM(-1,0))
      s|(0)=VAL(MID$(s$,1,1))
      s|(1)=VAL(MID$(s$,2,1))
      s|(2)=VAL(MID$(s$,3,1))
      s|(3)=VAL(MID$(s$,4,1))
      PlayerMode&=1
      s$="****"+Null$
      SENDMESSAGE DLGITEM(-1,0),WM_SETTEXT,0,V:s$
      @InitHumanVsAnything
    ENDIF
  ENDIF
RETURN
> PROCEDURE EventMenu
  LOCAL m$=Menu$(MENU(0)), dummy|
  m$=LOWER$(TRIM$(m$))
  IF INSTR(m$,"exit")
    @QuitApplication

  ELSE IF INSTR(m$,"human vs. &computer")
    PlayerMode&=0, Game!=FALSE
    s|(0)=RANDOM(10)
    s|(1)=RANDOM(10)
    s|(2)=RANDOM(10)
    s|(3)=RANDOM(10)
    @DisableEditTexts
    @InitHumanVsAnything

  ELSE IF INSTR(m$,"human vs. human")
    Game!=FALSE
    @HumanInitRandom

  ELSE IF INSTR(m$,"computer &vs. human")
    Game!=FALSE
    @HumanInitComputer

  ELSE IF INSTR(m$,"contents")
    ~WinHelp(WIN(1),"d:\gfw\mm.hlp",HELP_INDEX,0)

  ELSE IF INSTR(m$,"search")
    ~WinHelp(WIN(1),"d:\gfw\mm.hlp",&H105,0)

  ELSE IF INSTR(m$,"on help")
    ~WinHelp(WIN(1),"d:\gfw\mm.hlp",HELP_HELPONHELP,0)

  ELSE IF INSTR(m$,"about")
    ALERT 1,"MM Is a PUBLIC DOMAIN program, no copyright claimed.|Copy, modify or sell it. It was, by the way, written by Steve Philipp in 1995,|written and compiled with GFABASIC 4.30",1,"&Ok", dummy|
  ENDIF
RETURN
> PROCEDURE FillPossibleTable
  LOCAL i|,j|
  IF ReWard|(Turn&,0)+ReWard|(Turn&,1)=0  //no black, no white: all numbers wrong in
    //                                                                   all positions!
    FOR i|=0 TO 3
      FOR j|=0 TO 3
        Possible!(j|,Guess|(Turn&,i|))=FALSE
      NEXT j|
    NEXT i|

  ELSE IF ReWard|(Turn&,0)=0                      //no black: no number is correct where it is
    //                                                                  in this guess.
    FOR i|=0 TO 3
      Possible!(i|,Guess|(Turn&,i|))=FALSE
    NEXT i|
  ENDIF
RETURN
> PROCEDURE GiveAnswerToHuman(Turn&)
  LOCAL g$=_WIN$(DLGITEM(-1,Turn&+100)), i|, b|, w|
  FOR i|=0 TO 3
    G|(i|)=VAL(MID$(g$,SUCC(i|),1))    //convert the Human guess to bytes
  NEXT i|
  IF @ReWard(s|(),G|(),b|,w|)             //ReWard calculates the Blacks & Whites
    @Celebrate(0)                               //and returns TRUE if 4 Blacks gotten
  ELSE
    _WIN$(DLGITEM(-1,Turn&+200))=STR$(b|)
    _WIN$(DLGITEM(-1,Turn&+300))=STR$(w|)
  ENDIF
RETURN
> PROCEDURE HumanInitComputer
  LOCAL dummy|
  @DisableEditTexts
  SENDMESSAGE DLGITEM(-1,0),WM_SETTEXT,0,V:Null$
  ALERT 1,"You can enter a Secret Number into the window|under the clock. Enter four digits!|If you're afraid that I cheat|just write it down on a piece of paper.",1,"&Ok",dummy|
  ~SetWindowLong(DLGITEM(-1,0),GWL_STYLE,NormalStyle%)
  _WIN$(DLGITEM(-1,0))=""
  ~SetFocus(DLGITEM(-1,0))
  PlayerMode&=200                //In this mode he has a chance to enter the secret number
  //                                              in its window to answer easier...
RETURN
> PROCEDURE HumanInitRandom
  LOCAL dummy|
  @DisableEditTexts
  SENDMESSAGE DLGITEM(-1,0),WM_SETTEXT,0,V:Null$
  ALERT 1,"Enter a Secret Number into the window|under the clock. Enter four digits!|Make sure your Opponent can't see it.",1,"&Ok",dummy|
  ~SetWindowLong(DLGITEM(-1,0),GWL_STYLE,NormalStyle%)
  _WIN$(DLGITEM(-1,0))=""
  ~SetFocus(DLGITEM(-1,0))
  ~SetFocus(DLGITEM(-1,0))
  PlayerMode&=100                 //One Player can enter a secret number for another.
RETURN
> PROCEDURE Init
  @Constants
  @InitMenu
  @InitBoard
RETURN
> PROCEDURE InitBoard
  LOCAL y&=YOffset&, i|
  CLS GETNEAREST(50,255,100)
  EDITTEXT "****",0,XOffset&,y&-YGap&,40,24,WS_BORDER
  CTEXT "B",1,XOffset&+XGap&,y&-YGap&,20,24,WS_BORDER
  CTEXT "W",2,XOffset&+XGap&+BWGap&,y&-YGap&,20,24,WS_BORDER

  FOR i|=0 TO 9     //VB has an easy interface, but creating contols like this is not
    //                          very tedious, either... If only we had a DLL for 3 dimensional
    //                          controls and grids and Progress Meters and the like...

    CONTROL "0000",100+i|,"edit",$10810000,XOffset&,y&,40,24
    CONTROL "0",200+i|,"edit",$10810000,XOffset&+XGap&,y&,16,24
    CONTROL "0000",300+i|,"edit",$10810000,XOffset&+XGap&+BWGap&,y&,16,24
    y&+=YGap&
  NEXT i|

  NormalStyle%=GetWindowLong(DLGITEM(-1,0),GWL_STYLE)
  DisAbledStyle%=NormalStyle%|WS_DISABLED
RETURN
> PROCEDURE InitComputerGame
  ~SetWindowLong(DLGITEM(-1,0),GWL_STYLE,DisAbledStyle%)
  @Shuffle                    //randomize the number array (just for show)
  ARRAYFILL G|(),0
  ARRAYFILL Possible!(),TRUE
  ClockTime%=TIMER    //Computer guesses are rather fast, we don't need the Timer
  //                                    messages, we just UpdateClock after every guess
  _WIN$(clock&)="00:00:00"
  Game!=TRUE
  Turn&=-1
  @SwitchComputerTurn
RETURN
> PROCEDURE InitHumanVsAnything
  ~SetWindowLong(DLGITEM(-1,0),GWL_STYLE,DisAbledStyle%)
  _WIN$(DLGITEM(-1,0))="****"
  Turn&=-1
  Game!=TRUE
  SETTIMER 1,1,1000
  ClockTime%=TIMER
  @SwitchHumanVsAnythingTurn
RETURN
> PROCEDURE InitMenu
  LOCAL i&=-1, m$
  MenuData:
  DATA &Game,Human vs. &Computer,&Human vs. Human,Computer &vs. Human,-,&Exit,
  DATA &Help,&Contents,&Search Help...,&Help on Help,-,&About MasterMind,
  DATA ,*
  DIM Menu$(100)
  RESTORE MenuData
  DO
    i&++
    READ m$
    EXIT IF m$="*"
    Menu$(i&)=m$
  LOOP
  MENU Menu$()
RETURN
> PROCEDURE MakeComputerGuess
  LOCAL s$, i&,j|
  //This is the only interesting part of the program.
  SWITCH Turn&
  CASE 0     //Guess is automatic: we have no clue yet.
    Guess|(0,0)=0,Guess|(0,1)=1,Guess|(0,2)=2,Guess|(0,3)=3

  CASE 1     //Same as #0: we should check every possible number for later reference
    IF ReWard|(0,0)+ReWard|(0,1)=4  //but not if the previous guess already got 4 "sticks"!
      FOR i&=0 TO 3                             //in which case all other numbers are impossible!
        FOR j|=4 TO 9
          Possible!(i&,j|)=FALSE
        NEXT j|
      NEXT i&
      GOTO MakeComputerGuessComputed    //Only if the first guess contained all numbers!
    ENDIF                                                          //Otherwise:

    Guess|(1,0)=4,Guess|(1,1)=5,Guess|(1,2)=6,Guess|(1,3)=7

  CASE 2  //Same as CASE 1. Go on mechanically, or, if the first two guesses already contain
    //            all four possible numbers, start "thinking".

    IF ReWard|(0,0)+ReWard|(0,1)+ReWard|(1,0)+ReWard|(1,1)=4
      FOR i&=0 TO 3
        FOR j|=8 TO 9
          Possible!(i&,j|)=FALSE
        NEXT j|
      NEXT i&
      GOTO MakeComputerGuessComputed
    ENDIF

    Guess|(2,0)=8,Guess|(2,1)=9,Guess|(2,2)=8,Guess|(2,3)=9

  DEFAULT
    MakeComputerGuessComputed:
    ChangeLevel|=0                                   //start changing the number at the "ones" position
    //Under DOS or in other Jurassic environment, I would simply make a monster of four
    //nested for/next loops from 0 to 9 (the possible digits for each position), like this:

    // FOR g|(3)=0 to 9
    //      IF Possible!(3,g|(3))
    //         FOR g|(2)=0 to 9
    //             IF Possible!(2,g|(2))
    //                ...

    //but this would mean we would have to put some second event checking command
    //into these loops, and it wouldn't be very Windows-like. The idea is similar though,
    //only the layout is different to allow us to jump in and out of this structure.

    DO UNTIL @ReallyPossible(G|())    //this is the real test. It scans all previous guesses,
      //and checks the following: if the secret number IS our next guess, we would have gotten
      //exactly the same number of black and white sticks as we do when we check the old
      //guesses against the new one. If there is a difference, our guess simply cannot be
      //the right one.
      DO
        G|(ChangeLevel|)++             //therefore we increment a digit, starting from the "ones"
        //                                             and working our way up to the "thousands", since
        //                                             all possible solutions must be between 0000 and 9999,
        //                                             thus giving us 10,000 possibilities
        MustContinue!=FALSE           //this will be necessary a few lines later.
        IF G|(ChangeLevel|)>9           //we exhausted all possibilities in this position: must
          //                                             increment the next digit and iterate through all the
          //                                             lower ones again.
          IF ChangeLevel|=3               //this is the equivalent of NEXT g|(3) (if we used the
            //                                           simple FOR/NEXT solution, where g|(3) is already 10.
            @Celebrate(3)                     //no solution is possible: we reached 9999 without
            //                                           success. The User must have made a mistake in the
            //                                           answers.
            GOTO SkipMakeComputerGuess
          ELSE
            ChangeLevel|++                  //go to the next digit otherwise
            MustContinue!=TRUE          //because we'll have to increment the next digit,
            //                                             we shouldn't exit the loop after this. This
            //                                             is just to avoid the unnecessary g|(ChangeLevel|)++
            //                                             duplication here (and the checking that would come
            //                                             with it!
            FOR i&=PRED(ChangeLevel|) DOWNTO 0 //Reset all digits in the previous positions.
              G|(i&)=0
            NEXT i&
          ENDIF
        ENDIF
        //The next line is a kind of pre-filtering and it will force the program to jump over
        //numbers in a given position that are clearly impossible there!
        //we could also check for repetitions (whether the same digit is allowed to
        //come twice in a different position within the same guess), but it would only be
        //necessary if the iteration was slow.
      LOOP  UNTIL Possible!(ChangeLevel|,G|(ChangeLevel|)) AND (MustContinue!=FALSE)
      ChangeLevel|=0
    LOOP

    //By this time we should be sure that the next guess, if it is the solution, would have
    //generated the same answers for the previous guesses.

    Guess|(Turn&,0)=G|(0), Guess|(Turn&,1)=G|(1), Guess|(Turn&,2)=G|(2), Guess|(Turn&,3)=G|(3)

  ENDSWITCH
  //so, show the guess in the next available guess window:

  s$=STR$(n|(Guess|(Turn&,3)))+STR$(n|(Guess|(Turn&,2)))+STR$(n|(Guess|(Turn&,1)))+STR$(n|(Guess|(Turn&,0)))+Null$
  SENDMESSAGE DLGITEM(-1,Turn&+100),WM_SETTEXT,0,V:s$

  SkipMakeComputerGuess:
RETURN
> FUNCTION Numeric(wh&)
  LOCAL g$=_WIN$(wh&), i|
  //just to filter out unintentional typos.

  i|=LEN(g$)
  IF i|<4 THEN g$=g$+STRING$(4-i|,"0")
  FOR i|=1 TO 4
    IF VAL?(MID$(g$,i|,1))=0 THEN RETURN FALSE
  NEXT i|
  RETURN TRUE
ENDFUNC
> PROCEDURE QuitApplication
  LOCAL dummy|
  ALERT 2,"Quit MasterMind.",1,"&Yes|&No",dummy|
  IF dummy|-2
    CLOSEW #1
    END
  ENDIF
RETURN
> FUNCTION ReallyPossible(VAR G|())
  LOCAL i|,b|,w|
  //Iterate through all previous guesses and check if they'd've gotten the same Blacks and
  //Whites if our next guess had been the secret number.

  FOR i|=0 TO PRED(Turn&)
    //We must make a copy of the previous guesses, because the reward checking
    //function uses a one dimensional array, whereas we store the previous
    //guesses by Guess|(Turn&,Position|)

    PreviousGuess|(0)=Guess|(i|,0),PreviousGuess|(1)=Guess|(i|,1),PreviousGuess|(2)=Guess|(i|,2),PreviousGuess|(3)=Guess|(i|,3)

    ~@ReWard(G|(),PreviousGuess|(),b|,w|) //b| and w| are, of course, VAR variables.
    //                                                                 the return value of the function is irrelevant
    //                                                                  here (signaling final success, which is not
    //                                                                  possible here, since we're still guessing.
    IF b|<>ReWard|(i|,0) THEN RETURN FALSE  //ANY difference means an incorrect guess.
    IF w|<>ReWard|(i|,1) THEN RETURN FALSE
  NEXT i|
  RETURN TRUE
ENDFUNC
> FUNCTION ReWard(VAR os|(),og|(),b|,w|)
  LOCAL i|,j|
  b|=0,w|=0
  n&++
  FOR i|=0 TO 3
    TempS|(i|)=os|(i|), TempG|(i|)=og|(i|)    //Must make a copy, because the function will change
    //                                                            the values for the digits that have already been
    //                                                            rewarded, to avoid duplication in the reward.
    IF TempS|(i|)=TempG|(i|)
      b|++
      TempS|(i|)=10,TempG|(i|)=10             //the value 10 means: already rewarded, ignore in
      //                                                          the future.
    ENDIF
  NEXT i|
  IF b|=4 THEN RETURN TRUE
  FOR i|=0 TO 3
    IF TempG|(i|)<10
      FOR j|=0 TO 3
        IF j|<>i|
          IF TempS|(j|)<10
            IF TempG|(i|)=TempS|(j|)
              w|++
              TempG|(i|)=10,TempS|(j|)=10
              IF w|+b|=4 THEN RETURN FALSE
            ENDIF
          ENDIF
        ENDIF
      NEXT j|
    ENDIF
  NEXT i|
  RETURN FALSE
ENDFUNC
> PROCEDURE Shuffle
  LOCAL t|,f|,i|
  //To make it look more interesting, theComputer will not display its guesses directly;
  //rather, it will use them as index numbers for an array of shuffled digits.
  FOR i|=0 TO 200
    DO
      t|=RANDOM(10),f|=RANDOM(10)
    LOOP UNTIL t|<>f|
    SWAP n|(t|),n|(f|)
  NEXT i|
RETURN
> PROCEDURE SwitchComputerTurn
  LOCAL dummy|
  IF Game!
    Turn&++
    IF Turn&>9
      ALERT 3,"Sorry, I  can't guess.",1,"&Ok",dummy|
      Game!=FALSE
      @UpdateClock  //manually, to avoid the necessity of the WM_TIMER messages here.
    ELSE
      @MakeComputerGuess
      @UpdateClock

      AnswerClockTime%=TIMER //we cannot include in the computer's "thinking time"
      // the time the User uses up while entering the answers for the computer.

      ~SetWindowLong(DLGITEM(-1,Turn&+200),GWL_STYLE,NormalStyle%)
      ~SetWindowLong(DLGITEM(-1,Turn&+300),GWL_STYLE,NormalStyle%)
      SENDMESSAGE DLGITEM(-1,Turn&+200),WM_SETTEXT,0,V:Null$
      SENDMESSAGE DLGITEM(-1,Turn&+300),WM_SETTEXT,0,V:Null$
      ~SetFocus(DLGITEM(-1,Turn&+200))

      PlayerMode&=300  //Waiting for User's answer.
    ENDIF
  ENDIF
RETURN
> PROCEDURE SwitchHumanVsAnythingTurn //Human vs. Human or Human vs. Computer
  LOCAL dummy|

  IF Turn& >-1
    @GiveAnswerToHuman(Turn&)
    ~SetWindowLong(DLGITEM(-1,Turn&+100),GWL_STYLE,DisAbledStyle%)
  ENDIF

  IF Game!
    Turn&++
    IF Turn&>9
      ALERT 3,"Sorry, you used up the 10 chances.",1,"&Ok",dummy|
      Game!=FALSE
      KILLTIMER 1,1 //stop the clock, game over!
      //Strictly speaking, we should say @Celebrate(4) here. But it's already here, so
      //who cares? Like Windows is consistent???
    ELSE

      ~SetWindowLong(DLGITEM(-1,Turn&+100),GWL_STYLE,NormalStyle%)
      _WIN$(DLGITEM(-1,Turn&+100))=""
      ~SetFocus(DLGITEM(-1,Turn&+100))
    ENDIF
  ENDIF
RETURN
> PROCEDURE UpdateClock
  LOCAL t%,sec|, min|,hr|,sec$,mi$,hr$
  //Cut up the millisecond-timer into seconds, minutes, (Hours?!)

  t%=(TIMER-ClockTime%)\1000

  sec|=t% MOD 60
  sec$="0"+STR$(sec|)
  t%-=sec|

  min|=(t%\60) MOD 60

  hr|=(t%-min|)\3600
  hr$="0"+STR$(hr|)
  t%-=hr|

  mi$="0"+STR$(min|)
  hr$=RIGHT$(hr$,2)+":"
  mi$=RIGHT$(mi$,2)+":"
  sec$=RIGHT$(sec$,2)

  t$=hr$+mi$+sec$+Null$
  //When I used _WIN$(..., I had trouble with long texts in other programs.
  //I guess it's fixed in later versions of GFABASIC. To use the API command here is a quick fix.
  //In other places of this program, I didn't have any problem. Let me know if it misbehaves.
  //(or maybe I should simply upgrade my GFA version?)

  SENDMESSAGE clock&,WM_SETTEXT,0,V:t$
RETURN
> PROCEDURE HelpFileTutor
  //Helpfile information, syntax, etc.

  //f!=WinHelp(h&,addr_fh%,c&,d%)
  //f!:   if TRUE, the Help system was started with the corresponding parameters.
  //h&:   handle of the application which invoked the Help system.
  //addr_hf%:  pointer to a null byte terminated string which contains the pathname and then name of the Help file.
  //c&:   defines the type of help. c& can take one of the following values:
  // HELP_CONTEXT  ($0001)        //Display topic in Topic
  // HELP_QUIT  ($0002)                //Terminate help
  //HELP_INDEX  ($0003)              //Display index
  //HELP_HELPONHELP  ($0004)  //Display help on using help
  //HELP_SETINDEX  ($0005)        //Set the current Index for multi index help
  //HELP_KEY  ($0101)                  //Display topic for keyword in offabData
  //HELP_MULTIKEY  ($0201)        //Display topic for keyword in alternate keyword table
  //d%: specifies the context or the keyword for which the Help system was invoked.

  //       if c& = HELP_CONTEXT, d% contains a 32 bit unsigned integer value which identifies the context.
  //       if c& = HELP_KEY, d% contains a null byte terminated string which specifies the keyword.
  //       if c& = HELP_MULTIKEY, d% sets a pointer to a MULTIKEYHELP data structure.
RETURN
