maxdisks=64;
type
  TTowers = class(Tobject)
     peg:array[1..3, 1.. maxdisks] of integer;
     nbrdisks:array[1..3] of integer; {current nbr of disks on each peg}
     Procedure setdisks(NewNbrDisks:integer);
     Function MoveOne(Frompeg, topeg:integer):integer; {return disk nbr of disk moved}
  end;
.
.
. {generated code snipped} 
.
{********************* Tower Methods *****************}
Procedure TTowers.setdisks(NewNbrDisks:integer);
var
  i:integer;
Begin
  For i:=1 to 3 do nbrdisks[i]:=0;
  Nbrdisks[1]:=NewNbrdisks;
  {number the disks from high to low (low number in highest position}
  for i:= 1 to newnbrdisks do peg[1,i]:=newnbrdisks+1-i;
end;

Function TTowers.MoveOne(Frompeg, topeg:integer):integer; {return disk nbr of disk moved}
var
  disknbr:integer;
Begin
   disknbr:=Peg[frompeg, nbrdisks[frompeg]];
  {Can't move a disk to a smaller one}
  If (nbrdisks[topeg]>0) and (disknbr>=peg[topeg,nbrdisks[ToPeg]]) then result:=-1
  else
  begin
    dec(nbrdisks[Frompeg]);
    inc(nbrdisks[ToPeg]);
    Peg[Topeg,nbrdisks[topeg]]:=disknbr;
  end;
  result:=disknbr;
end;

{********************* Form methods **********************}

Procedure Tform1.MoveStack(n, A,C,B:integer);
{Use recursive calls to move n disks from Peg A to Peg C with Peg B as a spare}
  Begin
    if stopflag then exit; {User signaled stop}
    If n=1 then
    Begin
       MoveOne(A,C); {If there's only one to move, move it}
    end
    else
    Begin
      MoveStack(n-1, A,B,C);  {Move n-1 disks to peg B}
      MoveOne(A,C);           {Move 1 disk to Peg C}
      MoveStack(n-1,B,C,A);   {Then move n-1 disks from B back to Peg C}
    end;
  end;


Procedure TForm1.MoveOne(A,C:integer);
{Move a disk and display result}
var
  DiskNbr:integer;
Begin
  inc(movecount);
  Disknbr:=Tower.moveone(A,C);
  application.processmessages;
  If movecount<=MaxMovesToList
  then MoveBox.items.add('Disk '+inttostr(Disknbr) + ' from peg '+inttostr(A)+' to '+inttostr(C));
End;


procedure TForm1.SolveBtnClick(Sender: TObject);
{solve button was clicked}
begin
  {Initialize stuff}
  stopflag:=false;; {Quit flag - set by stop button}
  EstsecsLbl1.caption:='';
  EstSecsLbl2.caption:='';
  SolveBtn.enabled:=false;
  StopBtn.enabled:=true;
  movecount:=0;
  QueryPerformanceCounter(startcount); {Get initial timer count}
  MovesLbl.Caption:='Number of moves:' ;
  timelbl.caption:='Number of Seconds: ';
  ratelbl.caption:='Moves per second: ';
  Tower.setdisks(nbrdisks);
  MoveStack(nbrdisks,1,3,2); {move nbrdisks from peg 1 to peg 3 using peg2 as the spare}
  If tag=0 then makelabels('Complete');
  SolveBtn.enabled:=true;
  StopBtn.enabled:=false;
  Screen.cursor:=CrArrow;
end;

Procedure TForm1.MakeLabels(S:String);
var stopcount, freq:int64;
Begin
  QueryPerformanceCounter(stopcount); {Get end count}
  QueryPerformanceFrequency(freq); {Get frequency}
  MovesLbl.Caption:='Number of moves: '+floattostrf(movecount,ffnumber,9,0);
  seconds:=(stopcount-startcount)/freq;
  timelbl.caption:='Number of Seconds: '+floattostrf(seconds,ffnumber,6,1);
  If seconds>=0.5 then
  Begin
     rate:=movecount / seconds;
     ratelbl.caption:='Moves per second: '+floattostrf(rate,ffnumber,9,0);
  end
  else
   ratelbl.caption:='Moves per second: Need runtime of at least'
                   +#13+' 1/2 second to calculate rate';
End;

procedure TForm1.StopBtnClick(Sender: TObject);
var
  years:single;
  s:string;
begin
  makelabels('Not Complete');
  Screen.cursor:=crArrow;
  EstSecsLbl1.caption:= 'Estimated time to complete: '
      + floattostrf((power(2,nbrdisks)-1)/Rate,ffnumber,8,1)+' seconds';
  years:=power(2,nbrdisks)/(365*24*3600);
  if years>1 then s:=' years)' else s:=' year)';
  EstSecsLbl2.caption:=
   'Est. time at 1 move per second: '
   +#13
   +floattostrf(Power(2,nbrdisks),ffnumber,20,0)
   +' seconds '+#13+'(That''s '
   +floattostrf(years,ffnumber,15,1)+s;
  SolveBtn.enabled:=true;
  StopBtn.enabled:=false;
  stopflag:=true; {Set quit flag}
end;


procedure TForm1.DisksEdtChange(Sender: TObject);
begin
  nbrdisks:=disksedt.value;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  disksedtchange(sender);
  Tower:=TTowers.create;
  Label2.caption:='The first '+ inttostr(maxmovestoList)+' moves';
end;

end.