Langton's ant: Difference between revisions

(→‎But, if one remembers complex numbers: A variation to distinguish the unsullied from the cleaned.)
Line 3,788:
};
show(langton())</lang>
 
=={{header|Pascal}}==
Pascal does not offer complex number arithmetic, so adjusting directions via multiplication of ±i is out. Similarly, it does not offer array manipulation statements, so <code>Cell:=White;</code> must be achieved via explicit for-loops with explicitly stated indices and bounds, and the adjustment of the (x,y) position by (dx,dy) can't be done by array addition. Otherwise, matters are straightforward, so instead this version tries to animate the ant on the screen. Alas, the maximum screen size is 80 characters by 50 lines, except that output to the last line causes a screen scroll so that only 49 lines are available. Alas, this cell array is too small and the bounds are exceeded in step 5,156 - before the ant starts its migration.
 
The animation shows the arrival at a cell with a yellow arrow pointing in the arrival direction. The cell state is investigated to decide the new direction (which is shown as a green arrow), the current cell's state is flipped, and the move to the new cell position is made. To show these events, the programme waits for a keystroke but if the S key is pressed, full speed results.
 
{{works with| Free Pascal}}
{{works with|Turbo Pascal}} Except, the green arrow on step 4 does not appear!
 
<lang Pascal>
{$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.
</lang>
 
=={{header|Perl}}==
1,220

edits