SHULMAN@sdr.slb.com (Jeffrey Shulman) (05/05/88)
[Towers of Hanoi - Uploaded from Delphi by Jeff Shulman]
Name: TOWERS OF HANOI
Date: 3-APR-1988 17:09 by SOCCERKING
This is the same old towers of hanoi problem but with a few new twists.
If you are interested you can check out the source code. This program
is simply for your enjoyment and curiosity. I hope you enjoy it. Does
not run under MultiFinder.
[Moderator's Note: The application and a PackIt archive of the source
and Lightspeed Pascal project have been posted in comp.binaries.mac.]
---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# Towers.lp
# This archive created: Wed May 4 08:16:04 1988
# By: Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Towers.lp'" '(21552 characters)'
if test -f 'Towers.lp'
then
echo shar: will not over-write existing file "'Towers.lp'"
else
sed 's/^X//' << \SHAR_EOF > 'Towers.lp'
XPROGRAM RotBarcb;
X{NOTES:}
X{*A bar is a ring on a peg}
X{*All bars use the same bitmap to restore what it has erased}
X{*A move is when a bar goes from one peg to anther}
X CONST
X kAngle = 9; {angle between each turn of the bar}
X kNumTurn = 5; {90 div 9}
X kBase = 10; {numturn * 2}
X kBarWid = 4; {width of bar div 2}
X kNumFrame = 40; {numturn * 8 }
X kPi = 3.141592654;
X kAlt = 67; {Height when bar should switch directions}
X kPeg1 = 80; {Pos of peg A}
X kPeg2 = 256; {Pos of peg B}
X kPeg3 = 432; {Pos of peg C}
X kVel = 4; {Velocity at which pegs travel}
X kMaxBar = 6; {Maximun number of bars}
X kMaxMove = 2; {Maximun number of bars moving at one time}
X kMaxQue = 100; {maximun number of elements in que}
X kDLOG = 129; {Dialog ID}
X
X TYPE
X tPeg = (A, B, C);
X tBar = 0..kMaxBar;
X tMove = 0..kMaxMove;
X tQueNum = 1..kMaxQue;
X tFrame = 0..kNumFrame;
X
X tElement = RECORD {Each element in the queue holds a move}
X fFrom : tPeg;
X fTo : tPeg;
X END;
X
X{A stack holds the bars on each peg}
X tStack = RECORD
X fElements : ARRAY[tBar] OF tBar;
X fTos : tBar;
X END;
X
X{The Que holds the moves waiting to be preformed}
X tQueue = RECORD
X fElements : ARRAY[tQueNum] OF tElement;
X fFront, fRear : tQueNum;
X END;
X
X{Hold the information for each frame of a bar}
X tBarData = RECORD
X fRgn : RgnHandle;
X fOrg : point;
X END;
X
X{Hold the information for the bar}
X{NOTES:}
X{*Memory is radically sacrificed for speed}
X{*fAlmost is used to tell MoveBars that the bar has reached its loc but}
X{ it still needs to spin}
X{*When a bar is at some peg and the bar above spins it will}
X{ erase the bars underneath it because they are not part of gSavePort}
X{ To fix this we save the bits underneath the bar at a peg in fSaveBits}
X{ and restore them after the peg moves}
X{*As much information to realated to a bar as possible is stored in tBarInfo}
X tBarInfo = RECORD
X fFrame : ARRAY[tFrame] OF tBarData; {Hold the frames of the bar}
X fInd : tFrame; {Hold the current index into fFrame}
X fLastInd : tFrame; {Hold the last index into the fFrame}
X fIndFill : tFrame; {Hold the index to the last horz frame}
X fRad : integer; {Hold the radius of the bar}
X fLoc : point; {Hold the current location of the bar}
X fDestLoc : point; {Hold the destination location}
X fVel : point; {Hold the current velocity of the bar}
X fOldRect : rect; {Hold the previous position of the bar}
X fColor : Pattern; {Hold the color of the bar}
X fAlmost : boolean; {Used to tell some proc that the bar still needs to spin}
X fSaveBits : BitMap; {Used to save the bits of gSavePort}
X fTo : tPeg; {Destination peg}
X END;
X
X{This record stores the stack of bars on it}
X{and if this peg is free to move a bar to}
X tPegInfo = RECORD
X fFree : boolean; {Peg available?}
X fBars : tStack; {Stack of bars}
X END;
X
X tBars = ARRAY[tBar] OF tBarInfo; {Hold all bars}
X tPegs = ARRAY[tPeg] OF tPegInfo; {Hold all Pegs}
X tMoveBars = ARRAY[tMove] OF tBar; {Hold moving bars}
X tPegPositions = ARRAY[tPeg] OF integer; {Hold positions of Pegs}
X tBarPositions = ARRAY[tBar] OF integer; {Hold positions of bars}
X
X VAR
X gSavePort : GrafPtr; {Hold the port which saves the image}
X gDrawPort : GrafPtr; {Hold the port to draw in}
X gNumBars : tBar; {Hold the number of bars}
X gBar : tBars; {Hold the bars}
X gPeg : tPegs; {Hold the pegs}
X gMoveQue : tQueue; {Hold the move queue}
X gMoveBar : tMoveBars; {Hold the moving bars}
X gPegPos : tPegPositions; {Hold the peg positions}
X gBarPos : tBarPositions; {Hold the bar positions}
X gEraseRgn : RgnHandle; {Hold the erase region in PlotBar to save time}
X
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X{Stack routines}
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X
X{*****************************************************************************}
X{Init the stack pPeg}
X{*****************************************************************************}
X PROCEDURE InitStack (pPeg : tPeg);
X BEGIN
X gPeg[pPeg].fBars.fTos := 0;
X END;
X
X{*****************************************************************************}
X{Push pBar onto the stack of pPeg}
X{*****************************************************************************}
X PROCEDURE Push (pBar : tBar;
X pPeg : tPeg);
X VAR
X lTemp : rect;
X BEGIN
X WITH gPeg[pPeg].fBars DO
X BEGIN
X fTos := fTos + 1;
X fElements[fTos] := pBar;
X END;
X WITH gBar[pBar] DO {We must Draw the bar in gSavePort}
X BEGIN
X{Calculate its rectangle on the screen}
X SetRect(lTemp, fLoc.h - fRad, fLoc.v - 4, fLoc.h + fRad, fLoc.v + 4);
X SetPort(gSavePort);
X{Save gSavePort's bits}
X CopyBits(gSavePort^.portBits, fSaveBits, lTemp, fSaveBits.bounds, srccopy, NIL);
X FillRgn(fFrame[fIndFill].fRgn, fColor); {Draw it in gSavePort}
X SetPort(gDrawPort);
X END;
X END;
X
X{*****************************************************************************}
X{Get vBar out of the stack of pPeg}
X{*****************************************************************************}
X PROCEDURE Pop (VAR vBar : tBar;
X pPeg : tPeg);
X VAR
X lTemp : rect;
X BEGIN
X WITH gPeg[pPeg].fBars DO
X BEGIN
X vBar := fElements[fTos];
X fTos := fTos - 1;
X END;
X WITH gBar[vBar] DO {Restore the saved bits}
X BEGIN
X SetRect(lTemp, fLoc.h - fRad, fLoc.v - 4, fLoc.h + fRad, fLoc.v + 4);
X CopyBits(fSaveBits, gSavePort^.portBits, fSaveBits.bounds, lTemp, srccopy, NIL);
X END;
X END;
X
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X{Queue routines}
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X
X{*****************************************************************************}
X{Init the Queue}
X{*****************************************************************************}
X PROCEDURE InitQue;
X BEGIN
X gMoveQue.fFront := 1;
X gMoveQue.fRear := 1;
X END;
X
X{*****************************************************************************}
X{Get the next index into the queue}
X{*****************************************************************************}
X PROCEDURE NextInd (VAR vInd : tQueNum);
X BEGIN
X IF vInd = kMaxQue THEN
X vInd := 1
X ELSE
X vInd := vInd + 1;
X END;
X
X{*****************************************************************************}
X{Enq this move}
X{*****************************************************************************}
X PROCEDURE Enq (pFrom, pTo : tPeg);
X BEGIN
X WITH gMoveQue DO
X BEGIN
X fElements[fRear].fFrom := pFrom;
X fElements[fRear].fTo := pTo;
X NextInd(fRear);
X END;
X END;
X
X{*****************************************************************************}
X{Deq the next move and put it into vElem}
X{*****************************************************************************}
X PROCEDURE Deq (VAR vElem : tElement);
X BEGIN
X WITH gMoveQue DO
X BEGIN
X vElem := fElements[fFront];
X NextInd(fFront);
X END;
X END;
X
X{*****************************************************************************}
X{Get the move to be returned at the next Deq}
X{*****************************************************************************}
X PROCEDURE TopElem (VAR vElem : tElement);
X BEGIN
X WITH gMoveQue DO
X vElem := fElements[fFront];
X END;
X
X{*****************************************************************************}
X{Return true if the que is empty}
X{*****************************************************************************}
X FUNCTION EmptyQue : boolean;
X BEGIN
X EmptyQue := gMoveQue.fFront = gMoveQue.fRear;
X END;
X
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X{Drawing routines}
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X
X{*****************************************************************************}
X{Plot pBar using all the info in its record}
X{*****************************************************************************}
X PROCEDURE PlotBar (pBar : tBar);
X
X{ ***************************************************************************}
X{ Move the regions center to the absolute location (pLoch,pLocv)}
X{ ***************************************************************************}
X PROCEDURE MoveRgn (pBarData : tBarData;
X pLoch, pLocv : integer);
X VAR
X dh, dv : integer;
X BEGIN
X WITH pBarData.fRgn^^.rgnBBox, pBarData DO
X BEGIN
X OffsetRgn(pBarData.fRgn, fOrg.h - left, fOrg.v - top);
X OffsetRgn(pBarData.fRgn, pLoch, pLocv);
X END;
X END;
X
X BEGIN
X WITH gBar[pBar] DO
X BEGIN
X fInd := fInd + 1; {Inc the index}
X MoveRgn(fFrame[fInd], fLoc.h, fLoc.v); {Move the regionto the new loc}
X DiffRgn(fFrame[fLastInd].fRgn, fFrame[fInd].fRgn, gEraseRgn); {Calc the erase rgn}
X FillRgn(fFrame[fInd].fRgn, fColor); {Draw the bar}
X{Restore the Bits}
X CopyBits(gSavePort^.portBits, gDrawPort^.portBits, fOldRect, fOldRect, srccopy, gEraseRgn);
X fLastInd := fInd;
X SetRect(fOldRect, fLoc.h - fRad, fLoc.v - fRad, fLoc.h + fRad, fLoc.v + fRad);
X IF fInd = kNumFrame THEN
X fInd := 0;
X END;
X END;
X
X{*****************************************************************************}
X{Start the move in pElem}
X{*****************************************************************************}
X PROCEDURE StartMove (pElem : tElement);
X VAR
X lBar : tBar;
X lMove : tMove;
X BEGIN
X gPeg[pElem.fTo].fFree := false; {Mark the dest peg as used}
X pop(lBar, pElem.fFrom); {Get the bar to move}
X WITH gBar[lBar] DO {Init the bar to move}
X BEGIN
X fAlmost := false;
X SetPt(fVel, 0, -kVel);
X SetPt(fDestLoc, gPegPos[pElem.fTo], gBarPos[gPeg[pElem.fTo].fBars.fTos + 1]);
X fTo := pElem.fTo;
X END;
X{Put the bar into the next available slot in gMoveBar}
X lMove := 0;
X REPEAT
X lMove := lMove + 1;
X IF gMoveBar[lMove] = 0 THEN
X BEGIN
X gMoveBar[lMove] := lBar;
X lMove := kMaxMove;
X END;
X UNTIL lMove = kMaxMove;
X END;
X
X{*****************************************************************************}
X{Move the bars in gMoveBar}
X{*****************************************************************************}
X PROCEDURE MoveBars;
X VAR
X x : tMove;
X
X{ ***************************************************************************}
X{ Adjust the fLoc field of bar pBar and change direction if neccessary}
X{ Return true if bar has arrived at destination}
X{ ***************************************************************************}
X FUNCTION MoveTheBar (pBar : tBar) : boolean;
X BEGIN
X MoveTheBar := false;
X WITH gBar[pBar] DO {Adjust the velocity of the bar}
X BEGIN
X IF fVel.v = -kVel THEN
X IF fLoc.v <= kAlt THEN
X BEGIN
X fVel.v := 0;
X IF fLoc.h > fDestLoc.h THEN
X fVel.h := -kVel
X ELSE
X fVel.h := kVel;
X END;
X IF fVel.v = 0 THEN
X BEGIN
X IF fVel.h = kVel THEN
X IF fLoc.h >= fDestLoc.h THEN
X BEGIN
X fVel.h := 0;
X fVel.v := kVel;
X END;
X IF fVel.h = -kVel THEN
X IF fLoc.h <= fDestLoc.h THEN
X BEGIN
X fVel.h := 0;
X fVel.v := kVel;
X END;
X END;
X IF fVel.v = kVel THEN
X IF fLoc.v >= fDestLoc.v THEN
X fAlmost := true;
X IF fAlmost THEN {do not adjust fLoc}
X BEGIN
X IF (fInd = 10) OR (fInd = 30) THEN
X BEGIN
X fIndFill := fInd + 1;
X MoveTheBar := true;
X END;
X END
X ELSE {Adjust it}
X AddPt(fVel, fLoc);
X PlotBar(pBar); {Plot the bar}
X END;
X END;
X
X BEGIN
X{Update every bar in gMoveBar}
X FOR x := 1 TO kMaxMove DO
X IF gMoveBar[x] > 0 THEN
X IF MoveTheBar(gMoveBar[x]) THEN {We arrived}
X BEGIN
X Push(gMoveBar[x], gBar[gMoveBar[x]].fTo);
X gPeg[gBar[gMoveBar[x]].fTo].fFree := true;
X gMoveBar[x] := 0;
X END;
X END;
X
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X{Processing routines}
X{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
X
X{*****************************************************************************}
X{*****************************************************************************}
X{Decide if we can move a bar and return true if nothing left to do}
X{NOTE: This is the heart of the whole program}
X{*****************************************************************************}
X{*****************************************************************************}
X FUNCTION SystemTime : boolean;
X VAR
X lMove : tMove;
X lTempB : boolean;
X lElem : tElement;
X BEGIN
X IF button THEN {We are tired of watching these bars go in circles}
X ExitToShell;
X lTempB := true;
X{Is there room to in gMoveBar}
X FOR lMove := 1 TO kMaxMove DO
X lTempB := lTempB AND (gMoveBar[lMove] <> 0);
X IF NOT EmptyQue AND NOT lTempB THEN {A move is possible}
X BEGIN
X TopElem(lElem);
X IF gPeg[lElem.fTo].fFree AND gPeg[lElem.fFrom].fFree THEN {Ok to move}
X BEGIN
X Deq(lElem);
X StartMove(lElem);
X END;
X END;
X{Check to see if anything left do}
X lTempB := true;
X FOR lMove := 1 TO kMaxMove DO
X lTempB := lTempB AND (gMoveBar[lMove] = 0);
X SystemTime := EmptyQue AND lTempB;
X MoveBars;
X END;
X
X{*****************************************************************************}
X{Calculate the moves to preform}
X{*****************************************************************************}
X PROCEDURE Hanoi (pNumRings : tBar;
X pFrom, pTo, pUsing : tPeg);
X BEGIN
X IF SystemTime THEN
X ;
X IF pNumRings = 1 THEN
X Enq(pFrom, pTo)
X ELSE
X BEGIN
X hanoi(pNumRings - 1, pFrom, pUsing, pTo);
X Enq(pFrom, pTo);
X hanoi(pNumRings - 1, pUsing, pTo, pFrom);
X END;
X END;
X
X{*****************************************************************************}
X{Init the program}
X{*****************************************************************************}
X PROCEDURE Init;
X
X{ ***************************************************************************}
X{ Get the number of bars to move}
X{ ***************************************************************************}
X PROCEDURE GetNumBars;
X VAR
X lDlog : DialogPtr;
X lItem : integer;
X lType : integer;
X lItemHand : Handle;
X lBox : Rect;
X lText : str255;
X lRslt : longint;
X BEGIN
X lDlog := GetNewDialog(kDLOG, NIL, pointer(-1));
X REPEAT
X ModalDialog(NIL, lItem);
X GetDItem(lDlog, 2, ltype, lItemHand, lBox);
X GetIText(lItemHand, lText);
X StringToNum(lText, lRslt);
X gNumBars := integer(lRslt);
X UNTIL (gNumBars <= 6) AND (gNumBars >= 3);
X DisposDialog(lDlog);
X END;
X
X{ ***************************************************************************}
X{ Draw the Pegs}
X{ ***************************************************************************}
X PROCEDURE DrawScreen;
X VAR
X lTemp : Rect;
X BEGIN
X SetPort(gDrawPort);
X SetRect(lTemp, 8, 235, 152, 243);
X FillRect(lTemp, Black);
X SetRect(lTemp, 184, 235, 328, 243);
X FillRect(lTemp, Black);
X SetRect(lTemp, 360, 235, 504, 243);
X FillRect(lTemp, Black);
X SetRect(lTemp, 76, 99, 84, 235);
X FillRect(lTemp, Black);
X SetRect(lTemp, 252, 99, 260, 235);
X FillRect(lTemp, Black);
X SetRect(lTemp, 428, 99, 436, 235);
X FillRect(lTemp, Black);
X END;
X
X{ ***************************************************************************}
X{ Calculate the data for the frames of the bars}
X{ ***************************************************************************}
X PROCEDURE SetupData;
X VAR
X lBar : tBar;
X lFrame : integer;
X PtA, PtB : point;
X
X{ **************************************************************************}
X{ Calculate two point tangent to the line pAngle degrees around the circle}
X{ **************************************************************************}
X PROCEDURE Get2Tang (pAngle : real;
X pRad : integer;
X VAR PtA, PtB : point);
X VAR
X temp, temp2, xc, yc, m, perpm : real;
X BEGIN
X yc := pRad * cos(pAngle * pi / 180);
X xc := pRad * sin(pAngle * pi / 180);
X perpm := -xc / yc;
X temp := kBarWid / (perpm * perpm + 1);
X temp2 := temp * perpm;
X PtA.h := round(yc - temp2);
X PtA.v := round(xc - temp);
X PtB.h := round(yc + temp2);
X PtB.v := round(xc + temp);
X END;
X
X{ **************************************************************************}
X{ Transform PtA and PtB into 8 more points}
X{ **************************************************************************}
X PROCEDURE BuildData (pInd : integer;
X pBar : tBar;
X PtA, PtB : point);
X
X{ *************************************************************************}
X{ Build a region around the given points}
X{ *************************************************************************}
X PROCEDURE InsertElem (pIndex, pP1h, pP1v, pP2h, pP2v : integer);
X BEGIN
X WITH gBar[pBar] DO
X BEGIN
X fFrame[pIndex].fRgn := NewRgn;
X OpenRgn;
X MoveTo(pP1h, pP1v);
X LineTo(pP2h, pP2v);
X LineTo(-pP1h, -pP1v);
X LineTo(-pP2h, -pP2v);
X LineTo(pP1h, pP1v);
X CloseRgn(fFrame[pIndex].fRgn);
X fFrame[pIndex].fOrg := fFrame[pIndex].fRgn^^.rgnBBox.topleft;
X OffsetRgn(fFrame[pIndex].fRgn, fLoc.h, fLoc.v);
X END;
X END;
X
X BEGIN
X InsertElem(pInd, -PtA.v, PtA.h, -PtB.v, PtB.h);
X IF pInd <> 6 THEN
X InsertElem(kBase - pInd + 2, PtA.h, -PtA.v, PtB.h, -PtB.v);
X InsertElem(kBase + pInd, -PtA.h, -PtA.v, -PtB.h, -PtB.v);
X IF pInd <> 6 THEN
X InsertElem(kBase * 2 - pInd + 2, -PtA.v, -PtA.h, -PtB.v, -PtB.h);
X InsertElem(kBase * 2 + pInd, PtA.v, -PtA.h, PtB.v, -PtB.h);
X IF pInd <> 6 THEN
X InsertElem(kBase * 3 - pInd + 2, -PtA.h, PtA.v, -PtB.h, PtB.v);
X InsertElem(kBase * 3 + pInd, PtA.h, PtA.v, PtB.h, PtB.v);
X IF pInd <> 1 THEN
X InsertElem(kBase * 4 - pInd + 2, PtA.v, PtA.h, PtB.v, PtB.h);
X END;
X
X BEGIN
X FOR lBar := 1 TO gNumBars DO
X WITH gBar[lBar] DO {init the bar}
X BEGIN
X fRad := 16 + (lBar - 1) * 8;
X fInd := 10;
X fLastInd := 10;
X fIndFill := 11;
X fAlmost := false;
X WITH fSaveBits, bounds DO {Create fSaveBits}
X BEGIN
X SetRect(bounds, 0, 0, fRad * 2, 8);
X rowBytes := (((right - left - 1) DIV 16) + 1) * 2;
X baseAddr := NewPtr(rowBytes * (bottom - top));
X END;
X SetPt(fVel, 0, kVel);
X SetPt(fLoc, kPeg1, kAlt);
X SetPt(fDestLoc, kPeg1, (183 + (kMaxBar - gNumBars) * 8) + (lBar * 8));
X fTo := A;
X SetRect(fOldRect, fLoc.h - fRad, fLoc.v - fRad, fLoc.h + fRad, fLoc.v + fRad);
X GetIndPattern(fColor, sysPatListID, lBar + 1);
X FOR lFrame := 1 TO kNumTurn + 1 DO
X BEGIN
X Get2Tang((lFrame - 1) * kAngle, fRad, PtA, PtB);
X BuildData(lFrame, lBar, PtA, PtB);
X END;
X END;
X END;
X
X{ *****************************************************************************}
X{ Setup the Toolbox}
X{ *****************************************************************************}
X PROCEDURE InitToolbox;
X BEGIN
X InitGraf(@thePort);
X MoreMasters;
X MoreMasters;
X MoreMasters;
X MoreMasters;
X MoreMasters;
X MoreMasters;
X MoreMasters;
X MoreMasters;
X MaxApplZone;
X InitFonts;
X InitWindows;
X InitCursor;
X HideCursor;
X END;
X
X{ *****************************************************************************}
X{ Setup gSavePort}
X{ *****************************************************************************}
X PROCEDURE SetupSavePort;
X BEGIN
X gSavePort := GrafPtr(NewPtr(sizeof(GrafPort)));
X gEraseRgn := NewRgn;
X OpenPort(gSavePort);
X WITH gSavePort^, portBits, bounds DO
X BEGIN
X bounds := gDrawPort^.portBits.Bounds;
X portRect := bounds;
X rowBytes := (((right - left - 1) DIV 16) + 1) * 2;
X baseAddr := NewPtr(rowBytes * (bottom - top));
X cliprect(portRect);
X RectRgn(visrgn, portrect);
X END;
X END;
X
X{ *****************************************************************************}
X{ Setup the global variables}
X{ *****************************************************************************}
X PROCEDURE InitGlobals;
X VAR
X lBar : tBar;
X lMove : tMove;
X lPeg : tPeg;
X BEGIN
X InitQue;
X FOR lPeg := A TO C DO
X BEGIN
X InitStack(lPeg);
X gPeg[lPeg].fFree := true;
X END;
X FOR lMove := 1 TO kMaxMove DO
X gMoveBar[lMove] := 0;
X gPegPos[A] := kPeg1;
X gPegPos[B] := kPeg2;
X gPegPos[C] := kPeg3;
X FOR lBar := gNumBars DOWNTO 1 DO
X BEGIN
X gMoveBar[1] := lBar;
X WHILE NOT SystemTime DO
X ;
X END;
X FOR lBar := 1 TO gNumBars DO
X gBarPos[lBar] := gBar[gNumBars - lBar + 1].fDestLoc.v;
X END;
X
X BEGIN
X InitToolbox;
X GetPort(gDrawPort);
X SetUpSavePort;
X DrawScreen;
X CopyBits(gDrawPort^.portBits, gSavePort^.portBits, gDrawPort^.portRect, gSavePort^.portRect, srcCopy, NIL);
X GetNumBars;
X SetUpData;
X InitGlobals;
X END;
X
X{*******************************************************************************}
X{Make the magic happen by calling Hanoi and then SystemTime until done}
X{*******************************************************************************}
X PROCEDURE DoIt;
X VAR
X x : integer;
X BEGIN
X WHILE true DO
X BEGIN
X Hanoi(gNumBars, A, B, C);
X WHILE NOT SystemTime DO
X ;
X SetPort(gDrawPort);
X FOR x := 1 TO 16 DO
X InvertRect(gDrawPort^.PortRect);
X Hanoi(gNumBars, B, C, A);
X WHILE NOT SystemTime DO
X ;
X SetPort(gDrawPort);
X FOR x := 1 TO 16 DO
X InvertRect(gDrawPort^.PortRect);
X Hanoi(gNumBars, C, A, B);
X WHILE NOT SystemTime DO
X ;
X SetPort(gDrawPort);
X FOR x := 1 TO 16 DO
X InvertRect(gDrawPort^.PortRect);
X END;
X END;
X
XBEGIN
X Init;
X DoIt;
XEND.
SHAR_EOF
if test 21552 -ne "`wc -c < 'Towers.lp'`"
then
echo shar: error transmitting "'Towers.lp'" '(should have been 21552 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
---