114 lines
5.0 KiB
Plaintext
114 lines
5.0 KiB
Plaintext
{$B- Early and safe resolution of If x <> 0 and 1/x...}
|
|
Program LangtonsAnt; Uses CRT;
|
|
{Perpetrated by R.N.McLean (whom God preserve), Victoria University, December MMXV.}
|
|
Var AsItWas: record mode: word; ta: word; end;
|
|
Var LastLine,LastCol: byte;
|
|
|
|
Procedure Swap(var a,b: integer); {Oh for a compiler-recognised statement.}
|
|
var t: integer; {Such as A=:=B;}
|
|
Begin
|
|
t:=a; a:=b; b:=t;
|
|
End;
|
|
|
|
var Stepwise: boolean;
|
|
Var Cell: Array[1..80,1..50] of byte; {The screen is of limited size, alas.}
|
|
Var x,y,Step: integer; {In the absence of complex numbers,}
|
|
Var dx,dy: integer; {And also of array action statements.}
|
|
|
|
Procedure Croak(Gasp: string); {Exit message...}
|
|
Begin
|
|
GoToXY(1,12); TextColor(Yellow); {Reserve line twelve.}
|
|
WriteLn(Gasp,' on step ',Step,' to (',x,',',y,')');
|
|
HALT;
|
|
End;
|
|
|
|
Procedure Harken; {Waits for a keystroke.}
|
|
var ch: char; {The character. Should really be 16-bit.}
|
|
Begin
|
|
ch:=ReadKey; {Fancy keys evoke double characters. I don't care.}
|
|
if (ch = 'S') or (ch = 's') then Stepwise:=not Stepwise {Quick, slow, quick, quick, slow...}
|
|
else if ch = #27 then Croak('ESC!'); {Or perhaps, enough already!}
|
|
End; {Fancy keys will give a twostep.}
|
|
Procedure Waitabit; {Slows the action.}
|
|
Begin
|
|
if Stepwise or KeyPressed then Harken; {Perhaps a change while on the run.}
|
|
End; {of Waitabit.}
|
|
|
|
Procedure Turn(way:integer); {(dx,dy)*(0,w) = (-w*dy,+w*dx)}
|
|
Begin
|
|
Swap(dx,dy); {In the absence of complex arithmetic,}
|
|
dx:=-way*dx; dy:=way*dy; {Do this in two stages.}
|
|
End;
|
|
|
|
const Arrow: array[-1..+1,-1..+1] of integer {Only four entries are of interest.}
|
|
= ((1,27,3),(25,5,24),(7,26,9)); {For the four arrow symbols.}
|
|
Procedure ShowDirection(Enter,How: byte); {Show one.}
|
|
Begin
|
|
GoToXY(x,LastLine - y + 1); {(x,y) position, in Cartesian style.}
|
|
TextBackground(Enter); {The value in Cell[x,y] may have been changed.}
|
|
TextColor(How);
|
|
Writeln(chr(Arrow[dx,dy])); {Not an ASCII control character, but an arrow symbol.}
|
|
Waitabit; {Having gone to all this trouble.}
|
|
End;
|
|
Procedure ShowState; {Special usage for line two of the screen.}
|
|
Begin
|
|
GoToXY(1,2); TextBackground(LightGray); TextColor(Black);
|
|
Write(Step:5,' (',x:2,',',y:2,') ');
|
|
TextColor(Yellow); {Yellow indicates the direction in mind.}
|
|
Write(chr(Arrow[dx,dy])); {On *arrival* at a position.}
|
|
End;
|
|
|
|
Var i,j: integer; {Steppers. No whole-array assault as in Cell:=LightGray;}
|
|
var Enter: byte; {Needed to remember the cell state on arrival.}
|
|
BEGIN
|
|
AsItWas.mode:=LastMode; {Grr. I might want to save the display content too!}
|
|
AsItWas.ta:=TextAttr; {Not just its colour and style.}
|
|
TextMode(C80+Font8x8); {Crazed gibberish gives less unsquare character cells, and 80x50 of them.}
|
|
LastLine:=Hi(WindMax); { + 1 omitted, as a write to the last line scrolls the screen up one...}
|
|
LastCol:=Lo(WindMax) + 1; {Counting starts at zero, even though GoToXY starts with one.}
|
|
x:=LastCol div 2; {Start somewhere middleish.}
|
|
y:=LastLine div 2; {Consider (x,y) as being (0,0) for axes.}
|
|
dx:=+1; dy:=0; {Initial direction.}
|
|
TextBackground(LightGray); {"White" is not valid for background colour.}
|
|
TextColor(Black); {This will show up on a light background.}
|
|
ClrScr; {Here we go.}
|
|
|
|
WriteLn('Langton''s Ant, on x = 1:',LastCol,', y = 1:',LastLine);
|
|
ShowState; {Where we start.}
|
|
WriteLn; TextColor(Black);
|
|
WriteLn('Press a key for each step.'); {Some encouragement.}
|
|
WriteLn('"S" to pause each step or not.');
|
|
WriteLn('ESC to quit.');
|
|
|
|
for i:=1 to LastLine do begin GoToXY(x,i); Write('|'); end; {Draw a y-axis.}
|
|
for i:=1 to LastCol do begin GoToXY(i,LastLine - y + 1); Write('-'); end; {And x.}
|
|
gotoxy(1,6); {Can't silence the cursor!}
|
|
|
|
for i:=1 to LastCol do {Prepare the cells.}
|
|
for j:=1 to LastLine do {One by one.}
|
|
Cell[i,j]:=LightGray; {Cell:=LightGray. Sigh.}
|
|
|
|
Stepwise:=true; {The action is of interest.}
|
|
for Step:=1 to 12000 do {Here we go.}
|
|
if (x <= 0) or (x > LastCol) or (y <= 0) or (y > LastCol) then Croak('Out of bounds')
|
|
else {We're in a cell.}
|
|
begin {So, inspect it.}
|
|
if Stepwise or (Step mod 10 = 0) then ShowState {On arrival.}
|
|
else if KeyPressed then Harken; {If we're not pausing, check for a key poke.}
|
|
Enter:=cell[x,y]; {This is what awaits the feet.}
|
|
if Stepwise then ShowDirection(Enter,Yellow); {Current direction, about to be changed.}
|
|
case cell[x,y] of {So, what to do?}
|
|
LightGray: begin Cell[x,y]:=Black; Turn(-1); end;{White. Make black and turn right.}
|
|
Black: begin Cell[x,y]:=LightGray; Turn(+1); end;{Black. Make white and turn left.}
|
|
end; {Having decided,}
|
|
if Stepwise then ShowDirection(Enter,Green); {Show the direction about to be stepped.}
|
|
GoToXY(x,LastLine - y + 1); {Screen location (column,line) for (x,y)}
|
|
TextBackground(Cell[x,y]); {Change the state I'm about to leave.}
|
|
Write(' '); {Foreground colour irrelevant for spaces.}
|
|
x:=x + dx; y:=y + dy; {Make the step!}
|
|
end; {On to consider our new position.}
|
|
|
|
Croak('Finished'); {That was fun.}
|
|
|
|
END.
|