return to TicTacToe project page.
see Delphi unit1

unit Unit2;
{
 DavData software
 3D boter - kaas - eieren
 data & search unit

 2 players
 red - blue - red - blue...............
 analyse button predicts game
 7 - 02 - 2014 version 1.1
 9 - 02 - 2014         1.2   no win test if node < 5

} 

interface

uses sysutils;

type TWintriple = record
                   p1,p2,p3 : byte;
                  end;
     TNode   = record
                pos : byte;
                rating : byte;
                treshold : byte;
               end;

const maxmove = 27;

var game : array[0..maxmove] of byte;  //1=O 2=X
    node : array[1..maxmove] of TNode;
    moveNr : byte;

procedure makewinlist;
procedure initgame;
procedure analyse;
function checkwin(var tr : Twintriple; player : byte) : boolean;

implementation

uses unit1;

var winlist  : array[1..50] of TWinTriple;
    wincount : byte;
    testNode : byte;
    baseNode :byte;

procedure initgame;
var i : byte;
begin
 for i := 0 to maxmove do game[i] := 0;
 for i := 1 to maxmove do
  with node[i] do
   begin
    pos := 0;
    rating := 0;
    treshold :=0;
   end;
 moveNr := 0;
end;

function checkwin(var tr : TwinTriple; player : byte) : boolean;
//check for win somewhere, return wintriple# tr
var i : byte;
begin
 i := 0;
 result := false;
 repeat
  inc(i);
  with winlist[i] do
   result := (game[p1] = player) and
             (game[p2] = player) and
             (game[p3] = player);
 until result or (i = wincount);
 if result then tr := winlist[i];
end;

procedure makewinlist;
const concode : array[1..maxmove] of byte =
                (1,2,1,3,4,3,1,2,1,5,6,5,7,0,7,5,6,5,1,2,1,3,4,3,1,2,1);
var i,j : byte;  //start..end field
begin
 wincount := 0;
 for i:= 1 to 25 do
  for j := i+2 to 27 do
   if concode[i] = concode[j] then
    begin
     inc(wincount);
     with winlist[wincount] do
      begin
       p1 := i;
       p2 := (i + j) shr 1;
       p3 := j;
      end;
    end;
end;

//-- analyze helpers

function firstmove : boolean;
//make first move of new node
//false if no move (node = 27)
//true if move done
var i,m : byte;
begin
 with node[testnode] do
  begin
   if treshold = 100 then treshold := 98; //no win
   result := rating < treshold;
   if result then
    begin
     m := 2 - (testNode and 1);
     i := 1;
     while game[i] > 0 do inc(i);
     game[i] := m;
     pos := i;
    end;//if
  end; 
end;

procedure testwin;
//test for any win in new node
//set rating = 100 if win
//report basenode wins
var i,m,p : byte;
    win : boolean;
begin
 if testNode < 5 then exit;

 m := 2 - (testNode and 1);
 if testnode = basenode then        //basenode
  begin
   for p := 1 to maxmove do
    if game[p] = 0 then
     begin
      game[p] := m;
      for i := 1 to wincount do
       begin
        win  := (game[winlist[i].p1] = m) and
                (game[winlist[i].p2] = m) and
                (game[winlist[i].p3] = m);
        if win then begin
                     analysereport(p,100);
                     node[testNode].rating := 100;
                    end;
       end;
      game[p] := 0;
     end;
  end   //basenode
  else                      //not basenode
   begin
    p := 1;
    win := false;
    repeat
     if game[p] = 0 then
      begin
       game[p] := m;
       i := 0;
       repeat
        inc(i);
        win  := (game[winlist[i].p1] = m) and
                (game[winlist[i].p2] = m) and
                (game[winlist[i].p3] = m);
       until win or (i = wincount);
       game[p] := 0;
      end;//if game[p]
     inc(p);
    until win or (p = maxmove+1);
    if win then node[testnode].rating := 100;
   end;//else
end;

function nextNode : boolean;
//open node testnr+1
//set 1st move
var x : byte;
begin
 result := testNode < 27;
 if result then
  begin
   inc(testNode);
   with node[testNode] do
    begin
     pos := 0;
     if testNode = baseNode then
      begin
       treshold := 100;
       rating := 1;
      end
     else
      begin
       x := 100 - node[testNode-1].rating;
       if x < 50 then dec(x);
       if (x > 50) then inc(x);
       if testNode >= maxmove-1 then treshold := 50
        else treshold := x;
       x := 100 - node[testNode-1].treshold;
       if x < 50 then dec(x);
       if x > 50 then inc(x);
       rating := x;
      end;
    end;//with  
  end;
end;

function previousnode : boolean;
//close node nr
//if baseNode  set score
//else set rating
var x,p : byte;
    prf : boolean;
begin
 result := false;
 prf := true;
 while prf do
  begin
   prf := false;
   p := node[testnode].pos;
   game[p] := 0;               //remove O,X
   if testNode > baseNode then
    begin
     result := true;
     x := 100 - node[testnode].rating;
     dec(testNode);
     with node[testnode] do
      begin
       if x > 50 then dec(x);
       if x < 50 then inc(x);
       if testnode = basenode then analysereport(pos,x)
        else
         if x > rating then
          begin
           rating := x;
           prf := rating >= treshold;
          end;
      end;
    end
    else result := false; //testNode = baseNode
  end;//while
end;

function nextmove : boolean;
var x : byte;
begin
 result := false;
 x := node[testNode].pos;
 game[x] := 0;//none
 while (x < maxmove) and (result = false) do
  begin
   inc(x);
   result := game[x] = 0;
  end;
 if result then
  begin
   game[x] := 2 - (testNode and 1);
   node[testnode].pos := x;
  end;
end;

//-- main call

procedure analyse;
//analyse game
var Ffirst,Fnext,Fprev : boolean;
begin
 if movenr = 27 then exit;

 testNode := moveNr;
 baseNode := moveNr + 1;

 Ffirst := true;
 while Ffirst do
  begin
   Fnext := true;
   while Fnext do
    begin
     Fnext := false;
     if nextNode then
      begin
       testwin;
       Fnext := firstMove;
      end; 
    end;  

   Fprev := true;
   while Fprev do
    if previousNode then
     begin
      if nextmove then Fprev := false;
     end
     else begin
           Ffirst := false;
           Fprev := false;
          end;

  end;//Ffirst
end;

end.