This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,10 @@
[[wp:Langton's ant|Langton's ant]] models an ant sitting on a plane of cells, all of which are white initially, facing in one of four directions. Each cell can either be black or white. The ant moves according to the color of the cell it is currently sitting in, with the following rules:
# If the cell is black, it changes to white and the ant turns left;
# If the cell is white, it changes to black and the ant turns right;
# The Ant then moves forward to the next cell, and repeat from step 1.
This rather simple ruleset leads to an initially chaotic movement pattern, and after about 10000 steps, a cycle appears where the ant moves steadily away from the starting location in a diagonal corridor about 10 pixels wide. Conceptually the ant can then travel to infinitely far away.
For this task, start the ant near the center of a 100 by 100 field of cells, which is about big enough to contain the initial chaotic part of the movement. Follow the movement rules for the ant, terminate when it moves out of the region, and show the cell colors it leaves behind.
The problem has received some analysis, for more details, please take a look at the Wikipedia article.

View file

@ -0,0 +1,2 @@
---
note: Cellular automata

View file

@ -0,0 +1,56 @@
with Ada.Text_IO;
procedure Langtons_Ant is
Size: constant Positive := 100; -- change this to extend the playground
subtype Step is Integer range -1 .. +1;
procedure Right(N, W: in out Step) is
Tmp: Step := W;
begin
W := - N;
N := Tmp;
end Right;
procedure Left(N, W: in out Step) is
begin
for I in 1 .. 3 loop
Right(N, W);
end loop;
end Left;
Color_Character: array(Boolean) of Character :=
(False => ' ', True => '#');
Is_Black: array (1 .. Size, 1 .. Size) of Boolean :=
(others => (others => False)); -- initially, the world is white;
Ant_X, Ant_Y: Natural := Size/2; -- Position of Ant;
Ant_North: Step := 1; Ant_West: Step := 0; -- initially, Ant looks northward
Iteration: Positive := 1;
begin
loop -- iterate the loop until an exception is raised
if Is_Black(Ant_X, Ant_Y) then
Left(Ant_North, Ant_West);
else
Right(Ant_North, Ant_West);
end if;
Is_Black(Ant_X, Ant_Y) := not Is_Black(Ant_X, Ant_Y);
Ant_X := Ant_X - Ant_North; -- this may raise an exception
Ant_Y := Ant_Y - Ant_West; -- this may raise an exception
Iteration := Iteration + 1;
end loop;
exception
when Constraint_Error => -- Ant has left its playground ... now output
for X in 1 .. Size loop
for Y in 1 .. Size loop
Ada.Text_IO.Put(Color_Character(Is_Black(X, Y)));
end loop;
Ada.Text_IO.New_Line;
end loop;
Ada.Text_IO.Put_Line("# Iteration:" & Integer'Image(Iteration));
end Langtons_Ant;

View file

@ -0,0 +1,20 @@
SetBatchLines -1
n := 0, x := 50, y := 50, d := 1 ; starting positions and orientation
While x > 0 and x < 100 and y > 0 and y < 100 ; In this loop the ant moves
d := d + !!(a%x%_%y%) - !(a%x%_%y%)
,d := d=5 ? 1 : d=0 ? 4 : d
,a%x%_%y% := !a%x%_%y%
,x := x + (d=3) - (d=1)
,y := y + (d=4) - (d=2)
Loop 99 ; in this loop the ant's movements are compiled into a string
{
y := A_Index
Loop 99
x := A_Index
,o .= a%x%_%y% ? "#" : "."
o .= "`r`n"
}
clipboard := o ; set the string to the clipboard

View file

@ -0,0 +1,21 @@
REM Implementation of Langton's ant for Rosetta Code
fieldsize%=100
REM Being pedantic, this will actually result in a field of 101 square,
REM since arrays start at 0, and my implementation allows them to use it
DIM field&(fieldsize%,fieldsize%) : REM variables with an & suffix are byte variables
x%=fieldsize%/2
y%=fieldsize%/2
d%=0
REPEAT
IF field&(x%,y%)=0 THEN field&(x%,y%)=1:d%-=1 ELSE field&(x%,y%)=0:d%+=1
GCOL 15*field&(x%,y%)
PLOT 69,x%*2,y%*2 :REM for historical reasons there are two "plot points" per pixel
d%=(d%+4) MOD 4 :REM ensure direction is always between 0 and 3
CASE d% OF
WHEN 0:y%+=1
WHEN 1:x%+=1
WHEN 2:y%-=1
WHEN 3:x%-=1
ENDCASE
UNTIL x%>fieldsize% OR x%<0 OR y%>fieldsize% OR y%<0
END

View file

@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int w = 0, h = 0;
unsigned char *pix;
void refresh(int x, int y)
{
int i, j, k;
printf("\033[H");
for (i = k = 0; i < h; putchar('\n'), i++)
for (j = 0; j < w; j++, k++)
putchar(pix[k] ? '#' : ' ');
}
void walk()
{
int dx = 0, dy = 1, i, k;
int x = w / 2, y = h / 2;
pix = calloc(1, w * h);
printf("\033[H\033[J");
while (1) {
i = (y * w + x);
if (pix[i]) k = dx, dx = -dy, dy = k;
else k = dy, dy = -dx, dx = k;
pix[i] = !pix[i];
printf("\033[%d;%dH%c", y + 1, x + 1, pix[i] ? '#' : ' ');
x += dx, y += dy;
k = 0;
if (x < 0) {
memmove(pix + 1, pix, w * h - 1);
for (i = 0; i < w * h; i += w) pix[i] = 0;
x++, k = 1;
}
else if (x >= w) {
memmove(pix, pix + 1, w * h - 1);
for (i = w-1; i < w * h; i += w) pix[i] = 0;
x--, k = 1;
}
if (y >= h) {
memmove(pix, pix + w, w * (h - 1));
memset(pix + w * (h - 1), 0, w);
y--, k = 1;
}
else if (y < 0) {
memmove(pix + w, pix, w * (h - 1));
memset(pix, 0, w);
y++, k = 1;
}
if (k) refresh(x, y);
printf("\033[%d;%dH\033[31m@\033[m", y + 1, x + 1);
fflush(stdout);
usleep(10000);
}
}
int main(int c, char **v)
{
if (c > 1) w = atoi(v[1]);
if (c > 2) h = atoi(v[2]);
if (w < 40) w = 40;
if (h < 25) h = 25;
walk();
return 0;
}

View file

@ -0,0 +1,14 @@
(let [bounds (set (range 100))
xs [1 0 -1 0] ys [0 -1 0 1]]
(loop [dir 0 x 50 y 50
grid {[x y] false}]
(if (and (bounds x) (bounds y))
(let [cur (not (grid [x y]))
dir (mod (+ dir (if cur -1 1)) 4)]
(recur dir (+ x (xs dir)) (+ y (ys dir))
(merge grid {[x y] cur})))
(doseq [col (range 100)]
(println
(apply str
(map #(if (grid [% col]) \# \.)
(range 100))))))))

View file

@ -0,0 +1,79 @@
class Ant
constructor: (@world) ->
@location = [0, 0]
@direction = 'E'
move: =>
[x, y] = @location
if @world.is_set x, y
@world.unset x, y
@direction = Directions.left @direction
else
@world.set x, y
@direction = Directions.right @direction
@location = Directions.forward(x, y, @direction)
# Model a theoretically infinite 2D world with a hash, allowing squares
# to be black or white (independent of any ants.)
class BlackWhiteWorld
constructor: ->
@bits = {}
set: (x, y) ->
@bits["#{x},#{y}"] = true
unset: (x, y) ->
delete @bits["#{x},#{y}"]
is_set: (x, y) ->
@bits["#{x},#{y}"]
draw: ->
# Most of this code just involves finding the extent of the world.
# Always include the origin, even if it's not set.
@min_x = @max_x = @min_y = @max_y = 0
for key of @bits
[xx, yy] = (coord for coord in key.split ',')
x = parseInt xx
y = parseInt yy
@min_x = x if x < @min_x
@max_x = x if x > @max_x
@min_y = y if y < @min_y
@max_y = y if y > @max_y
console.log "top left: #{@min_x}, #{@max_y}, bottom right: #{@max_x}, #{@min_y}"
for y in [@max_y..@min_y] by -1
s = ''
for x in [@min_x..@max_x]
if @bits["#{x},#{y}"]
s += '#'
else
s += '_'
console.log s
# Simple code for directions, independent of ants.
Directions =
left: (dir) ->
return 'W' if dir == 'N'
return 'S' if dir == 'W'
return 'E' if dir == 'S'
'N'
right: (dir) ->
return 'E' if dir == 'N'
return 'S' if dir == 'E'
return 'W' if dir == 'S'
'N'
forward: (x, y, dir) ->
return [x, y+1] if dir == 'N'
return [x, y-1] if dir == 'S'
return [x+1, y] if dir == 'E'
return [x-1, y] if dir == 'W'
world = new BlackWhiteWorld()
ant = new Ant(world)
for i in [1..11500]
ant.move()
console.log "Ant is at #{ant.location}, direction #{ant.direction}"
world.draw()

View file

@ -0,0 +1,80 @@
> coffee langstons_ant.coffee
Ant is at -24,46, direction W
top left: -25, 47, bottom right: 22, -29
_##__##_________________________________________
##_#####________________________________________
#____##_#_______________________________________
____#_#_##______________________________________
_####_###_#_____________________________________
_#####_#__##____________________________________
__#___##_##_#___________________________________
___###___#__##__________________________________
____#___##_##_#_________________________________
_____###___#__##________________________________
______#___##_##_#_______________________________
_______###___#__##______________________________
________#___##_##_#_____________________________
_________###___#__##____________________________
__________#___##_##_#___________________________
___________###___#__##__________________________
____________#___##_##_#_________________________
_____________###___#__##________________________
______________#___##_##_#_______________________
_______________###___#__##______________________
________________#___##_##_#_____________________
_________________###___#__##____________________
__________________#___##_##_#___________________
___________________###___#__##__________________
____________________#___##_##_#_________________
_____________________###___#__##________________
______________________#___##_##_#_______________
_______________________###___#__##______________
________________________#___##_##_#__##_________
_________________________###___#__##__##________
__________________________#___##_##__##___#_____
____________________####___###___#___#__###_____
___________________#____#___#___##_####___#_____
__________________###____#___#_#______#_##_#____
__________________###____#_##_____#_##__#_##____
___________________#____#___##_#_#_____##_______
___________________#_#______#_#####__#___#______
__________________#___#####__________##_######__
__________________###__##__#_##_#_#_#___##_#_##_
________________##__#_#######_#___#__###____##_#
_______________#__#__######_##___#__#_##___#___#
______________#____#_#_##_#__######_#######___#_
______________#_####_##_#_####____##__##_#_##_#_
_______________#____####___#__#_######_##____###
__________________#___#_##_#_###_#__##__##___###
_____________________#######____#__##_##_#_____#
_____________####__##_##__####_##_##_##__#_____#
____________#____#_#___###_##_###____#_####____#
___________###_______###_#_#_#####____#_#______#
___________#_#___###_####_##_#___##_###_##_____#
_________________##_##__####____####_#_#_#_____#
____________#____#__##___###__###_____###______#
____________##___##_###_####__#______###___##__#
____________##_#_####_____#___#__#_##_###_##___#
___________####_##___##_####__#_#__#__#__###___#
___________#_##_###__#_#_##_#_#_____#_#_____#_#_
_______________#_#__#____##_##__#_#__###_##_____
_______________##_#____#__#####_#____#____#__#_#
______________#_##_#__#____##_##_#__###______###
____________#_#___#__#__#__#__###___##__##____#_
___________###_#_#####_######_###_#######_#_##__
___________#_#_#____#####___##__#####_#####_____
_____________#__##___#______#__#_##__###_###____
__________####___#####_#########___#_#__________
_____##____#__#_____###_#_#___#_###__###________
____#__#__####_##___###_##___###_##_____##______
___###____#_##_#_#####___#____#__#__##_###______
___#_#####_#_#___##__##_____#____#___#__#_______
_______######_####__##_#___#__##__#_#_##________
_____##______#_###_##__####___#___###___________
______#__#_#####__#___#_##___#__#__#____________
______##_###_#######_____#_____#_##_____________
_____#_#__##_##______#___##____#________________
____#__#_####________###__##__#_________________
____#_##_###____________##__##__________________
_____##_________________________________________
______##________________________________________

View file

@ -0,0 +1,32 @@
(defmacro toggle (gv) `(setf ,gv (not ,gv)))
(defun langtons-ant (width height start-x start-y start-dir)
(let ( (grid (make-array (list width height)))
(x start-x)
(y start-y)
(dir start-dir) )
(loop while (and (< -1 x width) (< -1 y height)) do
(if (toggle (aref grid x y))
(setq dir (mod (1+ dir) 4))
(setq dir (mod (1- dir) 4)))
(case dir
(0 (decf y))
(1 (incf x))
(2 (incf y))
(3 (decf x)))
)
grid
)
)
(defun show-grid (grid)
(destructuring-bind (width height) (array-dimensions grid)
(dotimes (y height)
(dotimes (x width)
(princ (if (aref grid x y) "#" ".")))
(princ #\Newline))
)
)
(setf *random-state* (make-random-state t))
(show-grid (langtons-ant 100 100 (+ 45 (random 10)) (+ 45 (random 10)) (random 4)))

View file

@ -0,0 +1,25 @@
import std.stdio, std.traits;
void main() {
enum width = 75, height = 52;
enum maxSteps = 12_000;
enum Direction { up, right, down, left }
enum Color : char { white = '.', black = '#' }
uint x = width / 2, y = height / 2;
auto M = new Color[][](height, width);
auto dir = Direction.up;
for (int i = 0; i < maxSteps && x < width && y < height; i++) {
immutable turn = M[y][x] == Color.black;
dir = [EnumMembers!Direction][(dir + (turn ? 1 : -1)) & 3];
M[y][x] = (M[y][x] == Color.black) ? Color.white : Color.black;
final switch(dir) with (Direction) {
case up: y--; break;
case right: x--; break;
case down: y++; break;
case left: x++; break;
}
}
writefln("%-(%s\n%)", cast(char[][])M);
}

View file

@ -0,0 +1,25 @@
import std.stdio, std.algorithm, std.traits, grayscale_image;
void main() {
enum width = 100, height = 100;
enum nSteps = 12_000;
enum Direction { up, right, down, left }
auto M = new Image!Gray(width, height);
M.clear(Gray.white);
uint x = width / 2, y = height / 2;
auto dir = Direction.up;
for (int i = 0; i < nSteps && x < width && y < height; i++) {
immutable turn = M[x, y] == Gray.black;
dir = [EnumMembers!Direction][(dir + (turn ? 1 : -1)) & 3];
M[x, y] = (M[x, y] == Gray.black) ? Gray.white : Gray.black;
final switch(dir) with (Direction) {
case up: y--; break;
case right: x--; break;
case down: y++; break;
case left: x++; break;
}
}
M.savePGM("langton_ant.pgm");
}

View file

@ -0,0 +1,51 @@
open list core generic
type Field = Field a
type Color = White | Black
type Direction = Lft | Fwd | Rgt | Bwd
field s = Field [[White \\ _ <- [1..s]] \\ _ <- [1..s]]
isBlack Black = true
isBlack _ = false
newfield xc yc (Field xs) = Field (newfield' 0 xs)
where newfield' _ [] = []
newfield' n (x::xs)
| n == yc = row 0 x :: xs
| else = x :: newfield' (n+1) xs
where row _ [] = []
row n (x::xs)
| n == xc = toggle x :: xs
| else = x :: row (n+1) xs
where toggle White = Black
toggle Black = White
showPath (Field xs) = toString <| show' "" xs
where show' sb [] = sb +> ""
show' sb (x::xs) = show' (showRow sb x +> "\r\n") xs
where showRow sb [] = sb +> ""
showRow sb (x::xs) = showRow (sb +> s) xs
where s | isBlack x = "#"
| else = "_"
move s xc yc = move' (Fwd,xc,yc) (field s)
where move' (pos,xc,yc)@coor fld
| xc >= s || yc >= s || xc < 0 || yc < 0 = fld
| else = fld |> newfield xc yc |> move' (matrix (dir fld) coor)
where dir (Field xs)
| `isBlack` (xs:yc):xc = Lft
| else = Rgt
matrix Lft (pos,x,y) = go (left pos,x,y)
matrix Rgt (pos,x,y) = go (right pos,x,y)
go (Lft,x,y) = (Lft,x - 1,y)
go (Rgt,x,y) = (Rgt,x+1,y)
go (Fwd,x,y) = (Fwd,x,y - 1)
go (Bwd,x,y) = (Bwd,x,y+1)
right Lft = Fwd
right Fwd = Rgt
right Rgt = Bwd
right Bwd = Lft
left Lft = Bwd
left Bwd = Rgt
left Rgt = Fwd
left Fwd = Lft

View file

@ -0,0 +1 @@
showPath <| move 100 50 50

View file

@ -0,0 +1,65 @@
include std\console.e
include std\graphics.e
sequence grid = repeat(repeat(1,100),100) --fill 100 by 100 grid with white (1)
sequence antData = {48, 53, 360} --ant x coordinate, y coordinate, facing angle
integer iterations = 0
--while ant isn't out of bounds of the 100 by 100 area..
while antData[1] > 0 and antData[1] < 100 and antData[2] > 0 and antData[2] < 100 do
switch grid[antData[1]][antData[2]] do
case 1 then--cell is already white
grid[antData[1]][antData[2]] = 0 --cell turns black, ant turns right
antData[3] += 90
break
case 0 then--cell is already black
grid[antData[1]][antData[2]] = 1 --cell turns white, ant turns left
antData[3] -= 90
break
end switch
--wrap ant directions if > 360 or < 90 (by 90)
switch antData[3] do
case 450 then
antData[3] = 90
break
case 0 then
antData[3] = 360
break
end switch
--move ant based on its new facing, one square
--first north, then south, east, west
switch antData[3] do
case 360 then
antData[2] -= 1
break
case 180 then
antData[2] += 1
break
case 90 then
antData[1] += 1
break
case 270 then
antData[1] -= 1
break
end switch
iterations += 1
end while
wrap(0) --don't wrap text output, the grid wouldnt display as a square
for y=1 to 100 do
printf(1,"\n")
for x=1 to 100 do
switch grid[x][y] do--each grid block , based on color
case 0 then
printf(1,".")
break
case 1 then
printf(1,"#")
break
end switch
end for
end for
printf(1,"\n%d Iterations\n",iterations)
any_key()--wait for keypress, put default message 'press any key..'

View file

@ -0,0 +1,2 @@
sequence grid = repeat(repeat(1,100),100) --fill 100 by 100 grid with white (1)
sequence antData = {48, 53, 360} --x coordinate, y coordinate, facing angle

View file

@ -0,0 +1,130 @@
class World
{
Int height
Int width
Bool[] state
new make (Int height, Int width)
{
this.height = height
this.width = width
state = List(Bool#, height * width)
(height*width).times { state.add (false) }
}
Bool inWorld (Int x, Int y)
{
x >= 0 && x < width && y >= 0 && y < height
}
Void show ()
{
height.times |h|
{
width.times |w|
{
Env.cur.out.writeChar (state[w*width+h] ? '#' : '.')
}
Env.cur.out.writeChar ('\n')
}
}
Void flip (Int x, Int y)
{
state[x*width + y] = !state[x*width + y]
}
Bool stateOf (Int x, Int y)
{
state[x*width + y]
}
}
enum class Direction
{
up (0, -1),
down (0, 1),
left (-1, 0),
right (1, 0)
private new make (Int deltaX, Int deltaY)
{
this.deltaX = deltaX
this.deltaY = deltaY
}
Direction rotateLeft ()
{
if (this == up) return left
if (this == down) return right
if (this == left) return down
// if (this == right)
return up
}
Direction rotateRight ()
{
if (this == up) return right
if (this == down) return left
if (this == left) return up
// if (this == right)
return down
}
const Int deltaX
const Int deltaY
}
class Ant
{
World world
Int currX
Int currY
Direction direction
new make (World world, Int x, Int y)
{
this.world = world
currX = x
currY = y
direction = Direction.up
}
Bool inWorld ()
{
world.inWorld (currX, currY)
}
// the ant movement rules
Void move ()
{
if (world.stateOf (currX, currY))
{
direction = direction.rotateLeft
}
else
{
direction = direction.rotateRight
}
world.flip (currX, currY)
currX += direction.deltaX
currY += direction.deltaY
}
}
class Main
{
Void main ()
{
world := World (100, 100)
ant := Ant (world, 50, 50)
numIterations := 0
while (ant.inWorld)
{
ant.move
numIterations += 1
}
world.show
echo ("Finished in $numIterations iterations")
}
}

View file

@ -0,0 +1,53 @@
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"os"
)
const (
up = iota
rt
dn
lt
)
func main() {
bounds := image.Rect(0, 0, 100, 100)
im := image.NewGray(bounds)
gBlack := color.Gray{0}
gWhite := color.Gray{255}
draw.Draw(im, bounds, image.NewUniform(gWhite), image.ZP, draw.Src)
pos := image.Point{50, 50}
dir := up
for pos.In(bounds) {
switch im.At(pos.X, pos.Y).(color.Gray).Y {
case gBlack.Y:
im.SetGray(pos.X, pos.Y, gWhite)
dir--
case gWhite.Y:
im.SetGray(pos.X, pos.Y, gBlack)
dir++
}
if dir&1 == 1 {
pos.X += 1 - dir&2
} else {
pos.Y -= 1 - dir&2
}
}
f, err := os.Create("ant.png")
if err != nil {
fmt.Println(err)
return
}
if err = png.Encode(f, im); err != nil {
fmt.Println(err)
}
if err = f.Close(); err != nil {
fmt.Println(err)
}
}

View file

@ -0,0 +1,81 @@
data Color = Black | White
deriving (Read, Show, Enum, Eq, Ord)
putCell c = putStr (case c of Black -> "#"
White -> ".")
toggle :: Color -> Color
toggle color = toEnum $ 1 - fromEnum color
data Dir = East | North | West | South
deriving (Read, Show, Enum, Eq, Ord)
turnLeft South = East
turnLeft dir = succ dir
turnRight East = South
turnRight dir = pred dir
data Pos = Pos { x :: Int, y :: Int }
deriving (Read)
instance Show Pos where
show p@(Pos x y) = "(" ++ (show x) ++ "," ++ (show y) ++ ")"
-- Return the new position after moving one unit in the given direction
moveOne pos@(Pos x y) dir =
case dir of
East -> Pos (x+1) y
South -> Pos x (y+1)
West -> Pos (x-1) y
North -> Pos x (y-1)
-- Grid is just a list of lists
type Grid = [[Color]]
colorAt g p@(Pos x y) = (g !! y) !! x
replaceNth n newVal (x:xs)
| n == 0 = newVal:xs
| otherwise = x:replaceNth (n-1) newVal xs
toggleCell g p@(Pos x y) =
let newVal = toggle $ colorAt g p
in replaceNth y (replaceNth x newVal (g !! y)) g
printRow r = do { mapM_ putCell r ; putStrLn "" }
printGrid g = mapM_ printRow g
data State = State { move :: Int, pos :: Pos, dir :: Dir, grid :: Grid }
printState s = do {
putStrLn $ show s;
printGrid $ grid s
}
instance Show State where
show s@(State m p@(Pos x y) d g) =
"Move: " ++ (show m) ++ " Pos: " ++ (show p) ++ " Dir: " ++ (show d)
nextState s@(State m p@(Pos x y) d g) =
let color = colorAt g p
new_d = case color of White -> (turnRight d)
Black -> (turnLeft d)
new_m = m + 1
new_p = moveOne p new_d
new_g = toggleCell g p
in State new_m new_p new_d new_g
inRange size s@(State m p@(Pos x y) d g) =
x >= 0 && x < size && y >= 0 && y < size
initialState size = (State 0 (Pos (size`div`2) (size`div`2)) East [ [ White | x <- [1..size] ] | y <- [1..size] ])
--- main
size = 100
allStates = initialState size : [nextState s | s <- allStates]
main = printState $ last $ takeWhile (inRange size) allStates

View file

@ -0,0 +1,52 @@
link graphics,printf
procedure main(A)
e := ( 0 < integer(\A[1])) | 100 # 100 or whole number from command line
LangtonsAnt(e)
end
record antrec(x,y,nesw)
procedure LangtonsAnt(e)
size := sprintf("size=%d,%d",e,e)
label := sprintf("Langton's Ant %dx%d [%d]",e,e,0)
&window := open(label,"g","bg=white",size) |
stop("Unable to open window")
ant := antrec(e/2,e/2,?4%4)
board := list(e)
every !board := list(e,"w")
k := 0
repeat {
k +:= 1
WAttrib("fg=red")
DrawPoint(ant.x,ant.y)
cell := board[ant.x,ant.y]
if cell == "w" then { # white cell
WAttrib("fg=black")
ant.nesw := (ant.nesw + 1) % 4 # . turn right
}
else { # black cell
WAttrib( "fg=white")
ant.nesw := (ant.nesw + 3) % 4 # . turn left = 3 x right
}
board[ant.x,ant.y] := map(cell,"wb","bw") # flip colour
DrawPoint(ant.x,ant.y)
case ant.nesw of { # go
0: ant.y -:= 1 # . north
1: ant.x +:= 1 # . east
2: ant.y +:= 1 # . south
3: ant.x -:= 1 # . west
}
if 0 < ant.x <= e & 0 < ant.y <= e then next
else break
}
printf("Langton's Ant exited the field after %d rounds.\n",k)
label := sprintf("label=Langton's Ant %dx%d [%d]",e,e,k)
WAttrib(label)
WDone()
end

View file

@ -0,0 +1,11 @@
dirs=: 0 1,1 0,0 _1,:_1 0
langton=:3 :0
loc=. <.-:$cells=. (_2{.y,y)$dir=. 0
while. *./(0<:loc), loc<$cells do.
color=. (<loc) { cells
cells=. (-.color) (<loc)} cells
dir=. 4 | dir + _1 ^ color
loc=. loc + dir { dirs
end.
' #' {~ cells
)

View file

@ -0,0 +1,68 @@
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Langton extends JFrame{
private JPanel planePanel;
private static final int ZOOM = 4;
public Langton(final boolean[][] plane){
planePanel = new JPanel(){
@Override
public void paint(Graphics g) {
for(int y = 0; y < plane.length;y++){
for(int x = 0; x < plane[0].length;x++){
g.setColor(plane[y][x] ? Color.BLACK : Color.WHITE);
g.fillRect(x * ZOOM, y * ZOOM, ZOOM, ZOOM);
}
}
//mark the starting point
g.setColor(Color.GREEN);
g.fillRect(plane[0].length / 2 * ZOOM,
plane.length / 2 * ZOOM, ZOOM/2, ZOOM/2);
}
};
planePanel.setSize(plane[0].length - 1, plane.length - 1);
add(planePanel);
setSize(ZOOM * plane[0].length, ZOOM * plane.length + 30);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args){
new Langton(runAnt(100, 100));
}
private static boolean[][] runAnt(int height, int width){
boolean[][] plane = new boolean[height][width];
int antX = width/2, antY = height/2;//start in the middle-ish
int xChange = 0, yChange = -1; //start moving up
while(antX < width && antY < height && antX >= 0 && antY >= 0){
if(plane[antY][antX]){
//turn left
if(xChange == 0){ //if moving up or down
xChange = yChange;
yChange = 0;
}else{ //if moving left or right
yChange = -xChange;
xChange = 0;
}
}else{
//turn right
if(xChange == 0){ //if moving up or down
xChange = -yChange;
yChange = 0;
}else{ //if moving left or right
yChange = xChange;
xChange = 0;
}
}
plane[antY][antX] = !plane[antY][antX];
antX += xChange;
antY += yChange;
}
return plane;
}
}

View file

@ -0,0 +1,101 @@
// create global canvas
var canvas = document.createElement('canvas');
canvas.id = 'globalCanvas';
document.body.appendChild(canvas);
function langtonant(antx, optx) {
'use strict';
var x, y, i;
// extend default opts
var opts = {
gridsize: 100,
pixlsize: 4,
interval: 4
};
for (i in optx) {
opts[i] = optx[i];
}
// extend default ants
var ants = [{
x: 50,
y: 50,
d: 0
}];
for (i in antx) {
ants[i] = antx[i];
}
// initialise grid
var grid = [];
for (x = 0; x < opts.gridsize; x ++) {
grid[x] = [];
for (y = 0; y < opts.gridsize; y ++) {
grid[x][y] = true;
}
}
// initialise directions
var dirs = [
{x: 1, y: 0},
{x: 0, y: -1},
{x: -1, y: 0},
{x: 0, y: 1}
];
// initialise canvas
var canv = document.getElementById('globalCanvas');
var cont = canv.getContext('2d');
canv.width = opts.gridsize * opts.pixlsize;
canv.height = opts.gridsize * opts.pixlsize;
// initialise pixels
var pixlblac = cont.createImageData(opts.pixlsize, opts.pixlsize);
for (i = 0; i < (opts.pixlsize * opts.pixlsize * 4); i += 4) {
pixlblac.data[i + 3] = 255;
}
var pixlwhit = cont.createImageData(opts.pixlsize, opts.pixlsize);
for (i = 0; i < (opts.pixlsize * opts.pixlsize * 4); i += 4) {
pixlwhit.data[i + 3] = 0;
}
// run simulation
function simulate() {
var sane = true;
// iterate over ants
for (i = 0; i < ants.length; i ++) {
var n = ants[i];
// invert, draw, turn
if (grid[n.x][n.y]) {
grid[n.x][n.y] = false;
cont.putImageData(pixlblac, n.x * opts.pixlsize, n.y * opts.pixlsize);
n.d --;
} else {
grid[n.x][n.y] = true;
cont.putImageData(pixlwhit, n.x * opts.pixlsize, n.y * opts.pixlsize);
n.d ++;
}
// modulus wraparound
n.d += dirs.length;
n.d %= dirs.length;
// position + direction
n.x += dirs[n.d].x;
n.y += dirs[n.d].y;
// sanity check
sane = (n.x < 0 || n.x > opts.gridsize || n.y < 0 || n.y > opts.gridsize) ? false : sane;
}
// loop with interval
if (sane) {
setTimeout(simulate, opts.interval);
}
}
simulate();
}

View file

@ -0,0 +1,5 @@
langtonant({}, {
gridsize: 100,
pixlsize: 4,
interval: 4
});

View file

@ -0,0 +1,19 @@
langtonant([
{
x: (100 / 2) + 7,
y: (100 / 2) + 7,
d: 1
}, {
x: (100 / 2) + 7,
y: (100 / 2) - 7,
d: 2
}, {
x: (100 / 2) - 7,
y: (100 / 2) - 7,
d: 3
}, {
x: (100 / 2) - 7,
y: (100 / 2) + 7,
d: 0
}
]);

View file

@ -0,0 +1,39 @@
HAI 1.3
I HAS A plane ITZ A BUKKIT
IM IN YR init UPPIN YR i TIL BOTH SAEM i AN 10000
plane HAS A SRS i ITZ FAIL
IM OUTTA YR init
I HAS A x ITZ 50, I HAS A y ITZ 50
I HAS A dir ITZ 0, I HAS A pos, I HAS A cell
BTW, WE PURRTIND WE HAS A 2D STRUKSHUR FUR EZ AKSESS
IM IN YR walker
pos R SUM OF PRODUKT OF y AN 100 AN x
cell R NOT plane'Z SRS pos
plane'Z SRS pos R cell
dir R MOD OF SUM OF dir AN SUM OF 5 AN PRODUKT OF cell AN 2 AN 4
dir, WTF?
OMG 0, x R SUM OF x AN 1, GTFO
OMG 1, y R DIFF OF y AN 1, GTFO
OMG 2, x R DIFF OF x AN 1, GTFO
OMG 3, y R SUM OF y AN 1, GTFO
OIC
BTW, CHEKIN TEH ANTZ BOUNDZ
WON OF BOTH SAEM x AN -1 AN BOTH SAEM x AN 100, O RLY?, YA RLY, GTFO, OIC
WON OF BOTH SAEM y AN -1 AN BOTH SAEM y AN 100, O RLY?, YA RLY, GTFO, OIC
IM OUTTA YR walker
IM IN YR printer UPPIN YR cell TIL BOTH SAEM cell AN 10000
plane'Z SRS cell, O RLY?
YA RLY, VISIBLE "#"!
NO WAI, VISIBLE "."!
OIC
NOT MOD OF SUM OF cell AN 1 AN 100, O RLY?, YA RLY, VISIBLE "", OIC
IM OUTTA YR printer BTW, UR OUTTA CYAN
KTHXBYE

View file

@ -0,0 +1,55 @@
dim arena(100,100)
black=0
white=not(black)
for i = 1 to 100
for j = 1 to 100
arena(i,j)=white
next
next
'north=1 east=2 south=3 west=4
nomainwin
graphicbox #1.g, 0, 0, 100, 100
open "Langton's Ant" for window as #1
#1 "trapclose Quit"
#1.g "down"
antX=50:antY=50
nsew=1 'ant initially points north
while (antX>0) and (antX<100) and (antY>0) and (antY<100)
if arena(antX,antY) then
nsew=nsew-1
if nsew<1 then nsew=4
else
nsew=nsew+1
if nsew>4 then nsew=1
end if
select case nsew
case 1: antY=antY-1
case 2: antX=antX+1
case 3: antY=antY+1
case 4: antX=antX-1
end select
arena(antX,antY)=not(arena(antX,antY))
#1.g "color ";GetColor$(antX,antY)
#1.g "set ";antX;" ";antY
wend
#1.g "flush"
wait
function GetColor$(x,y)
if arena(x,y) then
GetColor$="white"
else
GetColor$="black"
end if
end function
sub Quit handle$
close #handle$
end
end sub

View file

@ -0,0 +1,27 @@
'move up=1 right=2 down=3 left=4
' ---------------------------------
dim plane(100,100)
x = 50: y = 50
mx = 100
while (x>0) and (x<100) and (y>0) and (y<100)
if plane(x,y) then
nxt = nxt - 1
if nxt < 1 then nxt = 4
else
nxt = nxt + 1
if nxt > 4 then nxt = 1
end if
x = x + (nxt = 2) - (nxt = 4)
y = y + (nxt = 3) - (nxt = 1)
plane(x,y) = (plane(x,y) <> 1)
mx = min(x,mx)
wend
for x = mx to 100
for y = 1 to 100
print chr$((plane(x,y)*3) + 32);
next y
print x
next x

View file

@ -0,0 +1,14 @@
10 mode 1:defint a-z:deg
20 ink 1,0:ink 0,26
30 x=50:y=50:ang=270
40 dim play(100,100)
50 graphics pen 3:move 220,100:drawr 200,0:drawr 0,200:drawr -200,0:drawr 0,-200
60 ' move ant
70 if play(x,y) then ang=ang-90 else ang=ang+90
80 play(x,y)=1-play(x,y)
90 plot 220+2*x,100+2*y,play(x,y)
100 ang=ang mod 360
110 x=x+sin(ang)
120 y=y+cos(ang)
130 if x<1 or x>100 or y<1 or y>100 then end
140 goto 70

View file

@ -0,0 +1,6 @@
direction = 1;
data = SparseArray[{{50, 50} -> -1}, {100, 100}, 1];
NestWhile[
{Re@#, Im@#} &@(direction *= (data[[Sequence @@ #]] *= -1) I) + # &,
{50, 50}, 1 <= Min@# <= Max@# <= 100 &];
Image@data

View file

@ -0,0 +1,51 @@
// INIT AND DEFINITION
define('dest_name', 'output.png'); // destination image
define('width', 100);
define('height', 100);
$x = 50;
$y = 70;
$dir = 0; // 0-up, 1-left, 2-down, 3-right
$field = array();
$step_count = 0;
// LANGTON´S ANT PROCEDURE
while(0 <= $x && $x <= width && 0 <= $y && $y <= height){
if(isset($field[$x][$y])){
unset($field[$x][$y]);
$dir = ($dir + 1) % 4;
}else{
$field[$x][$y] = true;
$dir = ($dir + 3) % 4;
}
switch($dir){
case 0: $y++; break;
case 1: $x--; break;
case 2: $y--; break;
case 3: $x++; break;
}
$step_count++;
}
// ARRAY TO IMAGE
$img = imagecreatetruecolor(width, height);
$white = imagecolorallocate($img, 255, 255, 255);
for($x = 0; $x < width; $x++){
for($y = 0; $y < height; $y++){
if(isset($field[$x][$y])){
imagesetpixel($img, $x, $y, $white);
}
}
}
// TEXT TO IMAGE
$color = array();
$color[0] = imagecolorallocate($img, 255, 0, 0);
$color[1] = imagecolorallocate($img, 0, 255, 0);
$color[2] = imagecolorallocate($img, 0, 0, 255);
$print_array = array(
0 => 'Langton`s Ant', 1=>'PHP Version', 2=>'Steps: ' . $step_count
);
foreach($print_array as $key => $line){
imagestring($img, 3, 3, 3 + $key*11, $line, $color[$key]);
}
// SAVE IMAGE
imagepng($img, dest_name);

View file

@ -0,0 +1,41 @@
#!/usr/bin/perl
use strict;
# Perl 5 implementation of Langton's Ant
# Using screen coordinates - 0,0 in upper-left, +X right, +Y down -
# these directions (right, up, left, down) are counterclockwise
# so advance through the array to turn left, retreat to turn right
my @dirs = ( [1,0], [0,-1], [-1,0], [0,1] );
my $size = 100;
# we treat any false as white and true as black, so undef is fine for initial all-white grid
my @plane;
for (0..$size-1) { $plane[$_] = [] };
# start out in approximate middle
my ($x, $y) = ($size/2, $size/2);
# pointing in a random direction
my $dir = int rand @dirs;
my $move;
for ($move = 0; $x >= 0 && $x < $size && $y >= 0 && $y < $size; $move++) {
# toggle cell's value (white->black or black->white)
if ($plane[$x][$y] = 1 - $plane[$x][$y]) {
# if it's now true (black), then it was white, so turn right
$dir = ($dir - 1) % @dirs;
} else {
# otherwise it was black, so turn left
$dir = ($dir + 1) % @dirs;
}
$x += $dirs[$dir][0];
$y += $dirs[$dir][1];
}
print "Out of bounds after $move moves at ($x, $y)\n";
for (my $y=0; $y<$size; ++$y) {
for (my $x=0; $x<$size; ++$x) {
print $plane[$x][$y] ? '#' : '.';
}
print "\n";
}

View file

@ -0,0 +1,17 @@
(de ant (Width Height X Y)
(let (Field (make (do Height (link (need Width)))) Dir 0)
(until (or (le0 X) (le0 Y) (> X Width) (> Y Height))
(let Cell (nth Field X Y)
(setq Dir (% (+ (if (car Cell) 1 3) Dir) 4))
(set Cell (not (car Cell)))
(case Dir
(0 (inc 'X))
(1 (inc 'Y))
(2 (dec 'X))
(3 (dec 'Y)) ) ) )
(prinl "P1")
(prinl Width " " Height)
(for Row Field
(prinl (mapcar '[(X) (if X 1 0)] Row)) ) ) )
(out '(display -) (ant 100 100 50 50))
(bye)

View file

@ -0,0 +1,28 @@
width = 75
height = 52
nsteps = 12000
class Dir: up, right, down, left = range(4)
class Turn: left, right = False, True
class Color: white, black = '.', '#'
M = [[Color.white] * width for _ in xrange(height)]
x = width // 2
y = height // 2
dir = Dir.up
i = 0
while i < nsteps and 0 <= x < width and 0 <= y < height:
turn = Turn.left if M[y][x] == Color.black else Turn.right
M[y][x] = Color.white if M[y][x] == Color.black else Color.black
dir = (4 + dir + (1 if turn else -1)) % 4
dir = [Dir.up, Dir.right, Dir.down, Dir.left][dir]
if dir == Dir.up: y -= 1
elif dir == Dir.right: x -= 1
elif dir == Dir.down: y += 1
elif dir == Dir.left: x += 1
else: assert False
i += 1
print "\n".join("".join(row) for row in M)

View file

@ -0,0 +1,41 @@
/*REXX program implements Langton's ant and displays the path it walked.*/
parse arg dir . /*allow specification: ant facing*/
/*binary colors: 0=white, 1=black*/
@.=0 /*define stem array (all white).*/
lb=1 ; rb=100 /* right boundry, right boundry.*/
bb=1 ; tb=100 /*bottom " top " */
x=(rb-lb)%2 ; y=(tb-bb)%2 /*approximate center (walk start)*/
if dir=='' then dir=random(1,4) /*ant is facing random direction,*/
/*1=north 2=east 3=south 4=west*/
/*───────────────────────────────────────────ant walks hither & thither.*/
do steps=1 until x<lb | x>rb | y<bb | y>tb /*walk until out-of-bounds*/
black=@.x.y /*get color code of ant's cell. */
@.x.y=\@.x.y /*"flip" the color of the cell. */
if black then dir=dir-1 /*if cell was black, turn left. */
else dir=dir+1 /* " " " white, " right. */
if dir==0 then dir=4 /*ant should be facing "west". */
if dir==5 then dir=1 /* " " " " "north". */
select /*ant walks direction it's facing*/
when dir==1 then y=y+1 /*walking north? Then go "up". */
when dir==2 then x=x+1 /* " east? " " "right"*/
when dir==3 then y=y-1 /* " south? " " "down".*/
when dir==4 then x=x-1 /* " west? " " "left".*/
end /*select*/
end /*steps*/
/*───────────────────────────────────────────the ant is finished walking*/
say center(" Langton's ant walked" steps 'steps. ',79,""); say
/*Display Langton's ant's trail. */
do minx =lb to rb /*find leftmost non-blank column.*/
do y=bb to tb /*search row by row for it. */
if @.minx.y then leave minx /*found one, now quit searching. */
end /*y*/
end /*minx*/ /*above code crops left of array.*/
do y=tb to bb by -1; _='' /*display a plane (row) of cells.*/
do x=minx to rb /*process a "row" of cells. */
_=_ || @.x.y /*build a cell row for display. */
end /*x*/
_=translate(_,'#',10) /*color the cells: black | white.*/
if _\='' then say strip(_,'T') /*say line, strip trailing blanks*/
end /*y*/
/*stick a fork in it, we're done.*/

View file

@ -0,0 +1,63 @@
#lang racket
;; contracts allow us to describe expected behaviour of funcitons
(define direction/c (or/c 'u 'r 'l 'd))
(define turn/c (-> direction/c direction/c))
(define grid/c (hash/c integer? (hash/c integer? boolean?)))
(define-struct/contract ant ([d direction/c] [x integer?] [y integer?]))
(define/contract (turn-right dir) turn/c
(case dir ((u) 'r) ((d) 'l) ((r) 'd) ((l) 'u)))
(define/contract (turn-left dir) turn/c
(case dir ((u) 'l) ((d) 'r) ((r) 'u) ((l) 'd)))
(define/contract (move d x y)
(-> direction/c integer? integer? (list/c direction/c integer? integer?))
(list
d
(+ x (case d ((l) -1) ((r) 1) (else 0)))
(+ y (case d ((u) -1) ((d) 1) (else 0)))))
(define/contract (move-ant d a) (-> direction/c ant? ant?)
(apply make-ant (move d (ant-x a) (ant-y a))))
(define/contract (langton a grid) (-> ant? grid/c grid/c)
(let ((ax (ant-x a)) (ay (ant-y a)))
(if (and (<= 1 ax 100) (<= 1 ay 100))
(let* ((grid-row (hash-ref grid ay hash))
(cell-black? (hash-ref grid-row ax #f)))
(langton
(move-ant ((if cell-black? turn-left turn-right) (ant-d a)) a)
(hash-set grid ay (hash-set grid-row ax (not cell-black?)))))
grid)))
(define/contract (show-grid/text grid) (-> grid/c void?)
(for* ; for* allows us to refer to y in rw
((y (in-range 1 101))
(rw (in-value (hash-ref grid y #f)))
#:when rw ; if there is no row, the ant never visisted it
#:when (newline) ; when can be used simply for its side effect
(x (in-range 1 101)))
(case (hash-ref rw x #\?)
((#\?) (display #\space)) ; distingush between "ant-visited white" vs. pure white
((#f) (display #\:)) ; little anty footprints left
((#t) (display #\#)))))
(show-grid/text (langton (make-ant 'u 50 50) (hash)))
(require 2htdp/image)
(define/contract (show-grid/png grid) (-> grid/c image?)
(for*/fold
((scn (empty-scene 408 408)))
((y (in-range 1 101))
(rw (in-value (hash-ref grid y #f)))
#:when rw ; if there is no row, the ant never visisted it
(x (in-range 1 101)))
(case (hash-ref rw x #\?)
((#\?) scn) ; distingush between "ant-visited white" vs. pure white
((#f) (place-image (circle 2 "outline" "gray") (* x 4) (* y 4) scn)) ; little anty footprints left
((#t) (place-image (circle 2 "solid" "black") (* x 4) (* y 4) scn)))))
(show-grid/png (langton (make-ant 'u 50 50) (hash)))

View file

@ -0,0 +1,120 @@
class Ant
Directions = [:north, :east, :south, :west]
def initialize(plane, pos_x, pos_y)
@plane = plane
@position = Position.new(plane, pos_x, pos_y)
@direction = :south
end
attr_reader :plane, :direction, :position
def run
moves = 0
loop do
begin
if $DEBUG and moves % 100 == 0
system "clear"
puts "%5d %s" % [moves, position]
puts plane
end
moves += 1
move
rescue OutOfBoundsException
break
end
end
moves
end
def move
plane.at(position).toggle_colour
position.advance(direction)
if plane.at(position).white?
turn(:right)
else
turn(:left)
end
end
def turn(left_or_right)
idx = Directions.index(direction)
case left_or_right
when :left then @direction = Directions[(idx - 1) % Directions.length]
when :right then @direction = Directions[(idx + 1) % Directions.length]
end
end
end
class Plane
def initialize(x, y)
@x = x
@y = y
@cells = Array.new(y) {Array.new(x) {Cell.new}}
end
attr_reader :x, :y
def at(position)
@cells[position.y][position.x]
end
def to_s
@cells.collect {|row|
row.collect {|cell| cell.white? ? "." : "#"}.join + "\n"
}.join
end
end
class Cell
def initialize
@colour = :white
end
attr_reader :colour
def white?
colour == :white
end
def toggle_colour
@colour = (white? ? :black : :white)
end
end
class Position
def initialize(plane, x, y)
@plane = plane
@x = x
@y = y
check_bounds
end
attr_accessor :x, :y
def advance(direction)
case direction
when :north then @y -= 1
when :east then @x += 1
when :south then @y += 1
when :west then @x -= 1
end
check_bounds
end
def check_bounds
unless (0 <= @x and @x < @plane.x) and (0 <= @y and @y < @plane.y)
raise OutOfBoundsException, to_s
end
end
def to_s
"(%d, %d)" % [x, y]
end
end
class OutOfBoundsException < StandardError; end
#
# the simulation
#
ant = Ant.new(Plane.new(100, 100), 50, 50)
moves = ant.run
puts "out of bounds after #{moves} moves: #{ant.position}"
puts ant.plane

View file

@ -0,0 +1,43 @@
class Langton(matrix:Array[Array[Char]], ant:Ant) {
import Langton._
val rows=matrix.size
val cols=matrix(0).size
def isValid = 0 <= ant.row && ant.row < cols && 0 <= ant.col && ant.col < rows
def isBlack=matrix(ant.row)(ant.col)==BLACK
def changeColor(c:Char)={matrix(ant.row)(ant.col)=c; matrix}
def evolve():Langton={
val (newCol, newAnt)=if(isBlack) (WHITE, ant.turnLeft) else (BLACK, ant.turnRight)
new Langton(changeColor(newCol), newAnt.move)
}
override def toString()=matrix map (_.mkString("")) mkString "\n"
}
case class Ant(row:Int, col:Int, d:Int=0) {
def turnLeft=Ant(row,col,(d-1)&3)
def turnRight=Ant(row,col,(d+1)&3)
def move=d match {
case 0 => Ant(row-1,col,d) // north
case 1 => Ant(row,col+1,d) // east
case 2 => Ant(row+1,col,d) // south
case 3 => Ant(row,col-1,d) // west
}
}
object Langton {
val BLACK='#'
val WHITE='.'
def apply(x:Int=100, y:Int=100)=new Langton(Array.fill(y, x)(WHITE), Ant(x>>>1, y>>>1, 0))
def main(args: Array[String]): Unit = {
var l=Langton(100,100)
var moves=0
while (l.isValid) {
moves += 1
l=l.evolve
}
println("Out of bounds after "+moves+" moves")
println(l)
}
}

View file

@ -0,0 +1,33 @@
package require Tk
proc step {workarea} {
global x y dir
if {[lindex [$workarea get $x $y] 0]} {
$workarea put black -to $x $y
if {[incr dir] > 3} {set dir 0}
} else {
$workarea put white -to $x $y
if {[incr dir -1] < 0} {set dir 3}
}
switch $dir {
0 {incr x}
1 {incr y}
2 {incr x -1}
3 {incr y -1}
}
expr {$x < 0 || $x >= [image width $workarea] || $y < 0 || $y >= [image height $workarea]}
}
image create photo antgrid -width 100 -height 100
pack [label .l -image antgrid]
antgrid put white -to 0 0 99 99
set x [set y 50]
set dir 0
while 1 {
update
if {[step antgrid]} break
}
# Produce output in file
antgrid write ant.gif -format gif