program WallPaper; (* IMPORTANT - This program uses absolute variables between 2100 and 216F hex so that it may be saved with these variables already initialized. Therefore, 1) do not attempt to run this program from memory using Turbo Pascal, and 2) make sure you compile this program with a starting address of at least 2200 hex. Version 3 Notes: ------- - ----- Carson Wilson, Nov. 19, 1986. Oops! I used a string length of 16 to read in the values for PrinterName, InitPrinter, and ClearPrinter, which were absolute variables 16 bytes long. What I forgot was that string variables have an EXTRA byte (byte 0) used to hold their length. This file corrects that error by making PrinterName, InitPrinter, and ClearPrinter, each 32 bytes long (string[31]), and allowing up to 31 characters to be input for each of these variables. Version 2 Notes: ------- - ----- Updated and enhanced by Carson Wilson, November 18, 1986. Main program loop uses "frac(c / 2)" and c is now a real number to avoid integer overflow. Okidata Microline 182 printer capability added. Permanent printer installation is now possible. Terminal specific routines like ClrScr and GoToXY changed or eliminated so that terminal installation is unnecessary for those without Turbo Pascal. Now uses Turbo built-in procedure Sqr() to get squares in main program. The variable TOP is implemented for printer which do not start printing at the top of the page. Version 1 notes: ------- - ----- Turbo Pascal, written by Glenn Brooke 10/25/86 from a description by A.K. Dewdney in Scientific American September 1986. This is a public domain program, and may not be sold or utilized for profit. Support public domain! Relatively simple mathematical transformations of integer space can generate wonderfully complex patterns. This program simplifies the calculation and printing of these patterns, described as "Wallpaper for the Mind." I have found that setting the pitch at 40 and 35 lines/inch gives an excellent, dense picture on the Toshiba printers. I have not at this time experimented with other printers. I hope you enjoy this program as much as my colleagues and I. By the way, we have discovered how much children love to make these patterns. This is a fine way to spark mathematical interest in children of all ages! Glenn Brooke Lillipute Z-node (312) 649-1730 by modem 1025 Garnett Place Evanston, IL 60201 *) const FormFeed = 12; {ascii to send to printer for FormFeed} version = 3; update = '19 Nov 1986'; type ListStr = string[31]; { 31 + 1 byte for length } var corna, cornb, side : real; c, x, y, z : real; i, j : integer; response : char; done : boolean; { absolute variables for permanent program installation: } PrinterName : ListStr absolute $2100; { 31 + 1 byte for length } dimension : integer absolute $2120; Okidata : boolean absolute $2122; Toshiba : boolean absolute $2123; TOP : boolean absolute $2124; { top of page } InitPrinter : ListStr absolute $2130; ClearPrinter : ListStr absolute $2150; procedure ClrScr; { use linefeeds so that no terminal installation needed - C.W. } var line : byte; begin for line := 1 to 25 do writeln; end; procedure Set_Toshiba_Parameters; const pitch = 40; {*P} lines_per_inch = 35; {*P} type numst = string[2]; function Convert(x : integer) : numst; {converts 2 digit integer to equivalent 2 char string 13 -> '13' 7 -> '07'} var first, second : string[1]; begin str(x div 10, first); { get 1st digit } str(x mod 10, second); { get 2nd digit } convert := first + second end; { function Convert } begin { procedure Set_Toshiba_Parameters } write(lst, chr(27), 'L',convert(round(48/lines_per_inch))); write(lst, chr(27), 'E', convert(round(120/pitch))); end; { procedure Set_Toshiba_parameters } procedure SetPrinter(SendString: ListStr); begin write(lst,SendString); end; procedure GetCodes(var CodeString : ListStr); { input codes from user } var counter : byte; begin counter := 1; CodeString := ''; repeat read(kbd,Response); if ord(Response) <> 13 then { ^M } begin CodeString[counter] := response; CodeString[0] := chr(counter); if ord(response) < 32 then write('^',char(ord(response) + 64)) else write(response); end; counter := succ(counter); until (ord(response) = 13) or (counter = 16); end; procedure GetParameters; begin Okidata := false; Toshiba := false; TOP := false; writeln; writeln(' A) Okidata Microline 182 or compatible printer'); writeln(' B) Toshiba P1351 or P1350 or compatible printer'); writeln(' C) Install for other printer - see WALLPAP.DOC before'); writeln(' choosing this option.'); writeln(' D) Abort and exit to operating system'); writeln; write (' Select A, B, C, or D: '); repeat read(kbd,response); response := upcase(response); until (response in ['A','B','C','D']); writeln(response); case response of 'A' : begin Okidata := true; dimension := 136; PrinterName := 'Okidata 182'; initprinter := ^[ + '%9' + chr(8) {8/144 = ~17 l.p.i.} + chr(29); { 17.1 c.p.i } clearprinter := chr(24); end; 'B' : begin Toshiba := true; dimension := 180; PrinterName := 'Toshiba P1350/51'; clearprinter := chr(27) + chr(26) + 'I'; end; 'C' : begin { Install for other printer } writeln; repeat write(^M'Enter the name of your printer (31 characters maximum): '); buflen := 31; readln(PrinterName); write(^M'Printer is ',PrinterName,'. OK (Y/N)? '); read(kbd,response); response := upcase(response); until(response = 'Y'); writeln(response); repeat write(^M'Enter printer setup string (31 characters maximum): '); buflen := 31; GetCodes(initprinter); writeln; write('Printer initialization string OK (Y/N)? '); read(kbd,response); response := upcase(response); until(response = 'Y'); writeln(response); repeat write(^M'Enter the maximum number of characters for a line: '); buflen := 3; readln(dimension); write('Maximum characters per line is ',dimension,'. OK (Y/N)? '); read(kbd,response); response := upcase(response); until(response = 'Y'); writeln(response); repeat write(^M'Enter printer reset string (31 characters maximum): '); GetCodes(clearprinter); writeln; write('Printer reset string OK (Y/N)? '); read(kbd,response); response := upcase(response); until(response = 'Y'); writeln(response); write('Does your printer start at line one of the page (Y/N)? '); repeat read(kbd,response); response := upcase(response); until(response in ['Y','N']); writeln(response); if response = 'Y' then TOP := true; end; { of case 'C' } 'D' : begin writeln; write('Program Aborted.'); halt; end; { quit program } end; { of case response } writeln; writeln(' To save these settings permanently, type "SAVE 53 WALLPAP.COM" '); writeln(' at your system''s command line after exiting the program.'); writeln; write('Strike any key to continue: '); repeat until keypressed; end; { of procedure GetParameters } BEGIN {main program body} {initial screen with information about use of program} ClrScr; writeln; writeln; writeln(' Wallpaper for the Mind '); writeln(' Version ',version); writeln(' based upon an article by A.K.Dewdney'); writeln(' Implemented by Glenn Brooke'); writeln(' and Enhanced by Carson Wilson'); writeln(' Last update : ',update); writeln; writeln('The currently installed printer is ',PrinterName,'.'); write ('Do you wish to change it (Y/N)? '); repeat read(kbd,response); response := upcase(response); until(response in ['Y','N']); writeln(response); if response = 'Y' then GetParameters; ClrScr; writeln(' Just enter 3 integer values for corner A, corner B, and the length'); writeln(' of the side, and this program will generate beautiful patterns on your'); writeln(' dot matrix printer. Experimentation is most of the fun, but some good'); writeln(' starting areas are :'); writeln; writeln(' A B side '); writeln('=============================='); writeln(' -15 -20 150'); writeln(' 45 12 15 Tip : stick with one'); writeln(' 45 56 15 A, B coordinate set,'); writeln(' 15 12 10 and vary the side --'); writeln(' -25 -10 15 that''s where the fun is.'); writeln(' 50 36 25'); writeln; done := false; repeat writeln; writeln(' Please enter the desired integer coordinates '); writeln; write(' Corner A : '); readln(corna); write(' Corner B : '); readln(cornb); write(' Length of the side : '); readln(side); writeln; {print out relevant information on the page} write('--> Make sure your printer is on <--'); if TOP or Toshiba then for i := 1 to 5 do writeln(lst); writeln(lst, 'Wallpaper for the Mind'); write(^M,' '^M); writeln(lst, ' Corner A : ',corna:3:0); writeln(lst, ' Corner B : ',cornb:3:0); writeln(lst, ' Length of the side : ',side:3:0); for i := 1 to 5 do writeln(lst); {adjust printer to approprite pitch and lines per inch setting} {note, this is done after the coordinates are printed out} if Toshiba then Set_Toshiba_Parameters else SetPrinter(initprinter); writeln('Press ^S followed by ^C to abort'); writeln; {this is the calculation loop for pattern generation and printout} for i := 1 to dimension do begin write(^M,' Now working on row ',i,' of ',dimension,' '); for j := 1 to dimension do begin x := corna + (side*i/dimension); y := cornb + (side*j/dimension); z := sqr(x) + sqr(y); c := int(z); if frac(c / 2) = 0 then write(lst,'.') else write(lst,' '); end; {for j} writeln(lst); end; {for i} writeln; writeln(lst, chr(FormFeed)); write(' Another run with new coordinates (Y/N)? '); read(kbd,response); if upcase(response) <> 'Y' then done := true; SetPrinter(clearprinter); {put back to normal type situation} until done; ClrScr; writeln(' Hope you enjoy your wallpaper patterns!', chr(7)); END.