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 ---