<?xml version="1.0" encoding="UTF-8"?>
<Worksheet><Version major="6" minor="1"/><View-Properties><Zoom percentage="100"/></View-Properties><Styles><Layout alignment="centred" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Author" rightmargin="0.0" spaceabove="8.0" spacebelow="8.0"/><Layout alignment="left" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Normal" rightmargin="0.0" spaceabove="0.0" spacebelow="0.0"/><Layout alignment="centred" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Title" rightmargin="0.0" spaceabove="12.0" spacebelow="12.0"/><Font background="[0,0,0]" bold="true" executable="true" family="Monospaced" foreground="[255,0,0]" name="Maple Input"/><Font background="[0,0,0]" family="Times New Roman" name="Page Number" underline="false"/><Font background="[0,0,0]" bold="false" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Normal" readonly="false" size="12" underline="false"/><Font background="[0,0,0]" bold="false" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Author" readonly="false" size="12" underline="false"/><Font background="[0,0,0]" bold="true" name="_cstyle256"/><Font background="[0,0,0]" family="Times New Roman" name="2D Comment" underline="false"/><Font background="[0,0,0]" bold="true" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Title" readonly="false" size="18" underline="true"/></Styles><Page-Numbers enabled="false" first-number="1" first-numbered-page="1" horizontal-location="right" style="Page Number" vertical-location="bottom"/><Group><Input><Text-field layout="Title" style="Title">Mastermind</Text-field><Text-field layout="Author" style="Author">Douglas Wilhelm Harder  November 2001</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">This maplet plays the game <Equation input-equation="Mastermind^TM" style="2D Comment">NiMpJStNYXN0ZXJtaW5kRyUjVE1H</Equation>, more generically known as "Four of Eight".</Text-field><Text-field layout="Normal" style="Normal"/><Text-field layout="Normal" style="_cstyle256"><Font family="Times New Roman" foreground="[0,0,0]" italic="false" size="12" underline="false">To run this maplet, click the "Execute-Worksheet"  button in the tool-bar menu (the !!! button)<Font executable="false">
</Font></Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">restart:
module FourOfEight()
   export Display,
      Plot, Guess, Statistics, NewGame, HighScore, Update;
   local i, j, displaylist, spheretmp, Sphere, colours, colourtmp,
      columns, guesses, clearlower, layout, maplet, colorlist,
      currentwins, currentlosses, currentguesses,
      totalwins, totallosses, totalguesses, toNumber,
      code, guessnumber, pegs, topname, topscore, peglist, LittleSphere, littlespheretmp;

   topname := "anonymous";
   topscore := 13;

   randomize();

   totalwins := 0;
   totallosses := 0;
   totalguesses := 0;

   Display := proc()
      currentwins := 0;
      currentlosses := 0;
      currentguesses := 0;

      Maplets:-Display( maplet );
   end proc;

   Statistics := proc()
      local maplet, result;

      use Maplets:-Elements in
         maplet := Maplet(
            Window( 'title' = "Statistics",
               BoxLayout( BoxColumn(
                  BoxColumn( 'border', 'caption' = "Current Session",
                      GridLayout( [
                         ["Won:", convert( currentwins, string )],
                         ["Lost:", convert( currentlosses, string )],
                         ["Average Wins:", `if`( currentwins + currentlosses = 0, "0%",
                              sprintf( "%a%%", round( 100*currentwins/(currentwins + currentlosses) ) ) )],
                         ["Average Guesses:", `if`( currentwins + currentlosses = 0, "0",
                              sprintf( "%a", 0.01*round( 100*currentguesses/(currentwins + currentlosses) ) ) )]
                      ] )
                  ),
                  BoxColumn( 'border', 'caption' = "Total",
                      GridLayout( [
                         ["Won:", convert( totalwins, string )],
                         ["Lost:", convert( totallosses, string )],
                         ["Average:", `if`( totalwins + totallosses = 0, "0%",
                              sprintf( "%a%%", round( 100*totalwins/(totalwins + totallosses) ) ) )],
                         ["Average Guesses:", `if`( totalwins + totallosses = 0, "0",
                              sprintf( "%a", 0.01*round( 100*totalguesses/(totalwins + totallosses) ) ) )]
                       ] )
                  ),
                  BoxRow( Button( "OK", Shutdown() ), Button( "Clear", Shutdown("clear") ) )
               ) )
            )
         );
      end use;

      result := Maplets:-Display( maplet );

      if result = "clear" then
         currentwins := 0;
         currentlosses := 0;
         currentguesses := 0;
         totalwins := 0;
         totallosses := 0;
         totalguesses := 0;
      end if;

      NULL;
   end proc;

   HighScore := proc()
      local maplet, result;

      use Maplets:-Elements in
         maplet := Maplet(
            Window( 'title' = "Top Score",
               BoxLayout( BoxColumn(
                  BoxRow( BoxCell( topname ), BoxCell( convert( topscore, 'string' ) ) ),
                  BoxRow( Button( "OK", Shutdown() ), Button( "Clear", Shutdown("clear") ) )
               ) )
            )
         );
      end use;

      result := Maplets:-Display( maplet );

      if result = "clear" then
         topname := "anonymous";
         topscore := 13;
      end if;

      NULL;
   end proc;

   NewGame := proc()
      local result;

      if assigned( code ) then
         result := Maplets:-Examples:-Alert( "Do you want to give up your current game?" );

         if result &lt;&gt; true then
             return Plot( layout, pegs );
         else
            currentlosses := currentlosses + 1;
            currentguesses := currentguesses + 13;
            totallosses := totallosses + 1;
            totalguesses := totalguesses + 13;
         end if;
      end if;

      code := [seq( rand(1..8)(), i = 1..4 )];
      guessnumber := 1;
      layout := [[1, 1, 1, 1], seq( [0, 0, 0, 0], j = 1..guesses - 1 )];
      Maplets:-Tools:-Set( 'DDB1' = "red" );
      Maplets:-Tools:-Set( 'DDB2' = "red" );
      Maplets:-Tools:-Set( 'DDB3' = "red" );
      Maplets:-Tools:-Set( 'DDB4' = "red" );
      pegs := [];

      Plot( layout, pegs );
   end proc;

   Update := proc(a, b, c, d)
      if assigned( code ) then
         layout := subsop( guessnumber = [toNumber( a, b, c, d )], layout );

         Plot( layout, pegs );
      else
         Plot( layout, pegs );
      end if;
   end proc;

   Guess := proc(a, b, c, d)
      local black, white, guess, skipg, skipc, p, i, codeT;

      if not assigned( code ) then
         return Plot( layout, pegs );
      end if;

      black := 0;
      white := 0;
      skipg := {};

      guess := [toNumber(a, b, c, d)];

      for i from 1 to 4 do
         if code[i] = guess[i] then
            black := black + 1;
            skipg := skipg union {i};
         end if;
      end do;

      if nops( skipg ) = 4 then
         pegs := [op( pegs ), [6, 6, 6, 6]];

         currentwins := currentwins + 1;
         currentguesses := currentguesses + guessnumber;
         totalwins := totalwins + 1;
         totalguesses := totalguesses + guessnumber;

         Maplets:-Examples:-Message( sprintf( "You won in %a guess(es)", guessnumber ), 'title' = "Four Of Eight" );

         code := 'code';

         if guessnumber &lt; topscore then
             topscore := guessnumber;
             try
                 topname := Maplets:-Examples:-GetInput( "New high score.  Enter your name:", title = "Four Of Eight" );
             catch:
             end try;
         end if;

         return Plot( layout, pegs );
      end if;

       codeT := subsop( seq( i = NULL, i = skipg ), code );

       for i from 1 to 4 do
          if not member( i, skipg ) then
            if member( guess[i], codeT, 'p' ) then
               white := white + 1;
               codeT := subsop( p = NULL, codeT );
            end if;
         end if;
      end do;

      pegs := [op( pegs ), [seq( 6, i = 1..black ), seq( 5, i = 1..white ), seq( 0, i = 1..4 - black - white )]];

      if guessnumber = 12 then
         Maplets:-Examples:-Message( "You lost, please try again", 'title' = "Four Of Eight" );
         code := 'code';

         currentlosses := currentlosses + 1;
         currentguesses := currentguesses + 13;
         totallosses := totallosses + 1;
         totalguesses := totalguesses + 13;

         return Plot( layout, pegs );
      end if;

      layout := subsop( guessnumber + 1 = layout[guessnumber], layout );
      guessnumber := guessnumber + 1;

      Plot( layout, pegs );
   end proc;

   toNumber := proc(a, b, c, d)
      local A, B, C, D;

      member( convert( a, 'string' ), colorlist, A );
      member( convert( b, 'string' ), colorlist, B );
      member( convert( c, 'string' ), colorlist, C );
      member( convert( d, 'string' ), colorlist, D );

      A, B, C, D;
   end proc;

   colorlist := ["red", "green", "blue", "yellow", "white", "black", "orange", "brown"];

   use Maplets:-Elements in
      maplet := Maplet( 'onstartup' = A0,
         Action[A0](
            RunWindow( 'window' = W1 )
         ),
         Window[W1]( 'title' = "Four Of Eight", 'menubar' = MB1, [
            Plotter[PL1](),
            [
               DropDownBox['DDB1']( "red", colorlist, 'enabled' = 'false', onchange = 'update' ),
               DropDownBox['DDB2']( "red", colorlist, 'enabled' = 'false', onchange = 'update' ),
               DropDownBox['DDB3']( "red", colorlist, 'enabled' = 'false', onchange = 'update' ),
               DropDownBox['DDB4']( "red", colorlist, 'enabled' = 'false', onchange = 'update' )
            ],
            Button['BG']( "Guess", 'enabled' = 'false', 'onclick' = 'guess' )
         ] ),

         Action['guess'](
            Evaluate( 'function' = 'FourOfEight:-Guess()' )
         ),

         MenuBar[MB1](
            Menu( "Game",
               MenuItem( "New Game", 'onclick' = 'newgame' ),
               MenuItem( "Statistics", 'onclick' = 'stats' ),
               MenuItem( "High Score", 'onclick' = 'highscore' ),
               MenuItem( "Exit", 'onclick' = 'exit' )
            ),
            Menu( "Help",
               MenuItem( "Playing", 'onclick' = 'help' ),
               MenuItem( "About", 'onclick' = 'about' )
            )
         ),

         Action['update'](
            Evaluate( 'PL1' = 'FourOfEight:-Update'('DDB1', 'DDB2', 'DDB3', 'DDB4') )
         ),

         Action['guess'](
            Evaluate( 'PL1' = 'FourOfEight:-Guess'('DDB1', 'DDB2', 'DDB3', 'DDB4') )
         ),

         Action['newgame'](
            SetOption( 'BG'('enabled') = true ),
            SetOption( 'DDB1'('enabled') = true ),
            SetOption( 'DDB2'('enabled') = true ),
            SetOption( 'DDB3'('enabled') = true ),
            SetOption( 'DDB4'('enabled') = true ),
            Evaluate( 'PL1' = 'FourOfEight:-NewGame()' )
         ),

         Action['exit'](
            Shutdown()
         ),

         Action['stats'](
            Evaluate( 'function' = 'FourOfEight:-Statistics()' )
         ),

         Action['highscore'](
            Evaluate( 'function' = 'FourOfEight:-HighScore()' )
         ),

         Action['help'](
            RunWindow( 'window' = 'helpwindow' )
         ),

         Window['helpwindow'](
            "Help",
            BoxColumn( 'vscroll' = 'as_needed',
                BoxRow( 'caption' = "Introduction", 'border',
                    TextBox( 5..40, 'wrapped', 'not editable', 'font' = TNR,
                        "The goal of this game is to guess 4 colors which the computer has "
                        "chosen at random from a set of 8.  Each time you submit a guess, clues are given which "
                        "indicate how close you are to the correct answer.  A black spot "
                        "indicates you have a correct color in a correct location, and a white "
                        "spot indicates you have a correct color but in the wrong location."
                    )
                ),
                Button( "OK", CloseWindow( 'helpwindow' ) )
             )
         ),

         Action['about'](
            RunDialog( 'dialog' = 'aboutdialog' )
         ),

         MessageDialog['aboutdialog'](
            'title' = "About Four Of Eight",
            'caption' = "Author:  Douglas Wilhelm Harder &lt;douglas@links.uwaterloo.ca&gt;"
         )
      );
   end use;

   columns := 4;
   guesses := 12;

   spheretmp:= plottools[circle]( [0, 0], 1 );

   littlespheretmp:= plottools[circle]( [0, 0], 0.2 );

   Sphere := proc(dx, dy)
      local offset;

      offset := proc(L)
         [L[1] + 2.3*dx, L[2] + 2.3* dy];
      end proc;

      'POLYGONS'(
         seq( map( offset, i ), i = spheretmp ),
         'STYLE'('PATCHNOGRID'),
         colourtmp[dx, dy]
      );
   end proc;

   LittleSphere := proc(dx, dy)
      local offset;

      offset := proc(L)
         [-2 + L[1] + 0.5*dx, L[2] + 2.3*dy];
      end proc;

      'POLYGONS'(
         seq( map( offset, i ), i = littlespheretmp ),
         'STYLE'('PATCHNOGRID'),
         colourtmp[dx, dy]
      );
   end proc;

   colours := Array( 1..8, [
      COLOR( RGB, 1.0, 0.0, 0.0 ),         # red
      COLOR( RGB, 0.0, 1.0, 0.0 ),         # green
      COLOR( RGB, 0.0, 0.0, 1.0 ),         # blue
      COLOR( RGB, 1.0, 1.0, 0.0 ),         # yellow
      COLOR( RGB, 1.0, 1.0, 1.0 ),         # white
      COLOR( RGB, 0.35, 0.35, 0.35 ),         # black
      COLOR( RGB, 1.0, 0.5, 0.0 ),         # orange
      COLOR( RGB, 0.5, 0.3, 0.3 )          # brown
   ] );

   displaylist := [seq(
      [seq(
         Sphere( i, j ),
         j = 1..guesses
      )],
      i = 1..columns
   )];

   peglist := [seq(
      [seq(
         LittleSphere( i, j ),
         j = 1..guesses
      )],
      i = 1..columns
   )];

   Plot := proc(LT, pegsT)
      local i, j, L, pegs;

      L := ListTools:-Transpose( LT );
      pegs := `if`( pegsT = [], [], ListTools:-Transpose( pegsT ) );

      PLOT(
         seq(
            seq(
               `if`(
                  L[i, j] = 0,
                  NULL,
                  subs( colourtmp[i, j] = colours[L[i, j]], displaylist[i, j] )
               ),
               j = 1..nops(L[1])
            ),
            i = 1..nops(L)
         ),
         seq(
            seq(
               `if`(
                  pegs[i, j] = 0,
                  NULL,
                  subs( colourtmp[i, j] = colours[pegs[i, j]], peglist[i, j] )
               ),
               j = 1..nops(pegs[1])
            ),
            i = 1..nops(pegs)
         ), POLYGONS([[-3, 1], [-3, 30], [11, 30], [11, 1], [-3, 1]],
            STYLE(PATCHNOGRID), COLOR(RGB,0.8,0.8,0.8)), AXESSTYLE(NONE)
      );
   end proc;
end module:</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">FourOfEight:-Display();</Font></Text-field></Input></Group><Group><Input><Text-field prompt="&gt; " style="Maple Input"/></Input></Group><Text-field/></Worksheet>