-- AltoPoly.mesa
-- Last Edited by Sandman on  23-Apr-82 14:28:08
-- Last Edited by Daniels on  11-May-82 17:22:47
-- Last Edited by Sweet   on  14-May-82 14:56:11


DIRECTORY
  AltoDisplay,
  DisplayDefs,
  Inline USING [BITXOR, LongDiv, LongMult],
  MiscDefs, 
  Process,
  SystemDefs,
  Window;


AltoPoly: MONITOR
  IMPORTS
    DisplayDefs,Inline, MiscDefs, Process, SystemDefs =
  BEGIN OPEN Inline;

  DisplayWidth: CARDINAL = 38;
  DisplayHeight: CARDINAL = 808;
  DCBchainHead: POINTER TO DCBptr = LOOPHOLE[420B];
  DCBptr: TYPE = POINTER TO DCB;
  DCB: TYPE = AltoDisplay.DCB;
    
  bitmap: POINTER;
  dcb: DCBptr;
  bmWords, bmLines: CARDINAL;
  
  CreateDisplay: PROCEDURE =
    BEGIN
    wordsPerLine: CARDINAL ← DisplayWidth;
    bmLines ← DisplayHeight;
    bmWords ← wordsPerLine * bmLines;
    dcb ← SystemDefs.AllocateResidentSegment[bmWords+SIZE[DCB]];
    bitmap ← dcb+SIZE[DCB];
    MiscDefs.Zero[bitmap, bmWords];
    dcb↑ ← [NIL, high, black, 0, wordsPerLine, bitmap, bmLines/2];
    DCBchainHead↑ ← dcb;
    END;

  VectorSize: CARDINAL = 55;
  i1: CARDINAL ← 0;
  i2: CARDINAL ← VectorSize/2;
  
  vector: ARRAY [0..VectorSize) OF WORD ← [
    031575B, 055455B, 147160B, 176745B, 173126B, 
    117426B, 033612B, 130620B, 054013B, 167672B, 
    070252B, 033100B, 015700B, 113523B, 170465B, 
    024344B, 175535B, 137325B, 126211B, 010207B, 
    173547B, 016071B, 056622B, 014433B, 113225B, 
    047553B, 103025B, 110174B, 000125B, 173304B, 
    076700B, 104042B, 135030B, 126234B, 175154B, 
    140123B, 167542B, 000405B, 035464B, 166537B, 
    050260B, 167655B, 123615B, 175164B, 172206B, 
    140365B, 074606B, 075656B, 176163B, 030027B, 
    022102B, 040051B, 154630B, 017144B, 073372B];

  Word: PUBLIC PROCEDURE RETURNS [ret: WORD] =
    BEGIN
    ret ← vector[i1] ← vector[i1] + vector[i2];
    IF (i1 ← i1+1) >= VectorSize THEN i1 ← 0;
    IF (i2 ← i2+1) >= VectorSize THEN i2 ← 0;
    RETURN
    END;
    
  seed: CARDINAL;

  Random: PROCEDURE [low, high: CARDINAL ← 0] RETURNS [CARDINAL] =
    BEGIN
    seed ← Word[];
    RETURN[IF high = 0 THEN seed ELSE ((seed MOD (high-low+1)) + low)];
    END;
    
  movie: BOOLEAN ← FALSE;
  moviePause: CARDINAL ← 100;

  DoIt: PROCEDURE = {
    nPoints: [3..6] = Random[high: 6, low: 3];
    start, stop, middle, oldMiddle: ARRAY [0..6) OF Window.Place;
    dims: Window.Dims = [w: 608, h: 808];
    first: BOOLEAN ← TRUE;
    DrawPolygon: PROC [
      points: POINTER TO ARRAY [0..6) OF Window.Place, op: DisplayOp ← set] = {
      FOR i: CARDINAL IN [0..nPoints) DO
      DisplaySolidLine[start: points[i], stop: points[(i+1) MOD nPoints],
        op: op];
      ENDLOOP};
    DrawDashed: PROC = {
      FOR i: CARDINAL IN [0..nPoints) DO
        DisplayDashedLine[start: start[i], stop: stop[i]];
        ENDLOOP};
    EraseOldMiddle: PROC = {
      DrawPolygon[@oldMiddle, xor]}; 
      -- DrawPolygon[@start]; DrawPolygon[@stop]; DrawDashed[]};
    FOR i: CARDINAL IN [0..nPoints) DO
      start[i] ← [x: Random[high: dims.w-1], y: Random[high: dims.h-1]];
      stop[i] ← [x: Random[high: dims.w-1], y: Random[high: dims.h-1]];
      ENDLOOP;
    MiscDefs.Zero[bitmap, bmWords];
    DrawPolygon[@start];
    Pause[750];
    DrawPolygon[@stop];
    Pause[750];
    DrawDashed[];
    Pause[1500];
    IF ~movie THEN MiscDefs.Zero[bitmap, bmWords];
    oldMiddle ← start;
    FOR i: CARDINAL IN [0..interval] DO
      FOR j: CARDINAL IN [0..nPoints) DO
        middle[j] ← PointOnLine[
	  start: start[j], stop: stop[j], i: i, n: interval];
	ENDLOOP;
      DrawPolygon[@middle, IF movie THEN xor ELSE set];
      IF first THEN first ← FALSE
      ELSE IF movie THEN {EraseOldMiddle[]; Pause[moviePause]};
      oldMiddle ← middle;
      ENDLOOP;
    IF movie THEN EraseOldMiddle[];
    Pause[2500]};

  Pause: ENTRY PROCEDURE [msec: CARDINAL] = {
    cond: CONDITION ← [timeout: Process.MsecToTicks[msec]];
    WAIT cond};

  interval: CARDINAL ← 40;

  running, deactivating: BOOLEAN ← FALSE;

  wait: CONDITION ← [timeout: Process.SecondsToTicks[1]];

  Line: TYPE = POINTER TO PACKED ARRAY [0..608] OF [0..1];
  LineArray: TYPE = ARRAY [0..808) OF Line;
  lines: POINTER TO ARRAY [0..808) OF Line;

  InitLineArray: PROC = {
    wordsPerScanLine: CARDINAL = 38;
    lp: POINTER ← bitmap;
    lines ← SystemDefs.AllocateResidentSegment[SIZE[LineArray]];
    FOR i: CARDINAL IN [0..808) DO lines[i] ← lp + i*wordsPerScanLine; ENDLOOP};

  Vector: TYPE = RECORD [value: CARDINAL, neg: BOOLEAN];

  Vectorfy: PROC [start, stop: INTEGER] RETURNS [Vector] = INLINE {
    IF start < stop THEN RETURN[[value: stop - start, neg: FALSE]]
    ELSE RETURN[[value: start - stop, neg: TRUE]]};
    
  DisplayOp: TYPE = {set, xor};

  DisplaySolidLine: PROC [start, stop: Window.Place, op: DisplayOp] =
    BEGIN
    twodMajor, twodMajorminus2dMinor, xDir, yDir, e: INTEGER;
    deltaY, deltaX: Vector;
    deltaX ← Vectorfy[start: start.x, stop: stop.x];
    deltaY ← Vectorfy[start: start.y, stop: stop.y];
    IF deltaY.neg THEN yDir ← -1 ELSE yDir ← 1;
    IF deltaX.neg THEN xDir ← -1 ELSE xDir ← 1;
    IF deltaY.value > deltaX.value THEN
      BEGIN
      twodMajor ← 2*deltaX.value;
      twodMajorminus2dMinor ← twodMajor - 2*deltaY.value;
      e ← 2*deltaX.value - deltaY.value;
      UNTIL start.y = stop.y DO
	IF op = set THEN lines[start.y][start.x] ← 1
	ELSE lines[start.y][start.x] ← 
	  Inline.BITXOR[lines[start.y][start.x], 1];
	IF e > 0 THEN {
	  start.x ← start.x + xDir; e ← e + twodMajorminus2dMinor}
	ELSE e ← e + twodMajor;
     	start.y ← start.y + yDir;
	ENDLOOP;
      END
    ELSE -- shallow
      BEGIN
      twodMajor ← 2*deltaY.value;
      twodMajorminus2dMinor ← twodMajor - 2*deltaX.value;
      e ← 2*deltaY.value - deltaX.value;
      UNTIL start.x = stop.x DO
	IF op = set THEN lines[start.y][start.x] ← 1
	ELSE lines[start.y][start.x] ← 
	  Inline.BITXOR[lines[start.y][start.x], 1];
	IF e > 0 THEN {
	  start.y ← start.y + yDir; e ← e + twodMajorminus2dMinor}
	ELSE e ← e + twodMajor;
	start.x ← start.x + xDir;
	ENDLOOP;
      END
    END;
	 
  DisplayDashedLine: PROC [start, stop: Window.Place] =
    BEGIN
    twodMajor, twodMajorminus2dMinor, xDir, yDir, e: INTEGER;
    deltaY, deltaX: Vector;
    count: CARDINAL ← 0;
    value: [0..1] ← 1;
    deltaX ← Vectorfy[start: start.x, stop: stop.x];
    deltaY ← Vectorfy[start: start.y, stop: stop.y];
    IF deltaY.neg THEN yDir ← -1 ELSE yDir ← 1;
    IF deltaX.neg THEN xDir ← -1 ELSE xDir ← 1;
    IF deltaY.value > deltaX.value THEN
      BEGIN
      twodMajor ← 2*deltaX.value;
      twodMajorminus2dMinor ← twodMajor - 2*deltaY.value;
      e ← 2*deltaX.value - deltaY.value;
      UNTIL start.y = stop.y DO
	lines[start.y][start.x] ← value;
	IF e > 0 THEN {
	  start.x ← start.x + xDir; e ← e + twodMajorminus2dMinor}
	ELSE e ← e + twodMajor;
     	start.y ← start.y + yDir;
	IF count = 5 THEN {
	  value ← Inline.BITXOR[value, 1]; count ← 0}
	ELSE count ← count + 1;
	ENDLOOP;
      END
    ELSE -- shallow
      BEGIN
      twodMajor ← 2*deltaY.value;
      twodMajorminus2dMinor ← twodMajor - 2*deltaX.value;
      e ← 2*deltaY.value - deltaX.value;
      UNTIL start.x = stop.x DO
	lines[start.y][start.x] ← value;
	IF e > 0 THEN {
	  start.y ← start.y + yDir; e ← e + twodMajorminus2dMinor}
	ELSE e ← e + twodMajor;
	start.x ← start.x + xDir;
	IF count = 5 THEN {
	  value ← Inline.BITXOR[value, 1]; count ← 0}
	ELSE count ← count + 1;
	ENDLOOP;
      END
    END;
	 
	  	  	 
  PointOnLine: PROC [
    start, stop: Window.Place, i, n: INTEGER] RETURNS [place: Window.Place] =
    BEGIN
    vec: Vector ← Vectorfy[start: start.x, stop: stop.x];
    delta: CARDINAL ← LongDiv[LongMult[vec.value, i], n];
    place.x ← IF vec.neg THEN start.x - delta ELSE start.x + delta;
    vec ← Vectorfy[start: start.y, stop: stop.y];
    delta ← LongDiv[LongMult[vec.value, i], n];
    place.y ← IF vec.neg THEN start.y - delta ELSE start.y + delta;
    END;
  
  DisplayDefs.DestroyDisplay[];
  CreateDisplay[];
  InitLineArray[];
  AltoDisplay.Cursor↑ ← ALL[0];
  DO
    DoIt[];
    ENDLOOP;
  
  END...


~~~~~~~~~~