home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / LASER / HPMAZE.ZIP / HPMAZE.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-11-02  |  37.8 KB  |  963 lines

  1. PROGRAM hpmaze;
  2.   {
  3.          This program will generate a three dimensional maze suitable for
  4.     printing on a Hewlett-Packard LaserJet IID printer.  A different
  5.     random number seed will produce a different maze.
  6.  
  7.          Written by James L. Dean
  8.                     406 40th Street
  9.                     New Orleans, LA 70124
  10.   }
  11.   USES Crt;
  12.  
  13.   CONST
  14.     { printer constants }
  15.     DOTS_PER_INCH    =  300;
  16.     WIDTH_IN_INCHES  =    8.5;
  17.     LENGTH_IN_INCHES =   11.0;
  18.     DOTS_PER_STROKE  =    1;   { 300 DIV DOTS_PER_INCH }
  19.     NUM_Y_DOTS       = 2550;   { trunc(WIDTH_IN_INCHES*DOTS_PER_INCH) }
  20.     Y_DOT_MAX        = 2549;   { NUM_Y_DOTS-1 }
  21.     NUM_X_BYTES      =  412;   { trunc(LENGTH_IN_INCHES*DOTS_PER_INCH/8.0) }
  22.     X_BYTE_MAX       =  411;   { NUM_X_BYTES-1 }
  23.     NUM_X_DOTS       = 3296;   { 8*NUM_X_BYTES }
  24.     X_DOT_MAX        = 3295;   { NUM_X_DOTS-1 }
  25.     NUM_SLICES       =    4;   { smaller values run faster, use more memory }
  26.     ROWS_PER_SLICE   =  638;   { (NUM_Y_DOTS+NUM_SLICES-1) DIV NUM_SLICES }
  27.  
  28.     { maze constants }
  29.     MIN_DOTS_PER_ROOM_WALL = 40;
  30.     NUM_COLUMNS            = 32;   { <= NUM_X_DOTS DIV MIN_DOTS_PER_ROOM_WALL }
  31.     MAX_X                  = 64;   { 2*NUM_COLUMNS }
  32.     NUM_ROWS               = 24;   { <= NUM_Y_DOTS DIV MIN_DOTS_PER_ROOM_WALL }
  33.     MAX_Y                  = 48;   { 2*NUM_ROWS }
  34.     { float(NUM_COLUMNS)/float(NUM_ROWS) should be approximately
  35.       LENGTH_IN_INCHES/WIDTH_IN_INCHES }
  36.     { memory requirements and run time increase with NUM_COLUMNS*NUM_ROWS }
  37.     { HPMAZE.TMP requires 104*(2*NUM_COLUMNS+3)*(2*NUM_ROWS+3) bytes of
  38.       space }
  39.  
  40.     { escape sequences }
  41.     cursor_x_prefix : ARRAY [1..3] OF CHAR = (#27,'*','p');
  42.     cursor_x_suffix : CHAR = 'X';
  43.     cursor_y_prefix : ARRAY [1..3] OF CHAR = (#27,'*','p');
  44.     cursor_y_suffix : CHAR = 'Y';
  45.     dpi_prefix      : ARRAY [1..3] OF CHAR = (#27,'*','t');
  46.     dpi_suffix      : CHAR = 'R';
  47.     landscape       : ARRAY [1..5] OF CHAR = (#27,'&','l','1','O');
  48.     logical_mode    : ARRAY [1..5] OF CHAR = (#27,'*','r','0','F');
  49.     raster_prefix   : ARRAY [1..5] OF CHAR = (#27,'*','r','1','A');
  50.     raster_suffix   : ARRAY [1..4] OF CHAR = (#27,'*','r','B');
  51.     row_prefix      : ARRAY [1..3] OF CHAR = (#27,'*','b');
  52.     row_suffix      : CHAR = 'W';
  53.  
  54.   TYPE
  55.     PointType = RECORD
  56.                   x         : INTEGER;
  57.                   y         : INTEGER
  58.                 END;
  59.     prime_record = RECORD
  60.                      x         : REAL;
  61.                      y         : REAL;
  62.                      z         : REAL;
  63.                      lesser_x  : LONGINT;
  64.                      greater_x : LONGINT
  65.                 END;
  66.     row_type = RECORD
  67.                  column    : ARRAY [0..X_BYTE_MAX] OF BYTE
  68.                END;
  69.     row_ptr_type = ^row_type;
  70.  
  71.   VAR
  72.     ascii_equivalent           : STRING[5];
  73.     column_num                 : INTEGER;
  74.     cursor_x                   : INTEGER;
  75.     cursor_y                   : INTEGER;
  76.     delta_index_1              : INTEGER;
  77.     delta_index_1a             : INTEGER;
  78.     delta_index_1b             : INTEGER;
  79.     delta_index_1c             : INTEGER;
  80.     delta_index_1d             : INTEGER;
  81.     delta_index_2              : INTEGER;
  82.     delta_x                    : ARRAY [1..4,1..24] OF INTEGER;
  83.     delta_y                    : ARRAY [1..4,1..24] OF INTEGER;
  84.     digit                      : INTEGER;
  85.     digit_num                  : INTEGER;
  86.     ending_column_num          : INTEGER;
  87.     max_y_out                  : INTEGER;
  88.     max_z_out                  : INTEGER;
  89.     maze                       : FILE;
  90.     non_null_found             : BOOLEAN;
  91.     num_bytes                  : INTEGER;
  92.     num_x_divisions            : INTEGER;
  93.     num_y_divisions            : INTEGER;
  94.     page                       : ARRAY [0..MAX_Y,0..MAX_X] OF CHAR;
  95.     prime                      : FILE;
  96.     prime_head                 : LONGINT;
  97.     prime_tail                 : LONGINT;
  98.     r_n                        : ARRAY [1..8] OF INTEGER;
  99.     r_n_index_1                : INTEGER;
  100.     r_n_index_2                : INTEGER;
  101.     row_ptr                    : ARRAY [1..ROWS_PER_SLICE] OF row_ptr_type;
  102.     rotation                   : REAL;
  103.     row_num                    : INTEGER;
  104.     seed                       : STRING[8];
  105.     slice_y                    : INTEGER;
  106.     slice_y_start              : INTEGER;
  107.     slice_y_stop               : INTEGER;
  108.     starting_column_num        : INTEGER;
  109.     sum                        : INTEGER;
  110.     tem_int                    : INTEGER;
  111.     tilt                       : REAL;
  112.     x                          : INTEGER;
  113.     x_max                      : REAL;
  114.     x_min                      : REAL;
  115.     x_next                     : INTEGER;
  116.     x_out                      : INTEGER;
  117.     x_prime_max                : REAL;
  118.     x_wall_1                   : INTEGER;
  119.     y                          : INTEGER;
  120.     y_max                      : REAL;
  121.     y_min                      : REAL;
  122.     y_next                     : INTEGER;
  123.     y_out                      : INTEGER;
  124.     y_prime_max                : REAL;
  125.     y_prime_min                : REAL;
  126.     y_wall_1                   : INTEGER;
  127.     z_prime_max                : REAL;
  128.     z_prime_min                : REAL;
  129.  
  130.   PROCEDURE add_room;
  131.     VAR
  132.       delta_index_1 : BYTE;
  133.       delta_index_2 : BYTE;
  134.     BEGIN
  135.       page[y,x]:=' ';
  136.       delta_index_1:=1;
  137.       REPEAT
  138.         delta_index_2:=r_n[1];
  139.         r_n_index_1:=1;
  140.         FOR r_n_index_2:=2 TO 8 DO
  141.           BEGIN
  142.             tem_int:=r_n[r_n_index_2];
  143.             r_n[r_n_index_1]:=tem_int;
  144.             delta_index_2:=delta_index_2+tem_int;
  145.             IF delta_index_2 > 29 THEN
  146.               delta_index_2:=delta_index_2-29;
  147.             r_n_index_1:=r_n_index_2
  148.           END;
  149.         r_n[8]:=delta_index_2
  150.       UNTIL
  151.         (delta_index_2 <= 24);
  152.       WHILE (delta_index_1 <= 4) DO
  153.         BEGIN
  154.           x_next:=x+2*delta_x[delta_index_1][delta_index_2];
  155.           IF ((x_next <= 0) OR (x_next >= MAX_X)) THEN
  156.             delta_index_1:=delta_index_1+1
  157.           ELSE
  158.             BEGIN
  159.               y_next:=y+2*delta_y[delta_index_1][delta_index_2];
  160.               IF ((y_next <= 0) OR (y_next >= MAX_Y)) THEN
  161.                 delta_index_1:=delta_index_1+1
  162.               ELSE
  163.                 IF page[y_next,x_next] = 'W' THEN
  164.                   BEGIN
  165.                     IF x = x_next THEN
  166.                       BEGIN
  167.                         y_wall_1:=(y+y_next) DIV 2;
  168.                         page[y_wall_1,x_next]:=' '
  169.                       END
  170.                     ELSE
  171.                       BEGIN
  172.                         x_wall_1:=(x+x_next) DIV 2;
  173.                         page[y_next,x_wall_1]:=' '
  174.                       END;
  175.                     x:=x_next;
  176.                     y:=y_next;
  177.                     add_room;
  178.                     x:=x-2*delta_x[delta_index_1][delta_index_2];
  179.                     y:=y-2*delta_y[delta_index_1][delta_index_2]
  180.                   END
  181.                 ELSE
  182.                   delta_index_1:=delta_index_1+1
  183.             END
  184.         END
  185.     END;
  186.   FUNCTION f(x,y : REAL) : REAL;
  187.     VAR
  188.       x_out     : INTEGER;
  189.       y_out     : INTEGER;
  190.     BEGIN
  191.       y_out:=TRUNC(x/2.0)-1;
  192.       IF y_out < 0 THEN
  193.         f:=0.0
  194.       ELSE
  195.         IF y_out > MAX_Y THEN
  196.           f:=0.0
  197.         ELSE
  198.           BEGIN
  199.             x_out:=TRUNC(y/2.0)-1;
  200.             IF x_out < 0 THEN
  201.               f:=0.0
  202.             ELSE
  203.               IF x_out > MAX_X THEN
  204.                 f:=0.0
  205.               ELSE
  206.                 IF page[y_out,x_out] = 'W' THEN
  207.                   f:=3.4
  208.                 ELSE
  209.                   f:=0.0
  210.           END
  211.     END;
  212.   PROCEDURE evaluate_and_transform(
  213.    VAR x_min           : REAL;
  214.    VAR x_max           : REAL;
  215.    VAR y_min           : REAL;
  216.    VAR y_max           : REAL;
  217.    VAR num_x_divisions : INTEGER;
  218.    VAR num_y_divisions : INTEGER;
  219.    VAR rotation        : REAL;
  220.    VAR tilt            : REAL;
  221.    VAR x_prime_max     : REAL;
  222.    VAR y_prime_min     : REAL;
  223.    VAR y_prime_max     : REAL;
  224.    VAR z_prime_min     : REAL;
  225.    VAR z_prime_max     : REAL);
  226.     VAR
  227.       cos_rotation       : REAL;
  228.       cos_tilt           : REAL;
  229.       delta_x            : REAL;
  230.       delta_y            : REAL;
  231.       radians            : REAL;
  232.       radians_per_degree : REAL;
  233.       sin_rotation       : REAL;
  234.       sin_tilt           : REAL;
  235.       x                  : REAL;
  236.       x_division_num     : INTEGER;
  237.       x_prime            : REAL;
  238.       x_rotated          : REAL;
  239.       y                  : REAL;
  240.       y_division_num     : INTEGER;
  241.       y_prime            : REAL;
  242.       z                  : REAL;
  243.       z_prime            : REAL;
  244.     BEGIN
  245.       radians_per_degree:=arctan(1.0)/45.0;
  246.       radians:=tilt*radians_per_degree;
  247.       cos_tilt:=COS(radians);
  248.       sin_tilt:=SIN(radians);
  249.       radians:=rotation*radians_per_degree;
  250.       cos_rotation:=COS(radians);
  251.       sin_rotation:=SIN(radians);
  252.       z:=f(x_min,y_min);
  253.       x_rotated:=x_min*cos_rotation+y_min*sin_rotation;
  254.       y_prime_min:=-x_min*sin_rotation+y_min*cos_rotation;
  255.       z_prime_min:=-x_rotated*sin_tilt+z*cos_tilt;
  256.       x_prime_max:=x_rotated*cos_tilt+z*sin_tilt;
  257.       y_prime_max:=y_prime_min;
  258.       z_prime_max:=z_prime_min;
  259.       delta_x:=num_x_divisions;
  260.       delta_x:=(x_max-x_min)/delta_x;
  261.       delta_y:=num_y_divisions;
  262.       delta_y:=(y_max-y_min)/delta_y;
  263.       x:=x_min;
  264.       FOR x_division_num:=1 TO num_x_divisions DO
  265.         BEGIN
  266.           y:=y_min;
  267.           FOR y_division_num:=1 TO num_y_divisions DO
  268.             BEGIN
  269.               z:=f(x,y);
  270.               x_rotated:=x*cos_rotation+y*sin_rotation;
  271.               y_prime:=-x*sin_rotation+y*cos_rotation;
  272.               x_prime:=x_rotated*cos_tilt+z*sin_tilt;
  273.               z_prime:=-x_rotated*sin_tilt+z*cos_tilt;
  274.               IF x_prime > x_prime_max THEN
  275.                 x_prime_max:=x_prime;
  276.               IF y_prime < y_prime_min THEN
  277.                 y_prime_min:=y_prime;
  278.               IF y_prime > y_prime_max THEN
  279.                 y_prime_max:=y_prime;
  280.               IF z_prime < z_prime_min THEN
  281.                 z_prime_min:=z_prime;
  282.               IF z_prime > z_prime_max THEN
  283.                 z_prime_max:=z_prime;
  284.               y:=y+delta_y
  285.             END;
  286.           x:=x+delta_x
  287.         END
  288.     END;
  289.   PROCEDURE adjust_perspective(
  290.    VAR x_min           : REAL;
  291.    VAR x_max           : REAL;
  292.    VAR y_min           : REAL;
  293.    VAR y_max           : REAL;
  294.    VAR num_x_divisions : INTEGER;
  295.    VAR num_y_divisions : INTEGER;
  296.    VAR rotation        : REAL;
  297.    VAR tilt            : REAL;
  298.    VAR prime_head      : LONGINT;
  299.    VAR prime_tail      : LONGINT;
  300.    VAR x_prime_max     : REAL;
  301.    VAR y_prime_min     : REAL;
  302.    VAR y_prime_max     : REAL;
  303.    VAR z_prime_min     : REAL;
  304.    VAR z_prime_max     : REAL);
  305.     VAR
  306.       cos_rotation       : REAL;
  307.       cos_tilt           : REAL;
  308.       delta_x            : REAL;
  309.       delta_y            : REAL;
  310.       delta_z            : REAL;
  311.       finished           : BOOLEAN;
  312.       last_prime_ptr     : LONGINT;
  313.       last_prime_rec     : prime_record;
  314.       prime_ptr          : LONGINT;
  315.       prime_rec          : prime_record;
  316.       radians            : REAL;
  317.       radians_per_degree : REAL;
  318.       sin_rotation       : REAL;
  319.       sin_tilt           : REAL;
  320.       temp_rec           : prime_record;
  321.       x                  : REAL;
  322.       x_division_num     : INTEGER;
  323.       x_eye              : REAL;
  324.       x_increment        : REAL;
  325.       x_prime            : REAL;
  326.       x_rotated          : REAL;
  327.       y                  : REAL;
  328.       y_center           : REAL;
  329.       y_division_num     : INTEGER;
  330.       y_increment        : REAL;
  331.       y_prime            : REAL;
  332.       z                  : REAL;
  333.       z_center           : REAL;
  334.       z_prime            : REAL;
  335.     BEGIN
  336.       IF (y_prime_max-y_prime_min) > (z_prime_max-z_prime_min) THEN
  337.         x_eye:=2.0*(y_prime_max-y_prime_min)+x_prime_max
  338.       ELSE
  339.         x_eye:=2.0*(z_prime_max-z_prime_min)+x_prime_max;
  340.       IF x_eye <> x_prime_max THEN
  341.         BEGIN
  342.           radians_per_degree:=arctan(1.0)/45.0;
  343.           radians:=tilt*radians_per_degree;
  344.           cos_tilt:=COS(radians);
  345.           sin_tilt:=SIN(radians);
  346.           radians:=rotation*radians_per_degree;
  347.           cos_rotation:=COS(radians);
  348.           sin_rotation:=SIN(radians);
  349.           x_increment:=num_x_divisions;
  350.           x_increment:=(x_max-x_min)/x_increment;
  351.           y_increment:=num_y_divisions;
  352.           y_increment:=(y_max-y_min)/y_increment;
  353.           y_center:=(y_prime_max+y_prime_min)/2.0;
  354.           z_center:=(z_prime_max+z_prime_min)/2.0;
  355.           last_prime_ptr:=-1;
  356.           prime_head:=-1;
  357.           prime_tail:=-1;
  358.           prime_ptr:=-1;
  359.           x:=x_min;
  360.           FOR x_division_num:=1 TO num_x_divisions DO
  361.             BEGIN
  362.               y:=y_min;
  363.               FOR y_division_num:=1 TO num_y_divisions DO
  364.                 BEGIN
  365.                   prime_ptr:=prime_ptr+1;
  366.                   z:=f(x,y);
  367.                   x_rotated:=x*cos_rotation+y*sin_rotation;
  368.                   y_prime:=-x*sin_rotation+y*cos_rotation;
  369.                   x_prime:=x_rotated*cos_tilt+z*sin_tilt;
  370.                   z_prime:=-x_rotated*sin_tilt+z*cos_tilt;
  371.                   delta_x:=x_prime-x_eye;
  372.                   delta_y:=y_prime-y_center;
  373.                   delta_z:=z_prime-z_center;
  374.                   prime_rec.x
  375.                    :=SQRT(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z);
  376.                   prime_rec.y:=y_center
  377.                    +(y_prime-y_center)*(x_eye-x_prime_max)/(x_eye-x_prime);
  378.                   prime_rec.z:=z_center
  379.                    +(z_prime-z_center)*(x_eye-x_prime_max)/(x_eye-x_prime);
  380.                   IF last_prime_ptr = -1 THEN
  381.                     BEGIN
  382.                       prime_head:=prime_ptr;
  383.                       prime_tail:=prime_ptr;
  384.                       prime_rec.lesser_x:=-1;
  385.                       prime_rec.greater_x:=-1
  386.                     END
  387.                   ELSE
  388.                     IF prime_rec.x < last_prime_rec.x THEN
  389.                       BEGIN
  390.                         finished:=FALSE;
  391.                         WHILE (NOT finished) DO
  392.                           BEGIN
  393.                             last_prime_ptr:=last_prime_rec.lesser_x;
  394.                             IF last_prime_ptr = -1 THEN
  395.                               finished:=TRUE
  396.                             ELSE
  397.                               BEGIN
  398.                                 Seek(prime,last_prime_ptr);
  399.                                 BlockRead(prime,last_prime_rec,1);
  400.                                 IF prime_rec.x >= last_prime_rec.x THEN
  401.                                   finished:=TRUE
  402.                               END
  403.                           END;
  404.                         prime_rec.lesser_x:=last_prime_ptr;
  405.                         IF last_prime_ptr = -1 THEN
  406.                           BEGIN
  407.                             Seek(prime,prime_head);
  408.                             BlockRead(prime,temp_rec,1);
  409.                             temp_rec.lesser_x:=prime_ptr;
  410.                             Seek(prime,prime_head);
  411.                             BlockWrite(prime,temp_rec,1);
  412.                             prime_rec.greater_x:=prime_head;
  413.                             prime_head:=prime_ptr
  414.                           END
  415.                         ELSE
  416.                           BEGIN
  417.                             prime_rec.greater_x:=last_prime_rec.greater_x;
  418.                             Seek(prime,last_prime_rec.greater_x);
  419.                             BlockRead(prime,temp_rec,1);
  420.                             temp_rec.lesser_x:=prime_ptr;
  421.                             Seek(prime,last_prime_rec.greater_x);
  422.                             BlockWrite(prime,temp_rec,1);
  423.                             last_prime_rec.greater_x:=prime_ptr;
  424.                             Seek(prime,last_prime_ptr);
  425.                             BlockWrite(prime,last_prime_rec,1)
  426.                           END
  427.                       END
  428.                     ELSE
  429.                       BEGIN
  430.                         finished:=FALSE;
  431.                         WHILE (NOT finished) DO
  432.                           BEGIN
  433.                             last_prime_ptr:=last_prime_rec.greater_x;
  434.                             IF last_prime_ptr = -1 THEN
  435.                               finished:=TRUE
  436.                             ELSE
  437.                               BEGIN
  438.                                 Seek(prime,last_prime_ptr);
  439.                                 BlockRead(prime,last_prime_rec,1);
  440.                                 IF prime_rec.x <= last_prime_rec.x THEN
  441.                                   finished:=TRUE
  442.                               END
  443.                           END;
  444.                         prime_rec.greater_x:=last_prime_ptr;
  445.                         IF last_prime_ptr = -1 THEN
  446.                           BEGIN
  447.                             Seek(prime,prime_tail);
  448.                             BlockRead(prime,temp_rec,1);
  449.                             temp_rec.greater_x:=prime_ptr;
  450.                             Seek(prime,prime_tail);
  451.                             BlockWrite(prime,temp_rec,1);
  452.                             prime_rec.lesser_x:=prime_tail;
  453.                             prime_tail:=prime_ptr
  454.                           END
  455.                         ELSE
  456.                           BEGIN
  457.                             prime_rec.lesser_x:=last_prime_rec.lesser_x;
  458.                             Seek(prime,last_prime_rec.lesser_x);
  459.                             BlockRead(prime,temp_rec,1);
  460.                             temp_rec.greater_x:=prime_ptr;
  461.                             Seek(prime,last_prime_rec.lesser_x);
  462.                             BlockWrite(prime,temp_rec,1);
  463.                             last_prime_rec.lesser_x:=prime_ptr;
  464.                             Seek(prime,last_prime_ptr);
  465.                             BlockWrite(prime,last_prime_rec,1)
  466.                           END
  467.                       END;
  468.                   Seek(prime,prime_ptr);
  469.                   BlockWrite(prime,prime_rec,1);
  470.                   y:=y+y_increment;
  471.                   last_prime_ptr:=prime_ptr;
  472.                   last_prime_rec.x:=prime_rec.x;
  473.                   last_prime_rec.y:=prime_rec.y;
  474.                   last_prime_rec.z:=prime_rec.z;
  475.                   last_prime_rec.lesser_x:=prime_rec.lesser_x;
  476.                   last_prime_rec.greater_x:=prime_rec.greater_x
  477.                 END;
  478.               x:=x+x_increment
  479.             END
  480.         END
  481.     END;
  482.   PROCEDURE pset(
  483.    VAR x                             : INTEGER;
  484.    VAR y                             : INTEGER;
  485.        edge                          : BOOLEAN);
  486.     CONST
  487.       black : ARRAY [0..7] OF BYTE
  488.        = (128,64,32,16,8,4,2,1);
  489.       white : ARRAY [0..7] OF BYTE
  490.        = (127,191,223,239,247,251,253,254);
  491.     VAR
  492.       bit_num                        : INTEGER;
  493.       byte_num                       : INTEGER;
  494.       slice_y                        : INTEGER;
  495.     BEGIN
  496.       IF y >= slice_y_start THEN
  497.         BEGIN
  498.           IF y <= slice_y_stop THEN
  499.             BEGIN
  500.               slice_y:=y-slice_y_start+1;
  501.               byte_num:=x DIV 8;
  502.               bit_num:=x-8*byte_num;
  503.               IF edge THEN
  504.                 row_ptr[slice_y]^.column[byte_num]
  505.                  :=row_ptr[slice_y]^.column[byte_num] OR black[bit_num]
  506.               ELSE
  507.                 row_ptr[slice_y]^.column[byte_num]
  508.                  :=row_ptr[slice_y]^.column[byte_num] AND white[bit_num]
  509.             END
  510.         END
  511.     END;
  512.   PROCEDURE draw_line(
  513.    VAR x1                            : INTEGER;
  514.    VAR y1                            : INTEGER;
  515.    VAR x2                            : INTEGER;
  516.    VAR y2                            : INTEGER);
  517.     VAR
  518.       error                          : INTEGER;
  519.       error_prime_x                  : INTEGER;
  520.       error_prime_y                  : INTEGER;
  521.       permissible_delta_x            : INTEGER;
  522.       permissible_delta_y            : INTEGER;
  523.       x                              : INTEGER;
  524.       x_diff                         : INTEGER;
  525.       y                              : INTEGER;
  526.       y_diff                         : INTEGER;
  527.     BEGIN
  528.       IF x2 >= x1 THEN
  529.         permissible_delta_x:=1
  530.       ELSE
  531.         permissible_delta_x:=-1;
  532.       IF y2 >= y1 THEN
  533.         permissible_delta_y:=1
  534.       ELSE
  535.         permissible_delta_y:=-1;
  536.       x:=x1;
  537.       y:=y1;
  538.       x_diff:=x2-x1;
  539.       y_diff:=y2-y1;
  540.       error:=0;
  541.       pset(x,y,TRUE);
  542.       WHILE ((x <> x2) OR (y <> y2)) DO
  543.         BEGIN
  544.           error_prime_x:=error+permissible_delta_x*y_diff;
  545.           error_prime_y:=error-permissible_delta_y*x_diff;
  546.           IF ABS(error_prime_x) <= ABS(error_prime_y) THEN
  547.             BEGIN
  548.               x:=x+permissible_delta_x;
  549.               error:=error_prime_x
  550.             END
  551.           ELSE
  552.             BEGIN
  553.               y:=y+permissible_delta_y;
  554.               error:=error_prime_y
  555.             END;
  556.           pset(x,y,TRUE)
  557.         END
  558.     END;
  559.   PROCEDURE plot(
  560.    VAR prime_tail      : LONGINT;
  561.    VAR y_prime_min     : REAL;
  562.    VAR y_prime_max     : REAL;
  563.    VAR z_prime_min     : REAL;
  564.    VAR z_prime_max     : REAL;
  565.    VAR max_y_out       : INTEGER;
  566.    VAR max_z_out       : INTEGER;
  567.    VAR num_x_divisions : INTEGER;
  568.    VAR num_y_divisions : INTEGER);
  569.     VAR
  570.       box                   : ARRAY [1..4] OF PointType;
  571.       box_delta_x           : LONGINT;
  572.       box_delta_y           : LONGINT;
  573.       box_num_1             : INTEGER;
  574.       box_num_2             : INTEGER;
  575.       box_x_intercept       : LONGINT;
  576.       box_x1                : INTEGER;
  577.       box_x2                : INTEGER;
  578.       box_y_max             : INTEGER;
  579.       box_y_min             : INTEGER;
  580.       box_y_offset          : LONGINT;
  581.       box_y1                : INTEGER;
  582.       down_ptr              : LONGINT;
  583.       intercept_count_mod_2 : INTEGER;
  584.       heap_size             : LONGINT;
  585.       line_x1               : INTEGER;
  586.       line_x2               : INTEGER;
  587.       line_y1               : INTEGER;
  588.       line_y2               : INTEGER;
  589.       pixels_per_unit       : REAL;
  590.       prime_ptr             : LONGINT;
  591.       prime_rec             : prime_record;
  592.       right_ptr             : LONGINT;
  593.       temp_rec              : prime_record;
  594.       y_offset              : REAL;
  595.       y_out_max             : REAL;
  596.       z_offset              : REAL;
  597.       z_out_max             : REAL;
  598.     BEGIN
  599.       y_out_max:=max_y_out;
  600.       z_out_max:=max_z_out;
  601.       IF z_out_max*(y_prime_max-y_prime_min)
  602.        > y_out_max*(z_prime_max-z_prime_min) THEN
  603.         BEGIN
  604.           pixels_per_unit
  605.            :=y_out_max/(y_prime_max-y_prime_min);
  606.           y_offset:=0.0;
  607.           z_offset
  608.            :=-(z_out_max-pixels_per_unit*(z_prime_max-z_prime_min))/2.0
  609.         END
  610.       ELSE
  611.         IF z_out_max*(y_prime_max-y_prime_min)
  612.          < y_out_max*(z_prime_max-z_prime_min) THEN
  613.           BEGIN
  614.             pixels_per_unit:=z_out_max/(z_prime_max-z_prime_min);
  615.             y_offset:=(y_out_max
  616.              -pixels_per_unit*(y_prime_max-y_prime_min))
  617.              /2.0;
  618.             z_offset:=0.0
  619.           END
  620.         ELSE  { plot degenerates to a single point }
  621.           BEGIN
  622.             pixels_per_unit:=1.0;
  623.             y_offset:=y_out_max/2.0;
  624.             z_offset:=-z_out_max/2.0
  625.           END;
  626.       prime_ptr:=prime_tail;
  627.       heap_size:=num_x_divisions;
  628.       heap_size:=heap_size*num_y_divisions;
  629.       WHILE (prime_ptr <> -1) DO
  630.         BEGIN
  631.           Seek(prime,prime_ptr);
  632.           BlockRead(prime,prime_rec,1);
  633.           right_ptr:=prime_ptr+1;
  634.           IF ((right_ptr MOD num_y_divisions) <> 0) THEN
  635.             BEGIN
  636.               down_ptr:=prime_ptr+num_y_divisions;
  637.               IF (down_ptr < heap_size) THEN
  638.                 BEGIN
  639.                   box[1].x:=TRUNC(y_offset+pixels_per_unit
  640.                    *(prime_rec.y-y_prime_min));
  641.                   box[1].y:=TRUNC(z_offset+z_out_max
  642.                    -pixels_per_unit*(prime_rec.z-z_prime_min));
  643.                   Seek(prime,right_ptr);
  644.                   BlockRead(prime,temp_rec,1);
  645.                   box[2].x:=TRUNC(y_offset+pixels_per_unit
  646.                    *(temp_rec.y-y_prime_min));
  647.                   box[2].y:=TRUNC(z_offset+z_out_max
  648.                    -pixels_per_unit*(temp_rec.z-z_prime_min));
  649.                   Seek(prime,down_ptr);
  650.                   BlockRead(prime,temp_rec,1);
  651.                   box[4].x:=TRUNC(y_offset+pixels_per_unit
  652.                    *(temp_rec.y-y_prime_min));
  653.                   box[4].y:=TRUNC(z_offset+z_out_max
  654.                    -pixels_per_unit*(temp_rec.z-z_prime_min));
  655.                   Seek(prime,down_ptr+1);
  656.                   BlockRead(prime,temp_rec,1);
  657.                   box[3].x:=TRUNC(y_offset+pixels_per_unit
  658.                    *(temp_rec.y-y_prime_min));
  659.                   box[3].y:=TRUNC(z_offset+z_out_max
  660.                    -pixels_per_unit*(temp_rec.z-z_prime_min));
  661.                   box_y_min:=box[1].y;
  662.                   box_y_max:=box_y_min;
  663.                   FOR box_num_1:=2 TO 4 DO
  664.                     BEGIN
  665.                       IF box[box_num_1].y < box_y_min THEN
  666.                         box_y_min:=box[box_num_1].y;
  667.                       IF box[box_num_1].y > box_y_max THEN
  668.                         box_y_max:=box[box_num_1].y
  669.                     END;
  670.                   FOR box_y1:=box_y_min TO box_y_max DO
  671.                     BEGIN
  672.                       intercept_count_mod_2:=0;
  673.                       box_num_2:=2;
  674.                       FOR box_num_1:=1 TO 4 DO
  675.                         BEGIN
  676.                           IF box[box_num_1].y >= box_y1 THEN
  677.                             BEGIN
  678.                               IF box_y1 > box[box_num_2].y THEN
  679.                                 BEGIN
  680.                                   box_delta_y
  681.                                    :=box[box_num_2].y-box[box_num_1].y;
  682.                                   box_delta_x
  683.                                    :=box[box_num_2].x-box[box_num_1].x;
  684.                                   box_y_offset:=box_y1-box[box_num_1].y;
  685.                                   box_x_intercept:=box[box_num_1].x;
  686.                                   box_x1:=(box_delta_x*box_y_offset)
  687.                                    DIV box_delta_y+box_x_intercept;
  688.                                   IF intercept_count_mod_2 = 0 THEN
  689.                                     box_x2:=box_x1
  690.                                   ELSE
  691.                                     BEGIN
  692.                                       IF box_x1 < box_x2 THEN
  693.                                         BEGIN
  694.                                           line_x1:=box_x1;
  695.                                           line_x2:=box_x2
  696.                                         END
  697.                                       ELSE
  698.                                         BEGIN
  699.                                           line_x1:=box_x2;
  700.                                           line_x2:=box_x1
  701.                                         END;
  702.                                       pset(line_x1,box_y1,FALSE);
  703.                                       WHILE (line_x1 < line_x2) DO
  704.                                         BEGIN
  705.                                           line_x1:=line_x1+1;
  706.                                           pset(line_x1,box_y1,FALSE)
  707.                                         END
  708.                                     END;
  709.                                   intercept_count_mod_2
  710.                                    :=1-intercept_count_mod_2
  711.                                 END
  712.                             END
  713.                           ELSE
  714.                             BEGIN
  715.                               IF box_y1 <= box[box_num_2].y THEN
  716.                                 BEGIN
  717.                                   box_delta_y
  718.                                    :=box[box_num_2].y-box[box_num_1].y;
  719.                                   box_delta_x
  720.                                    :=box[box_num_2].x-box[box_num_1].x;
  721.                                   box_y_offset:=box_y1-box[box_num_1].y;
  722.                                   box_x_intercept:=box[box_num_1].x;
  723.                                   box_x1:=(box_delta_x*box_y_offset)
  724.                                    DIV box_delta_y+box_x_intercept;
  725.                                   IF intercept_count_mod_2 = 0 THEN
  726.                                     box_x2:=box_x1
  727.                                   ELSE
  728.                                     BEGIN
  729.                                       IF box_x1 < box_x2 THEN
  730.                                         BEGIN
  731.                                           line_x1:=box_x1;
  732.                                           line_x2:=box_x2
  733.                                         END
  734.                                       ELSE
  735.                                         BEGIN
  736.                                           line_x1:=box_x2;
  737.                                           line_x2:=box_x1
  738.                                         END;
  739.                                       pset(line_x1,box_y1,FALSE);
  740.                                       WHILE (line_x1 < line_x2) DO
  741.                                         BEGIN
  742.                                           line_x1:=line_x1+1;
  743.                                           pset(line_x1,box_y1,FALSE)
  744.                                         END
  745.                                     END;
  746.                                   intercept_count_mod_2
  747.                                    :=1-intercept_count_mod_2
  748.                                 END
  749.                             END;
  750.                           box_num_2:=box_num_2+1;
  751.                           IF box_num_2 > 4 THEN
  752.                             box_num_2:=1
  753.                         END
  754.                     END;
  755.                   box_num_2:=2;
  756.                   FOR box_num_1:=1 TO 4 DO
  757.                     BEGIN
  758.                       line_x1:=box[box_num_1].x;
  759.                       line_y1:=box[box_num_1].y;
  760.                       line_x2:=box[box_num_2].x;
  761.                       line_y2:=box[box_num_2].y;
  762.                       box_num_2:=box_num_2+1;
  763.                       draw_line(line_x1,line_y1,line_x2,line_y2);
  764.                       IF box_num_2 > 4 THEN
  765.                         box_num_2:=1
  766.                     END
  767.                 END
  768.             END;
  769.           prime_ptr:=prime_rec.lesser_x
  770.         END
  771.     END;
  772.   BEGIN
  773.     ClrScr;
  774.     WRITELN(OUTPUT,'                                 Maze Generator');
  775.     WRITELN(OUTPUT,' '); WRITELN(OUTPUT,' '); WRITELN(OUTPUT,' ');
  776.     WRITELN(OUTPUT,'     The maze will be outputted to HPMAZE.LST.');
  777.     WRITELN(OUTPUT,' ');
  778.     WRITE(OUTPUT,'     Random number seed?  ');
  779.     READLN(INPUT,seed);
  780.     r_n_index_1:=1;
  781.     FOR r_n_index_2:=1 TO LENGTH(seed) DO
  782.       BEGIN
  783.         tem_int:=ORD(seed[r_n_index_2]);
  784.         WHILE (tem_int > 29) DO tem_int:=tem_int-29;
  785.         r_n[r_n_index_1]:=tem_int;
  786.         r_n_index_1:=r_n_index_1+1
  787.       END;
  788.     r_n_index_2:=8;
  789.     WHILE (r_n_index_1 > 1) DO
  790.       BEGIN
  791.         r_n_index_1:=r_n_index_1-1;
  792.         r_n[r_n_index_2]:=r_n[r_n_index_1];
  793.         r_n_index_2:=r_n_index_2-1
  794.       END;
  795.     WHILE (r_n_index_2 >= 1) DO
  796.       BEGIN
  797.         r_n[r_n_index_2]:=19;
  798.         r_n_index_2:=r_n_index_2-1
  799.       END;
  800.     delta_x[1,1]:=-1;
  801.     delta_y[1,1]:=0;
  802.     delta_x[2,1]:=0;
  803.     delta_y[2,1]:=1;
  804.     delta_x[3,1]:=1;
  805.     delta_y[3,1]:=0;
  806.     delta_x[4,1]:=0;
  807.     delta_y[4,1]:=-1;
  808.     delta_index_2:=0;
  809.     FOR delta_index_1a:=1 TO 4 DO
  810.       FOR delta_index_1b:=1 TO 4 DO
  811.         IF delta_index_1a <> delta_index_1b THEN
  812.           FOR delta_index_1c:=1 TO 4 DO
  813.             IF ((delta_index_1a <> delta_index_1c)
  814.             AND (delta_index_1b <> delta_index_1c)) THEN
  815.               FOR delta_index_1d:=1 TO 4 DO
  816.                 IF ((delta_index_1a <> delta_index_1d)
  817.                 AND (delta_index_1b <> delta_index_1d)
  818.                 AND (delta_index_1c <> delta_index_1d)) THEN
  819.                   BEGIN
  820.                     delta_index_2:=delta_index_2+1;
  821.                     delta_x[delta_index_1a,delta_index_2]:=delta_x[1,1];
  822.                     delta_y[delta_index_1a,delta_index_2]:=delta_y[1,1];
  823.                     delta_x[delta_index_1b,delta_index_2]:=delta_x[2,1];
  824.                     delta_y[delta_index_1b,delta_index_2]:=delta_y[2,1];
  825.                     delta_x[delta_index_1c,delta_index_2]:=delta_x[3,1];
  826.                     delta_y[delta_index_1c,delta_index_2]:=delta_y[3,1];
  827.                     delta_x[delta_index_1d,delta_index_2]:=delta_x[4,1];
  828.                     delta_y[delta_index_1d,delta_index_2]:=delta_y[4,1]
  829.                   END;
  830.     max_y_out:=X_DOT_MAX;
  831.     max_z_out:=Y_DOT_MAX;
  832.     FOR y_out:=0 TO MAX_Y DO
  833.       FOR x_out:=0 TO MAX_X DO
  834.         page[y_out,x_out]:='W';
  835.     sum:=0;
  836.     FOR digit_num:=1 TO 3 DO
  837.       BEGIN
  838.         digit:=r_n[1];
  839.         r_n_index_1:=1;
  840.         FOR r_n_index_2:=2 TO 8 DO
  841.           BEGIN
  842.             tem_int:=r_n[r_n_index_2];
  843.             r_n[r_n_index_1]:=tem_int;
  844.             digit:=digit+tem_int;
  845.             IF digit > 29 THEN
  846.               digit:=digit-29;
  847.             r_n_index_1:=r_n_index_2
  848.           END;
  849.         r_n[8]:=digit;
  850.         sum:=29*sum+digit
  851.       END;
  852.     x:=2*(sum MOD NUM_COLUMNS)+1;
  853.     sum:=0;
  854.     FOR digit_num:=1 TO 3 DO
  855.       BEGIN
  856.         digit:=r_n[1];
  857.         r_n_index_1:=1;
  858.         FOR r_n_index_2:=2 TO 8 DO
  859.           BEGIN
  860.             tem_int:=r_n[r_n_index_2];
  861.             r_n[r_n_index_1]:=tem_int;
  862.             digit:=digit+tem_int;
  863.             IF digit > 29 THEN
  864.               digit:=digit-29;
  865.             r_n_index_1:=r_n_index_2
  866.           END;
  867.         r_n[8]:=digit;
  868.         sum:=29*sum+digit
  869.       END;
  870.     y:=2*(sum MOD NUM_ROWS)+1;
  871.     add_room;
  872.     page[0,1]:=' ';
  873.     page[MAX_Y,MAX_X-1]:=' ';
  874.     x_min:=1.0;
  875.     x_max:=MAX_Y;
  876.     x_max:=2.0*x_max+5.0;
  877.     y_min:=1.0;
  878.     y_max:=MAX_X;
  879.     y_max:=2.0*y_max+5.0;
  880.     num_x_divisions:=2*(MAX_Y+3);
  881.     num_y_divisions:=2*(MAX_X+3);
  882.     prime_head:=-1;
  883.     rotation:=20.0;
  884.     tilt:=30.0;
  885.     evaluate_and_transform(x_min,x_max,y_min,y_max,num_x_divisions,
  886.      num_y_divisions,rotation,tilt,x_prime_max,y_prime_min,y_prime_max,
  887.      z_prime_min,z_prime_max);
  888.     Assign(prime,'HPMAZE.TMP');
  889.     Rewrite(prime,Sizeof(prime_record));
  890.     adjust_perspective(x_min,x_max,y_min,y_max,num_x_divisions,num_y_divisions,
  891.      rotation,tilt,prime_head,prime_tail,x_prime_max,y_prime_min,y_prime_max,
  892.      z_prime_min,z_prime_max);
  893.     FOR row_num:=1 TO ROWS_PER_SLICE DO
  894.       New(row_ptr[row_num]);
  895.     Assign(maze,'HPMAZE.LST');
  896.     Rewrite(maze,1);
  897.     BlockWrite(maze,landscape,SizeOf(landscape));
  898.     BlockWrite(maze,dpi_prefix,SizeOf(dpi_prefix));
  899.     Str(DOTS_PER_INCH,ascii_equivalent);
  900.     BlockWrite(maze,ascii_equivalent[1],Length(ascii_equivalent));
  901.     BlockWrite(maze,dpi_suffix,SizeOf(dpi_suffix));
  902.     BlockWrite(maze,logical_mode,SizeOf(logical_mode));
  903.     slice_y_start:=0;
  904.     WHILE (slice_y_start <= Y_DOT_MAX) DO
  905.       BEGIN
  906.         slice_y_stop:=slice_y_start+ROWS_PER_SLICE-1;
  907.         IF slice_y_stop > Y_DOT_MAX THEN
  908.           slice_y_stop:=Y_DOT_MAX;
  909.         FOR row_num:=1 TO ROWS_PER_SLICE DO
  910.           FOR column_num:=0 to X_BYTE_MAX DO
  911.             row_ptr[row_num]^.column[column_num]:=0;
  912.         plot(prime_tail,y_prime_min,y_prime_max,z_prime_min,z_prime_max,
  913.          max_y_out,max_z_out,num_x_divisions,num_y_divisions);
  914.         row_num:=1;
  915.         FOR slice_y:=slice_y_start TO slice_y_stop DO
  916.           BEGIN
  917.             starting_column_num:=0;
  918.             non_null_found:=FALSE;
  919.             WHILE ((starting_column_num <= X_BYTE_MAX) AND (NOT non_null_found)) DO
  920.               IF row_ptr[row_num]^.column[starting_column_num] = 0 THEN
  921.                 starting_column_num:=starting_column_num+1
  922.               ELSE
  923.                 non_null_found:=TRUE;
  924.             IF non_null_found THEN
  925.               BEGIN
  926.                 non_null_found:=FALSE;
  927.                 ending_column_num:=X_BYTE_MAX;
  928.                 WHILE ((ending_column_num >= 0) AND (NOT non_null_found)) DO
  929.                   IF row_ptr[row_num]^.column[ending_column_num] = 0 THEN
  930.                     ending_column_num:=ending_column_num-1
  931.                   ELSE
  932.                     non_null_found:=TRUE;
  933.                 BlockWrite(maze,cursor_x_prefix,SizeOf(cursor_x_prefix));
  934.                 cursor_x:=8*DOTS_PER_STROKE*starting_column_num;
  935.                 Str(cursor_x,ascii_equivalent);
  936.                 BlockWrite(maze,ascii_equivalent[1],Length(ascii_equivalent));
  937.                 BlockWrite(maze,cursor_x_suffix,SizeOf(cursor_x_suffix));
  938.                 BlockWrite(maze,cursor_y_prefix,SizeOf(cursor_y_prefix));
  939.                 cursor_y:=DOTS_PER_STROKE*slice_y;
  940.                 Str(cursor_y,ascii_equivalent);
  941.                 BlockWrite(maze,ascii_equivalent[1],Length(ascii_equivalent));
  942.                 BlockWrite(maze,cursor_y_suffix,SizeOf(cursor_y_suffix));
  943.                 BlockWrite(maze,raster_prefix,SizeOf(raster_prefix));
  944.                 BlockWrite(maze,row_prefix,SizeOf(row_prefix));
  945.                 num_bytes:=ending_column_num-starting_column_num+1;
  946.                 Str(num_bytes,ascii_equivalent);
  947.                 BlockWrite(maze,ascii_equivalent[1],Length(ascii_equivalent));
  948.                 BlockWrite(maze,row_suffix,SizeOf(row_suffix));
  949.                 BlockWrite(maze,row_ptr[row_num]^.column[starting_column_num],
  950.                  num_bytes);
  951.                 BlockWrite(maze,raster_suffix,SizeOf(raster_suffix))
  952.               END;
  953.             row_num:=row_num+1
  954.           END;
  955.         slice_y_start:=slice_y_start+ROWS_PER_SLICE
  956.       END;
  957.     Close(maze);
  958.     Close(prime);
  959.     Erase(prime);
  960.     FOR row_num:=1 TO ROWS_PER_SLICE DO
  961.       Dispose(row_ptr[row_num])
  962.   END.
  963.