A Model Program

This is an attempt to develop a minmax based game playing program. We will discuss program development strategy.

Assumptions


Variables

BD = Board Dimension. This can be changed and the program recompiled to allow playing on a board larger than 4 x 4.

CTYPE = BD x BD character array. The defined type of the characteristics of the nodes.

HUMAN and COMPUTER which side is which color (as in Black and White of Chess)

Program Elements

Main Program: Sown in Listing 1. Controls everything, the main loop.

MoveSide: Shown in Listing 2. The heart of the program.

MoveSide examines the color to determine if the player is human or computer.

If it is Human, MoveSide asks for the move. When the human makes the move, it checks the validity of the move.

If it is the Computer’s turn, MoveSide computes the move by calling ComputeAMove (Shown in Listing 3).

ComputeAMove: Once "Expanded" is defined in this manner, tree generation is easy (see Listing 4). In this listing, The outer loop says, "keep doing this while the tree is NOT full. The tree-full condition is triggered by a tree overflow.
If we are trying to create a five-level tree and we've only got room for a four-level tree, the code drops N levels and starts all over.
Main Loop:
Next is the main loop.It just keeps looking for unexpanded nodes and keeps expanding  them until none are left.
FindFirst is a depth-first search thru the tree in search  for unexpanded nodes.
Expand (Listing 5) looks at the board position at node (N, Side). It examines every location on the board for a friendly piece and considers every possible move for it with a routine called ConsiderMove.
ConsiderMove then adds any appropriate nodes to the tree with CreateNode from the tree-handling toolbox.

Program Flow:
 

    Main Program calls (SetUpGame, ChooseColor, MoveSide, ShowBoard)

   MoveSide calls (GetInputMove, ComputeAMove, Won)

   ComputeAMove calls (GenTree, MinMax)

   GenTree calls (FindFirst, Expand)

Only the code for the underlines procedures is shown below.
 

Sample Coding:

Listing 1. Main Program

Begin

        SetUpTheGame (CurrentBoard);

        ChooseColor (Computer, Human);
        {play White or Black? - White goes first}

        Side-to-move := White;

        Repeat

                MoveSide (SideToMove, CurrentBoard);

                ShowBoard (CurerntBoard);

                WhoWon := Won (CurrentBoard, SideToMove);

                SideToMove := Opposite (SideToMove);

        Until WhoWon <> Neither;

        If WhoWon = Computer then Writeln (‘I have won!’)

                             else writeln (‘you have won’);

End.

Listing 2. Moveside Routine (This was called in Listing 1.)

PROCEDURE  MoveSide(Side: Char; Var CurrentBoard: Ctype; WhoWon: char);

Begin

        IF Side = Human THEN

                GetInputMove (CurerntBoard, Side);

        ELSE

                ComputeAMove (CurerntBoard, Side);

End
 
 

Listing 3. ComputeAMove Routine

Procedure ComputeAMove(Var Board: Ctype; Side: char);

Begin

    GenTree (Nlevels, side); {Generates move tree}

    MinMax (Board, Side, Nlevels); {Returns new board position}
 

End

Listing 4. GenTree Routine

{Generates a tree N levels deep for side Side}

Procedure GenTree (Var Nlevels: INTEGER; Side: CHAR)

Var

    N, INTEGER
    AllDone: Boolean;
    TreeFull: Boolean;

Begin {Outer loop}

    Repeat

    Treefull := FALSE;
    Inittree; {then set up root characteristics}
    AllDone:= FALSE;

    Begin {This is the main loop}
    {Find first unexpanded node by calling FindFirst, which is a depth-first search in    search for an unexpanded node}
            FindFirst(N);
            If N=NULL then AllDone := TRUE Else

            Begin {This is the Inner loop}
            {Expand node n, by calling Expand}
            Expand (N, Side, TreeFull, Nlevels);
            If TreeFull then

                    Begin {Innermost loop}
                    {Reduce Search Depth}
                    Nlevels := Nlevels - 1;
                    writeln ('GenTree: Tree overflow. Reducing plies'
                                                'temporarily to ' nlevels);
                    End; {Reduce search depth}
            End; {Expand node n}
    End {main loop}

Until NOT TreeFull;

End;

Listing 5. Procedure for expanding gametree nodes.

Procedure Expand (N: INTEGER; OriginalSide: CHAR; VAR Nlevels: INTEGER);

Begin
{First, we have to know which side is making the move}
    IF odd(Depth(N))    THEN ThisSide := Opposite (OriginalSide)
                                    ELSE ThisSide := OriginalSide;
    Characteristic (B, N);
    {Now find pieces and see if they can move}
    FOR I := 1 TO BD DO FOR J :=1 TO BD DO

    Begin
    IF B[I, J] = ThisSide THEN FOR K :=1 TO NMoves DO
        ConsiderMove (I, J, K, B, ThisSide, TreefUll, N, OriginalSide, Nlevels);
    SetValue (N, Expanded); {now the parent node has been expanded}
    End;
End;

Notes: We may have to pull together a number of tree handling routines.