%begin
   %include "mach:extl1.imp"
   %constant %integer pegmargin = 0,
                      pegspace  = 114,
                      pegbase   = 0
   %integer n, discinc, dischigh, dw, xs, xe, yb, yt, discn,
      i, start, finish, top, discolour
   %integer %array pegs(0:2, 0:64)

   %routine init(%integer n)

      discinc = (pegspace-1)//(n+1)
      dischigh = discinc*4
      pegs(0, 0) = n
      pegs(1, 0) = 0
      pegs(2, 0) = 0

      clear

      %for i = 1, 1, n %cycle
         discn = n+1-i
         pegs(0, i) = discn
         dw = discinc*(discn+1)
         xs = pegspace+pegmargin
         xe = xs+dw
         xs = xs-dw
         yb = pegbase+(i-1)*dischigh
         discolour = 1+rem(discn, 7)
         colour(discolour)
         fill(xs, yb, xe, yb+dischigh-1)
      %repeat
   %end

   %routine updown(%integer pos, from, to)
      xs = pegmargin+pegspace*(2*pos+1)
      xe = xs+dw
      xs = xs-dw
      yb = pegbase+(from-1)*dischigh
      yt = pegbase+(to-1)*dischigh
      %if yb>yt %start
         yb = yb-discinc
         %for i = yb-1, -1, yt %cycle
            colour(discolour)
            hline(xs, xe, i)
            colour(black)
            hline(xs, xe, i+dischigh)
         %repeat
      %finish %else %start
         yt = yt-discinc
         %for i = yb, 1, yt-1 %cycle
            colour(discolour)
            hline(xs, xe, i+dischigh)
            colour(black)
            hline(xs, xe, i)
         %repeat
      %finish
   %end

   %routine leftright(%integer from, to, pos)
      xs = pegmargin+pegspace*(2*from+1)-dw
      xe = pegmargin+pegspace*(2*to+1)-dw
      yb = pegbase+(pos-1)*dischigh-discinc
      yt = yb+dischigh-1
      %if xs>xe %start
         %for i = xs, -1, xe+1 %cycle
            colour(discolour)
            vline(i-1, yb, yt)
            colour(black)
            vline(i+dw+dw, yb, yt)
         %repeat
      %finish %else %start
         %for i = xs, 1, xe-1 %cycle
            colour(discolour)
            vline(i+dw+dw+1, yb, yt)
            colour(black)
            vline(i, yb, yt)
         %repeat
      %finish
   %end

   %routine discmove(%integer from, to)
      start = pegs(from, 0)
      discn = pegs(from, start)
      discolour = 1+rem(discn, 7)
      dw = discinc*(discn+1)
      pegs(from, 0) = start-1
      top = 0
      %if from>to %start
         %for i = to, 1, from %cycle
            top = pegs(i, 0)+1 %if pegs(i, 0)>=top
         %repeat
      %finish %else %start
         %for i = from, 1, to %cycle
            top = pegs(i, 0)+1 %if pegs(i, 0)>=top
         %repeat
      %finish
      top = top+1
      finish = pegs(to, 0)+1
      pegs(to, 0) = finish
      pegs(to, finish) = discn
      updown(from, start, top)
      leftright(from, to, top)
      updown(to, top, finish)
   %end

   %routine hanmove(%integer from, to, spare, n)

      n = n-1
      hanmove(from, spare, to, n) %if n>0
      discmove(from, to)
      hanmove(spare, to, from, n) %if n>0
   %end

   prompt("Number of discs? (1:64) :")
   %cycle
      read(n)
      %exit %if n<=0
      %continue %if n>64
      init(n)
      hanmove(0, 2, 1, n)
   %repeat
%end %of %program
