MODULE Hanoi;

	FROM SYSTEM IMPORT ADR;
	IMPORT System;
	IMPORT VDI, v, vr, vsf;
	IMPORT AES, appl, graf;


	CONST
		cMax = 5;

	TYPE
		tTurm = RECORD
			Ebenen: ARRAY[1..cMax] OF SHORTCARD;
			Hoehe, Nr: SHORTCARD;
		END;

	VAR
		A, B, C: tTurm;
		Handle: SHORTINT;
		INIT: BOOLEAN;
		TermChain: System.tTermChain;

	PROCEDURE InitVDI;
		TYPE
			tIn = ARRAY [0..10] OF SHORTINT;
		VAR
			dmy: SHORTINT;
			In : tIn;
			Out : ARRAY[0..127] OF SHORTINT;
	BEGIN
		IF NOT INIT THEN
			IF appl.init () >= 0 THEN
				Handle := graf.handle (dmy, dmy, dmy, dmy);
				In := tIn{1 BY 10, 2};
				v.opnvwk (In, Handle, Out);
				v.hidec (Handle);
				v.clrwk (Handle);
				System.InstallTerm (TermChain, ExitVDI);
				INIT := TRUE;
			END
		END; (* IF *)
	END InitVDI;


	(*$E+ $S-*)
	PROCEDURE ExitVDI;
	BEGIN
		IF INIT THEN
			v.showc (Handle, FALSE);
			v.clsvwk(Handle);
			appl.exit ();
			INIT := FALSE;
		END; (* IF *)
	END ExitVDI;
	(*$E= $S-*)

	PROCEDURE ZeichneScheibe (x, y, w: SHORTINT);
		VAR
			pxy: ARRAY[0..1] OF VDI.tPoint;
			dmy: SHORTINT;
	BEGIN
		pxy[0].x := x * 170 - (w * 6 + 10);
		pxy[0].y := 360 - y * 15 - 15;
		pxy[1].x := x * 170 + w * 6 + 10;
		pxy[1].y := 360 - y * 15;
		VOID (vsf.color (Handle, VDI.Black));
		VOID (vsf.interior (Handle, vsf.Pattern));
		VOID (vsf.style (Handle, 4));
		v.ellipse (Handle, x * 170, 360 - y * 15, w * 6 + 10, w + 4);
		VOID (vsf.perimeter (Handle, FALSE));
		vr.recfl (Handle, pxy);
		VOID (vsf.perimeter (Handle, TRUE));
		VOID (vsf.style (Handle, 2));
		v.ellipse (Handle, x * 170, 360 - y * 15 - 15, w * 6 + 10, w + 4);
	END ZeichneScheibe;


	PROCEDURE LoescheScheibe (x, y, w: SHORTINT);
		VAR
			pxy: ARRAY[0..1] OF VDI.tPoint;
			dmy : SHORTINT;
	BEGIN
		pxy[0].x := x * 170 - (w * 6 + 10);
		pxy[0].y := 360 - y * 15 - 15 - (w + 4);
		pxy[1].x := x * 170 + w * 6 + 10;
		pxy[1].y := 360 - y * 15 + w + 4;
		VOID (vsf.interior (Handle, vsf.Solid));
		VOID (vsf.color (Handle, VDI.White));
		VOID (vsf.perimeter (Handle, FALSE));
		vr.recfl (Handle, pxy);
		VOID (vsf.perimeter (Handle, TRUE))
	END LoescheScheibe;


	PROCEDURE InitTurm (VAR Turm: tTurm; x, Nr: SHORTCARD);
		VAR
			i : SHORTCARD;
	BEGIN
		Turm.Hoehe := x;
		Turm.Nr := Nr;
		FOR i := 1 TO x DO
			Turm.Ebenen[i] := x - i + 1;
			ZeichneScheibe (Turm.Nr, i, Turm.Ebenen[i]);
		END;
		FOR i := x + 1 TO cMax DO
			Turm.Ebenen[i] := 0;
		END;
	END InitTurm;


	PROCEDURE Transport (Anzahl : SHORTCARD; VAR Von, Ueber, Nach: tTurm);

		PROCEDURE Wait;
			VAR
				i : LONGINT;
		BEGIN
			FOR i := 0 TO 100000 DO END;
		END Wait;

	BEGIN
		IF Anzahl > 1 THEN
			Transport (Anzahl - 1, Von, Nach, Ueber);
		END;
		INC (Nach.Hoehe);
		Nach.Ebenen[Nach.Hoehe] := Von.Ebenen[Von.Hoehe];
		LoescheScheibe (Von.Nr, Von.Hoehe, Von.Ebenen[Von.Hoehe]);
		Von.Ebenen[Von.Hoehe] := 0;
		DEC (Von.Hoehe);
		IF Von.Hoehe > 0 THEN
			ZeichneScheibe (Von.Nr, Von.Hoehe, Von.Ebenen[Von.Hoehe]);
		END;
		ZeichneScheibe (Nach.Nr, Nach.Hoehe, Nach.Ebenen[Nach.Hoehe]);
		Wait;
		IF Anzahl > 1 THEN
			Transport (Anzahl - 1, Ueber, Von, Nach);
		END;
	END Transport;


BEGIN
	INIT := FALSE;
	InitVDI;
	InitTurm (A, cMax, 1);
	InitTurm (B, 0, 2);
	InitTurm (C, 0, 3);
	Transport (cMax, A, B, C);
	Transport (cMax, C, B, A);
END Hanoi.
		
	
	