# Project : Koch curve

load "guilib.ring"

paint = null

new qapp
        {
        win1 = new qwidget() {
                  setwindowtitle("Koch curve")
                  setgeometry(100,100,500,600)
                  label1 = new qlabel(win1) {
                              setgeometry(10,10,400,400)
                              settext("")
                  }
                  new qpushbutton(win1) {
                          setgeometry(150,500,100,30)
                          settext("draw")
                          setclickevent("draw()")
                  }
                  show()
        }
        exec()
        }

func draw
        p1 = new qpicture()
               color = new qcolor() {
               setrgb(0,0,255,255)
        }
        pen = new qpen() {
                 setcolor(color)
                 setwidth(1)
        }
        paint = new qpainter() {
                  begin(p1)
                  setpen(pen)

        koch(100, 100, 400, 400, 4)

        endpaint()
        }
        label1 { setpicture(p1) show() }

func koch x1, y1, x2, y2, it

        angle = 60*3.14/180
        x3 = (2*x1+x2)/3
        y3 = (2*y1+y2)/3

        x4 = (x1+2*x2)/3
        y4 = (y1+2*y2)/3

        x = x3 + (x4-x3)*cos(angle)+(y4-y3)*sin(angle)
        y = y3 - (x4-x3)*sin(angle)+(y4-y3)*cos(angle)

       if (it > 0)
          koch(x1, y1, x3, y3, it-1)
          koch(x3, y3, x, y, it-1)
          koch(x, y, x4, y4, it-1)
          koch(x4, y4, x2, y2, it-1)
       else
          paint.drawline(x1, y1, x3, y3)
          paint.drawline(x3, y3, x, y)
          paint.drawline(x, y, x4, y4)
          paint.drawline(x4, y4, x2, y2)
      ok


attr_reader :koch
def settings
  size 600, 600
end

def setup
  sketch_title '2D Koch'
  @koch = KochSnowflake.new
  koch.create_grammar 5
  no_loop
end

def draw
  background 0
  koch.render
end

# LSystem class
class Grammar
  attr_reader :axiom, :rules
  def initialize(axiom, rules)
    @axiom = axiom
    @rules = rules
  end

  def apply_rules(prod)
    prod.gsub(/./) { |token| rules.fetch(token, token) }
  end

  def generate(gen)
    return axiom if gen.zero?

    prod = axiom
    gen.times do
      prod = apply_rules(prod)
    end
    prod
  end
end

Turtle = Struct.new(:x, :y, :theta)

# KochSnowflake class has access to Sketch methods eg :line, :width, :height
class KochSnowflake
  include Processing::Proxy

  attr_reader :grammar, :axiom, :draw_length, :production, :turtle
  DELTA = 60.radians

  def initialize
    @axiom = 'F--F--F' # 'F' for simple Koch Curve
    @grammar = Grammar.new(
      axiom,
      'F' => 'F+F--F+F'
    )
    @draw_length = 20
    stroke 0, 255, 0
    stroke_weight 2
    @turtle = Turtle.new(width / 5, height * 0.7, 0)
  end

  def render
    production.scan(/./) do |element|
      case element
      when 'F' # NB NOT using affine transforms
        draw_line(turtle)
      when '+'
        turtle.theta += DELTA
      when '-'
        turtle.theta -= DELTA
      when 'L', 'R'
      else puts 'Grammar not recognized'
      end
    end
  end

  def draw_line(turtle)
    x_temp = turtle.x
    y_temp = turtle.y
    @turtle.x += draw_length * Math.cos(turtle.theta)
    @turtle.y += draw_length * Math.sin(turtle.theta)
    line(x_temp, y_temp, turtle.x, turtle.y)
  end

  ##############################
  # create grammar from axiom and
  # rules (adjust scale)
  ##############################

  def create_grammar(gen)
    @draw_length *= 0.6**gen
    @production = @grammar.generate gen
  end
end


// [dependencies]
// svg = "0.8.0"

use svg::node::element::path::Data;
use svg::node::element::Path;
use svg::node::element::Rectangle;

const SQRT3_2: f64 = 0.86602540378444;

fn koch_curve(mut data: Data, x0: f64, y0: f64, x1: f64, y1: f64, order: usize) -> Data {
    if order == 0 {
        data = data.line_to((x1, y1));
    } else {
        let dx = x1 - x0;
        let dy = y1 - y0;
        let x2 = x0 + dx / 3.0;
        let y2 = y0 + dy / 3.0;
        let x3 = x0 + dx / 2.0 - dy * SQRT3_2 / 3.0;
        let y3 = y0 + dy / 2.0 + dx * SQRT3_2 / 3.0;
        let x4 = x0 + 2.0 * dx / 3.0;
        let y4 = y0 + 2.0 * dy / 3.0;
        data = koch_curve(data, x0, y0, x2, y2, order - 1);
        data = koch_curve(data, x2, y2, x3, y3, order - 1);
        data = koch_curve(data, x3, y3, x4, y4, order - 1);
        data = koch_curve(data, x4, y4, x1, y1, order - 1);
    }
    data
}

fn write_koch_snowflake(file: &str, size: usize, order: usize) -> std::io::Result<()> {
    let length = (size as f64) * SQRT3_2 * 0.95;
    let x0 = ((size as f64) - length) / 2.0;
    let y0 = (size as f64) / 2.0 - length * SQRT3_2 / 3.0;
    let x1 = x0 + length / 2.0;
    let y1 = y0 + length * SQRT3_2;
    let x2 = x0 + length;

    let mut data = Data::new().move_to((x0, y0));
    data = koch_curve(data, x0, y0, x1, y1, order);
    data = koch_curve(data, x1, y1, x2, y0, order);
    data = koch_curve(data, x2, y0, x0, y0, order);

    let path = Path::new()
        .set("fill", "none")
        .set("stroke", "white")
        .set("stroke-width", "1")
        .set("d", data);

    let rect = Rectangle::new()
        .set("width", "100%")
        .set("height", "100%")
        .set("fill", "black");

    let document = svg::Document::new()
        .set("width", size)
        .set("height", size)
        .add(rect)
        .add(path);

    svg::save(file, &document)
}

fn main() {
    write_koch_snowflake("koch_snowflake.svg", 600, 5).unwrap();
}


var rules = Hash(
    F => 'F+F--F+F',
)

var lsys = LSystem(
    width:  800,
    height: 800,

    xoff: -210,
    yoff: -90,

    len:   8,
    angle: 60,
    color: 'dark green',
)

lsys.execute('F--F--F', 4, "koch_snowflake.png", rules)


import "graphics" for Canvas, Color, Point
import "dome" for Window
import "math" for M

class Game {
    static init() {
        Window.title = "Koch curve"
        Canvas.resize(512, 512)
        Window.resize(512, 512)
        Canvas.cls(Color.white) // white background
        koch(100, 100, 400, 400, 4)
        koch(101, 100, 401, 400, 4) // 2 pixels wide
    }

    static koch(x1, y1, x2, y2, iter) {
        var angle = Num.pi / 3 // 60 degrees
        var x3 = (x1*2 + x2) / 3
        var y3 = (y1*2 + y2) / 3
        var x4 = (x1 + x2*2) / 3
        var y4 = (y1 + y2*2) / 3
        var x5 = x3 + (x4-x3)*M.cos(angle) + (y4-y3)*M.sin(angle)
        var y5 = y3 - (x4-x3)*M.sin(angle) + (y4-y3)*M.cos(angle)
        if (iter > 0) {
            iter = iter - 1
            koch(x1, y1, x3, y3, iter)
            koch(x3, y3, x5, y5, iter)
            koch(x5, y5, x4, y4, iter)
            koch(x4, y4, x2, y2, iter)
        } else {
            Canvas.line(x1, y1, x3, y3, Color.blue)
            Canvas.line(x3, y3, x5, y5, Color.blue)
            Canvas.line(x5, y5, x4, y4, Color.blue)
            Canvas.line(x4, y4, x2, y2, Color.blue)
        }
    }

    static update() {}

    static draw(dt) {}
}


real PosX, PosY, Angle;

proc DrawSide(Depth, Dist);     \Draw side as 4 segments
int Depth;  real Dist;
int I; real Dir;
def Deg2Rad = 3.14159265358979323846/180.;
[Dir:= [0., -60., 120., -60.];
for I:= 0 to 3 do
    [Angle:= Angle + Dir(I);
    if Depth < 4 then DrawSide(Depth+1, Dist/3.)
    else [PosX:= PosX + Dist*Cos(Angle*Deg2Rad);
          PosY:= PosY + Dist*Sin(Angle*Deg2Rad);
          Line(fix(PosX), fix(PosY), $F \BrWhite\);
         ];
    ];
];

int Side;
[SetVid($107);  \set 1280x1024x8 VESA graphic display
PosX:= float(1280/2);  PosY:= 0.;
Move(fix(PosX), fix(PosY));     \set start of Line
Angle:= 60.;                    \heading = 60 degrees
for Side:= 1 to 3 do            \sides of triangle
    [DrawSide(0, 290.);
    Angle:= Angle + 120.;
    ];
]


T.enum Dir
   UP
   RIGHT
   DOWN
   LEFT

-V color_WHITE = Char(‘ ’)
-V color_BLACK = Char(‘#’)

F invert_color(&grid, x, y)
   ‘Invert the color of grid at x, y coordinate.’
   I grid[y][x] == :color_BLACK
      grid[y][x] = :color_WHITE
   E
      grid[y][x] = :color_BLACK

F next_direction(grid, x, y, =direction)
   ‘Compute next direction according to current position and direction.’
   V turn_right = grid[y][x] != :color_BLACK
   V direction_index = Int(direction)
   I turn_right
      direction_index = (direction_index + 1) % 4
   E
      direction_index = (direction_index + 4 - 1) % 4
   V directions = [Dir.UP, Dir.RIGHT, Dir.DOWN, Dir.LEFT]
   direction = directions[direction_index]
   R direction

F next_position(=x, =y, direction)
   ‘Compute next position according to direction.’
   I direction == UP
      y--
   E I direction == RIGHT
      x--
   E I direction == DOWN
      y++
   E I direction == LEFT
      x++
   R (x, y)

F print_grid(grid)
   ‘Display grid.’
   print(80 * ‘#’)
   print(grid.map(row -> row.join(‘’)).join("\n"))

F ant(width, height, max_nb_steps)
   ‘Langton's ant.’
   V grid = [[:color_WHITE] * width] * height
   V x = width I/ 2
   V y = height I/ 2
   V direction = Dir.UP

   V i = 0
   L i < max_nb_steps & x C 0 .< width & y C 0 .< height
      invert_color(&grid, x, y)
      direction = next_direction(grid, x, y, direction)
      (x, y) = next_position(x, y, direction)
      i++

   print_grid(grid)

ant(width' 75, height' 52, max_nb_steps' 12000)


DEFINE DIRN="0"
DEFINE DIRE="1"
DEFINE DIRS="2"
DEFINE DIRW="3"
DEFINE BLACK="1"
DEFINE WHITE="2"
DEFINE MAXX="159"
DEFINE MAXY="95"

BYTE FUNC TurnLeft(BYTE dir)
  IF dir=DIRN THEN
    RETURN (DIRW)
  FI
RETURN (dir-1)

BYTE FUNC TurnRight(BYTE dir)
  IF dir=DIRW THEN
    RETURN (DIRN)
  FI
RETURN (dir+1)

PROC DrawAnt(INT x,y)
  BYTE c,dir

  dir=DIRN

  DO
    c=Locate(x,y)

    IF c=BLACK THEN
      Color=WHITE
      Plot(x,y)
      dir=TurnLeft(dir)
    ELSE
      Color=BLACK
      Plot(x,y)
      dir=TurnRight(dir)
    FI
    IF dir=DIRN THEN
      y==-1
      IF y<0 THEN EXIT FI
    ELSEIF dir=DIRE THEN
      x==+1
      IF X>MAXX THEN EXIT FI
    ELSEIF dir=DIRS THEN
      y==+1
      IF Y>MAXY THEN EXIT FI
    ELSE
      x==-1
      IF x<0 THEN EXIT FI
    FI
  OD
RETURN

PROC Main()
  BYTE CH=$02FC
  BYTE y

  Graphics(7+16)
  SetColor(0,0,2)
  SetColor(1,0,12)
  Color=2
  FOR y=0 TO MAXY
  DO
    Plot(0,y) DrawTo(MAXX,y)
  OD

  DrawAnt(80,48)

  DO UNTIL CH#$FF OD
  CH=$FF
RETURN


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;


BEGIN
    # size of board for Langton's ant #
    INT max board = 100;
    [ 1 : max board, 1 : max board ]CHAR board;
    # start with the board all white #
    CHAR white = " ", black = "#";
    FOR r TO 1 UPB board DO FOR c TO 2 UPB board DO board[ r, c ] := white OD OD;
    # possible ant directions #
    INT head left = 0, head up = 1, head right = 2, head down = 3;
    # returns the new direction if we turn left from curr direction #
    OP LEFT = ( INT curr direction )INT:
       IF   curr direction = head left  THEN head down
       ELIF curr direction = head down  THEN head right
       ELIF curr direction = head right THEN head up
       ELSE                                  head left
       FI ; # LEFT #
    # returns the new direction if we turn right from curr direction #
    OP RIGHT = ( INT curr direction )INT:
       IF   curr direction = head left  THEN head up
       ELIF curr direction = head up    THEN head right
       ELIF curr direction = head right THEN head down
       ELSE                                  head left
       FI ; # RIGHT #
    # move the ant until it leaves the board #
    INT ant row := max board OVER 2;
    INT ant col := max board OVER 2;
    INT ant direction := head up;
    INT max row := 1;
    INT max col := 1;
    INT min row := max board;
    INT min col := max board;
    INT moves := 0;
    WHILE ant row >= 1 LWB board AND ant row <= 1 UPB board
      AND ant col >= 2 LWB board AND ant col <= 2 UPB board
    DO
        moves +:= 1;
        IF ant row > max row THEN max row := ant row FI;
        IF ant col > max col THEN max col := ant col FI;
        IF ant row < min row THEN min row := ant row FI;
        IF ant col < min col THEN min col := ant col FI;
        IF board[ ant row, ant col ] = white THEN
            # ant turns right on a white square #
            ant direction := RIGHT ant direction;
            board[ ant row, ant col ] := black
        ELSE
            # ant turns left on a black square #
            ant direction :=  LEFT ant direction;
            board[ ant row, ant col ] := white
        FI;
        # move the ant #
        IF     ant direction = head up    THEN ant row -:= 1
        ELIF   ant direction = head down  THEN ant row +:= 1
        ELIF   ant direction = head left  THEN ant col -:= 1
        ELSE # ant direction = head right #    ant col +:= 1
        FI
    OD;
    # show resultant position #
    print( ( "After ", whole( moves, 0 ), " moves."
           , " Showing rows ", whole( min row,0 ), " to ", whole( max row, 0 )
           , " columns ", whole( min col,0 ), " to ", whole( max col, 0 )
           , newline
           )
         );
    FOR r FROM min row TO max row DO
        print( ( board[ r, min col : max col ], newline ) )
    OD
END


#NoEnv
SetBatchLines, -1
; Directions
Directions := {0: "North", 1: "East", 2: "South", 3: "West"}
; Initialize the plane (set all cells to white)
White := 0xFFFFFF
Plane := []
PW := PH := 100
loop, % PH {
    I := A_Index
    loop, % PW
        Plane[I, A_Index] := White
}
; Let it run
DI := D := 0 ; initial direction
X := Y := 50 ; initial coordinates
while (X > 0) && (X <= PW) && (Y > 0) && (Y <= PH) {
    D := (D + ((Plane[X, Y] ^= White) ? 1 : 3)) & 3
    if (D & 1)
        X += -(D = 3) + (D = 1)
    else
        Y += -(D = 0) + (D = 2)
}
; Show the result
HBM := CreateDIB(Plane, PW, PH, 400, 400, 0)
Gui, Margin, 0, 0
Gui, Add, Text, x0 y0 w20 h440 Center 0x200, W
Gui, Add, Text, x20 y0 w400 h20 Center 0x200, N
Gui, Add, Picture, x20 y20 w400 h400 0x4E hwndHPIC ; SS_REALSIZECONTROL = 0x40 | SS_BITMAP = 0xE
DllCall("User32.dll\SendMessage", "Ptr", HPIC, "UInt", 0x172, "Ptr", 0, "Ptr", HBM) ; STM_SETIMAGE = 0x172
Gui, Add, Text, xp+5 yp h20 0x200 BackgroundTrans, % "Initial direction: " . Directions[DI]
Gui, Add, Text, x20 y420 w400 h20 Center 0x200, S
Gui, Add, Text, x420 y0 w20 h440 Center 0x200, E
Gui, Show, , Langton's ant (%PW%x%PH%)
Return

GuiClose:
ExitApp

CreateDIB(PixelArray, PAW, PAH, BMW := 0, BMH := 0, Gradient := 1) { ; SKAN, 01-Apr-2014 / array version by just me
    SLL := (PAW * 3) + (PAW & 1)
    VarSetCapacity(BMBITS, SLL * PAH, 0)
    P := &BMBITS
    loop, % PAH {
        R := A_Index
        loop, % PAW
            P := Numput(PixelArray[R, A_Index], P + 0, "UInt") - 1
        P += (PAW & 1)
    }
    HBM := DllCall("Gdi32.dll\CreateBitmap", "Int", PAW, "Int", PAH, "UInt", 1, "UInt", 24, "Ptr", 0, "UPtr")
    HBM := DllCall("User32.dll\CopyImage", "Ptr", HBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
    DllCall( "Gdi32.dll\SetBitmapBits", "Ptr", HBM, "UInt", SLL * PAH, "Ptr", &BMBITS)
    if (!Gradient)
        HBM := DllCall("User32.dll\CopyImage", "Ptr", HBM, "UInt", 0, "Int", 0, "Int", 0, "Int", 8, "UPtr")
    return DllCall("User32.dll\CopyImage", "Ptr", HBM, "UInt", 0, "Int", BMW, "Int", BMH, "UInt", 0x200C, "UPtr")
} ; http://ahkscript.org/boards/viewtopic.php?f=6&t=3203


Global $iCountMax = 100000
Global $aFields[100][100][2]
Global $iDelayStep = 10  ; stop between steps in msec

Global $aDirection[4][4] = [ _ ; [ direction 0-3 ][ left change x, y, right change x, y ]
[-1,  0, +1,  0], _   ; == direction 0
[ 0, -1,  0, +1], _   ; == direction 1
[+1,  0, -1,  0], _   ; == direction 2
[ 0, +1,  0, -1]]     ; == direction 3

Global $hGui = GUICreate("Langton's ant", 100*8, 100*8)
GUISetBkColor(0xFFFFFF)

For $i = 0 To 99
	For $j = 0 To 99
		$aFields[$i][$j][0] = GUICtrlCreateLabel('', $j*8, $i*8)
		GUICtrlSetColor(-1, 0xFF0000)
		$aFields[$i][$j][1] = 0
	Next
Next

GUISetState()

GUICtrlSetData($aFields[49][49][0], '#')

Do
	Sleep($iDelayStep)
Until Not _SetAnt()

Do
Until GUIGetMsg() = -3

Func _SetAnt()
	Local Static $iRowLast = 49, $iColLast = 49, $iCount = 0
	Local Static $aCol[2] = [0xFFFFFF,0x000000], $iDirection = 0
	Local $iRow, $iCol, $fRight = False
	If $iCount = $iCountMax Then Return 0

	; == get current color
	Local $iLastColor = $aFields[$iRowLast][$iColLast][1]

	; == go to left/right
	If $iLastColor = 0 Then $fRight = True

	; == set the ant to the next field
	Local $indexX = 0, $indexY = 1
	If $fRight Then
		$indexX = 2
		$indexY = 3
	EndIf
	$iRow = $iRowLast + ($aDirection[$iDirection][$indexX])
	$iCol = $iColLast + ($aDirection[$iDirection][$indexY])
	If $iRow < 0 Or $iRow > 99 Or $iCol < 0 Or $iCol > 99 Then Return 0
	GUICtrlSetData($aFields[$iRowLast][$iColLast][0], '')
	GUICtrlSetData($aFields[$iRow][$iCol][0], '#')

	; == direction for next step
	If $fRight Then
		$iDirection += 1
		If $iDirection = 4 Then $iDirection = 0
	Else
		$iDirection -= 1
		If $iDirection = -1 Then $iDirection = 3
	EndIf

	; == change the color of the current field
	GUICtrlSetBkColor($aFields[$iRowLast][$iColLast][0], $aCol[(Not $iLastColor)*1])
	$aFields[$iRowLast][$iColLast][1] = (Not $iLastColor)*1

	$iRowLast = $iRow
	$iColLast = $iCol
	$iCount += 1
	WinSetTitle($hGui, '', "Langton's ant      [ step: " & StringFormat('%06d', $iCount) & " ]")
	Return 1
EndFunc  ;==>_SetAnt


# usage: awk  -v debug=0  -f langton.awk

# Simulates the cellular automaton "Langton's ant",
# see http://en.wikipedia.org/wiki/Langton%27s_ant

function turnRight() {
	dir++
	if( dir>4 ) { dir=1 }
}
function turnLeft() {
	dir--
	if( dir<1 ) { dir=4 }
}
function move() {
	if (dir==1) { y--; z="^" }
	if (dir==3) { y++; z="v" }

	if (dir==2) { x++; z=">" }
	if (dir==4) { x--; z="<" }
}

function ant() {
	if( debug )  AntStat() 				##

	if( grid[x,y]==0 ) { turnLeft() } else { turnRight() }
	if( grid[x,y]==0 ) { color=1    } else { color=0 }

	if( debug )  print( "# action", color, dir, z )	##

	grid[x,y] = color
	move()
}

###

function AntStat() {
	printf( "Move# %d : Ant @ x=%d y=%d dir=%d %s  color=%d\n",
		 moveNr, x,y, dir,z, grid[x,y] )
}
function dumpGrid() {
	AntStat()

	printf( "Grid:" )
	for(xx=1; xx<=limit/10; xx++) {
		printf( "....+....%s", xx )
	}
	printf "\n"

	cSum=0
	for(yy=1; yy <= limit; yy++) {
		printf( "%4d:",yy )
		for(xx=1; xx <= limit; xx++) {
			c = grid[xx,yy]
			if( c ) cSum++
	c1++
	c2+=grid[xx,yy]
			if( (xx==x)&&(yy==y) ) 	{ c=z } 	# Ant
			printf( c )
		}
		printf( "\n" )
	}
	printf( "Cells: %d  'black' cells: %d  Moves: %d\n\n", limit*limit, cSum, moveNr )
}

BEGIN {
	  print( "Langton's ant\n" )

	  limit  = 72
	  for(x=1; x <= limit; x++) {
		for(y=1; y <= limit; y++) {
			grid[x,y] = 0
		}
	  }

	  moveNr =   0
	  x      =  36
	  y      =  28
	  dir    =   1	# 1=up/north 2=right/east 3=down/south 4=left/west
	  z      = "!"

	  while( moveNr < 11200 ) {
		moveNr++
 		ant()
		if(x<0 || x>limit) break
		if(y<0 || y>limit) break

		# Snapshots:
		if (moveNr==163 || moveNr==1297 || moveNr==10095 ) dumpGrid()
		if (y<=5 ) break
	  }
	  dumpGrid()
}
END	{ print("END.") }


      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


define o() {
    auto i, j

    "P1 "
    w
    h
    for (j = 0; j < h; j++) {
        for (i = 0; i < w; i++) {
            a[j * w + i]
        }
    }
}

define l(w, h, x, y) {
    auto a[], d, i, x[], y[]

    /* d represents one of the four possible directions:
     *             0
     *             ⇑
     *           3⇐ ⇒1
     *             ⇓
     *             2
     * The arrays x[] and y[] contain the changes to the x and y direction for
     * each value of d.
     */
    x[1] = 1
    x[3] = -1
    y[0] = -1
    y[2] = 1

    while (1) {
        i = y * w + x
        if (a[i] == 0) d += 1   /* turn right if white */
        if (a[i] == 1) d -= 1   /* turn left if black */
        if (d < 0) d = 3
        if (d > 3) d = 0
        x += x[d]
        y += y[d]
        a[i] = 1 - a[i]         /* toggle cell colour */
        if (x < 0) break
        if (x == w) break
        if (y < 0) break
        if (y == h) break
    }

    o()
}

l(100, 100, 50, 50)
quit


Rot ← ¬⊸{-⌾(𝕨⊸⊑)⌽𝕩}
Fmt ← ⊏⟜" #"
_while_ ← {𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}

Ant ← 2⊑{ # Generator Block
  p‿d‿g:
  r ← d Rot˜ p⊑g
  ⟨
    p + r
    r
    ¬⌾(p⊸⊑)g
  ⟩
} _while_ {   # Condition Block
  p‿d‿g:
  ∧´(p≥0‿0)∧p<≢g
}

•Show Fmt Ant ⟨50‿50, 0‿1, 100‿100⥊0⟩


#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[[email protected]\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;
}


using System;

namespace LangtonAnt
{
    public struct Point
    {
        public int X;
        public int Y;

        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }

    enum Direction
    {
        North, East, West, South
    }

    public class Langton
    {
        public readonly bool [,] IsBlack;
        private Point _origin;
        private Point _antPosition = new Point(0, 0);
        public bool OutOfBounds { get; set;}

        // I don't see any mention of what direction the ant is supposed to start out in
        private Direction _antDirection = Direction.East;

        private readonly Direction[] _leftTurn = new[] { Direction.West, Direction.North, Direction.South, Direction.East };
        private readonly Direction[] _rightTurn = new[] { Direction.East, Direction.South, Direction.North, Direction.West };
        private readonly int[] _xInc = new[] { 0, 1,-1, 0};
        private readonly int[] _yInc = new[] {-1, 0, 0, 1};

        public Langton(int width, int height, Point origin)
        {
            _origin = origin;
            IsBlack = new bool[width, height];
            OutOfBounds = false;
        }

        public Langton(int width, int height) : this(width, height, new Point(width / 2, height / 2)) {}

        private void MoveAnt()
        {
            _antPosition.X += _xInc[(int)_antDirection];
            _antPosition.Y += _yInc[(int)_antDirection];
        }

        public Point Step()
        {
            if (OutOfBounds)
            {
                throw new InvalidOperationException("Trying to step after ant is out of bounds");
            }
            Point ptCur = new Point(_antPosition.X + _origin.X, _antPosition.Y + _origin.Y);
            bool leftTurn = IsBlack[ptCur.X, ptCur.Y];
            int iDirection = (int) _antDirection;
            _antDirection = leftTurn ? _leftTurn[iDirection] : _rightTurn[iDirection];
            IsBlack[ptCur.X, ptCur.Y] = !IsBlack[ptCur.X, ptCur.Y];
            MoveAnt();
            ptCur = new Point(_antPosition.X + _origin.X, _antPosition.Y + _origin.Y);
            OutOfBounds =
                ptCur.X < 0 ||
                ptCur.X >= IsBlack.GetUpperBound(0) ||
                ptCur.Y < 0 ||
                ptCur.Y >= IsBlack.GetUpperBound(1);
            return _antPosition;
        }
    }
    class Program
    {
        static void Main()
        {
            Langton ant = new Langton(100, 100);

            while (!ant.OutOfBounds) ant.Step();

            for (int iRow = 0; iRow < 100; iRow++)
            {
                for (int iCol = 0; iCol < 100; iCol++)
                {
                    Console.Write(ant.IsBlack[iCol, iRow] ? "#" : " ");
                }
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }
}


#include <windows.h>
#include <string>

//--------------------------------------------------------------------------------------------------
using namespace std;

//--------------------------------------------------------------------------------------------------
const int BMP_SIZE = 600, CELL_SIZE = 4, GRID_SIZE = BMP_SIZE / CELL_SIZE;
const bool INFINIT_RUN = false;

enum cellState { WHITE, BLACK, ANT };
enum facing { NOR, EAS, SOU, WES };
enum state { RUNNING, RESTING };

//--------------------------------------------------------------------------------------------------
class myBitmap
{
public:
    myBitmap() : pen( NULL ) {}
    ~myBitmap()
    {
	DeleteObject( pen );
	DeleteDC( hdc );
	DeleteObject( bmp );
    }

    bool create( int w, int h )
    {
	BITMAPINFO	bi;
	ZeroMemory( &bi, sizeof( bi ) );

	bi.bmiHeader.biSize	   = sizeof( bi.bmiHeader );
	bi.bmiHeader.biBitCount	   = sizeof( DWORD ) * 8;
	bi.bmiHeader.biCompression = BI_RGB;
	bi.bmiHeader.biPlanes	   = 1;
	bi.bmiHeader.biWidth	   =  w;
	bi.bmiHeader.biHeight	   = -h;

	HDC dc = GetDC( GetConsoleWindow() );
	bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
	if( !bmp ) return false;

	hdc = CreateCompatibleDC( dc );
	SelectObject( hdc, bmp );
	ReleaseDC( GetConsoleWindow(), dc );

	width = w; height = h;

	return true;
    }

    void clear()
    {
	ZeroMemory( pBits, width * height * sizeof( DWORD ) );
    }

    void setPenColor( DWORD clr )
    {
	if( pen ) DeleteObject( pen );
	pen = CreatePen( PS_SOLID, 1, clr );
	SelectObject( hdc, pen );
    }

    void saveBitmap( string path )
    {
	BITMAPFILEHEADER fileheader;
	BITMAPINFO	 infoheader;
	BITMAP		 bitmap;
	DWORD		 wb;

	GetObject( bmp, sizeof( bitmap ), &bitmap );

	DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
	ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
	ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
	ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );

	infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
	infoheader.bmiHeader.biCompression = BI_RGB;
	infoheader.bmiHeader.biPlanes = 1;
	infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
	infoheader.bmiHeader.biHeight = bitmap.bmHeight;
	infoheader.bmiHeader.biWidth = bitmap.bmWidth;
	infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );

	fileheader.bfType    = 0x4D42;
	fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
	fileheader.bfSize    = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;

	GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );

	HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
	WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
	WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
	WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
	CloseHandle( file );

	delete [] dwpBits;
    }

    HDC getDC() const     { return hdc; }
    int getWidth() const  { return width; }
    int getHeight() const { return height; }

private:
    HBITMAP bmp;
    HDC	    hdc;
    HPEN    pen;
    void   *pBits;
    int	    width, height;
};
//--------------------------------------------------------------------------------------------------
class Ant
{
public:
    Ant()
    {
	_bmp.create( BMP_SIZE, BMP_SIZE );
	ZeroMemory( _grid, sizeof( _grid ) );
	RED_BRUSH = CreateSolidBrush( 255 );
	_antState = RUNNING;
    }

    ~Ant()
    {
	DeleteObject( RED_BRUSH );
    }

    void setPosition( int x, int y )
    {
	_sx = x; _sy = y;
	_facing = WES;
    }

    void mainLoop()
    {
	switch( _antState )
	{
	    case RUNNING:
	        simulate();
		// fall thru
	    case RESTING:
		display();
	}
    }

    void setHWND( HWND hwnd ) { _hwnd = hwnd; }

private:
    void simulate()
    {
	switch( _grid[_sx][_sy] )
	{
	    case BLACK:
		_grid[_sx][_sy] = WHITE;
		if( --_facing < NOR ) _facing = WES;
	    break;
	    case WHITE:
		_grid[_sx][_sy] = BLACK;
		if( ++_facing > WES ) _facing = NOR;
	}
	switch( _facing )
	{
	    case NOR:
		if( --_sy < 0 )
		{
		    if( INFINIT_RUN ) _sy = GRID_SIZE - 1;
		    else _antState = RESTING;
		}
	    break;
	    case EAS:
		if( ++_sx >= GRID_SIZE )
		{
		    if( INFINIT_RUN ) _sx = 0;
		    else _antState = RESTING;
		}
	    break;
	    case SOU:
		if( ++_sy >= GRID_SIZE )
		{
		    if( INFINIT_RUN ) _sy = 0;
		    else _antState = RESTING;
		}
	    break;
	    case WES:
	        if( --_sx < 0 )
		{
		    if( INFINIT_RUN ) _sx = GRID_SIZE - 1;
		    else _antState = RESTING;
		}
	}
    }

    void display()
    {
        _bmp.clear();

        HBRUSH br; RECT rc;
        int xx, yy; HDC dc = _bmp.getDC();

        for( int y = 0; y < GRID_SIZE; y++ )
	    for( int x = 0; x < GRID_SIZE; x++ )
	    {
	        switch( _grid[x][y] )
	        {
		    case BLACK: br = static_cast<HBRUSH>( GetStockObject( BLACK_BRUSH ) ); break;
		    case WHITE: br = static_cast<HBRUSH>( GetStockObject( WHITE_BRUSH ) );
	        }
	        if( x == _sx && y == _sy ) br = RED_BRUSH;

	        xx = x * CELL_SIZE; yy = y * CELL_SIZE;
	        SetRect( &rc, xx, yy, xx + CELL_SIZE, yy + CELL_SIZE );
	        FillRect( dc, &rc, br );
	    }

        HDC wdc = GetDC( _hwnd );
        BitBlt( wdc, 0, 0, BMP_SIZE, BMP_SIZE, dc, 0, 0, SRCCOPY );
        ReleaseDC( _hwnd, wdc );
    }

    myBitmap _bmp;
    HWND     _hwnd;
    HBRUSH   RED_BRUSH;
    BYTE     _grid[GRID_SIZE][GRID_SIZE];
    int      _sx, _sy, _facing;
    state    _antState;
};
//--------------------------------------------------------------------------------------------------
class wnd
{
public:
    int wnd::Run( HINSTANCE hInst )
    {
	_hInst = hInst;
	_hwnd = InitAll();

	_ant.setHWND( _hwnd );
	_ant.setPosition( GRID_SIZE / 2, GRID_SIZE / 2 );

	ShowWindow( _hwnd, SW_SHOW );
	UpdateWindow( _hwnd );

	MSG msg;
	ZeroMemory( &msg, sizeof( msg ) );
	while( msg.message != WM_QUIT )
	{
	    if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) != 0 )
	    {
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	    }
	    else
	    {
		_ant.mainLoop();
	    }
	}
	return UnregisterClass( "_LANGTONS_ANT_", _hInst );
    }
private:
    static int WINAPI wnd::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
    {
	switch( msg )
	{
	    case WM_DESTROY: PostQuitMessage( 0 ); break;
	    default:
		return DefWindowProc( hWnd, msg, wParam, lParam );
	}
	return 0;
    }

    HWND InitAll()
    {
	WNDCLASSEX wcex;
	ZeroMemory( &wcex, sizeof( wcex ) );
	wcex.cbSize	       = sizeof( WNDCLASSEX );
	wcex.style	       = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc   = ( WNDPROC )WndProc;
	wcex.hInstance     = _hInst;
	wcex.hCursor       = LoadCursor( NULL, IDC_ARROW );
	wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
	wcex.lpszClassName = "_LANGTONS_ANT_";

	RegisterClassEx( &wcex );

	return CreateWindow( "_LANGTONS_ANT_", ".: Langton's Ant -- PJorente :.", WS_SYSMENU, CW_USEDEFAULT, 0, BMP_SIZE, BMP_SIZE, NULL, NULL, _hInst, NULL );
    }

    HINSTANCE _hInst;
    HWND      _hwnd;
    Ant       _ant;
};
//--------------------------------------------------------------------------------------------------
int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
    wnd myWnd;
    return myWnd.Run( hInstance );
}
//--------------------------------------------------------------------------------------------------


config const gridHeight: int = 100;
config const gridWidth: int = 100;

class PBMWriter {
  var imgDomain: domain(2);
  var imgData: [imgDomain] int;

  proc PBMWriter( height: int, width: int ){
    imgDomain = { 1..#height, 1..#width };
  }

  proc this( i : int, j : int) ref : int{
    return this.imgData[ i, j ];
  }

  proc writeImage( fileName: string ){
    var file = open(fileName, iomode.cw);
    var writingChannel = file.writer();
    writingChannel.write("P1\n", imgDomain.dim(1).size, " " ,imgDomain.dim(2).size,"\n");

    for px in imgData {
      writingChannel.write( px, " " );
    }

    writingChannel.write( "\n" );
    writingChannel.flush();
    writingChannel.close();
  }

}

enum Color { white, black };

inline proc nextDirection( position: 2*int, turnLeft: bool ): 2*int {
  return ( (if turnLeft then 1 else -1 ) * position[2], (if turnLeft then -1 else 1 ) * position[1] );
}

proc <( left: 2*int, right: 2*int ){
  return left[1] < right[1] && left[2] < right[2];
}

proc <=( left: 2*int, right: 2*int ){
  return left[1] <= right[1] && left[2] <= right[2];
}

proc main{
  const gridDomain: domain(2) = {1..#gridHeight, 1..#gridWidth};
  var grid: [gridDomain] Color;

  var antPos = ( gridHeight / 2, gridWidth / 2 );
  var antDir = (1,0); // start up;

  while (0,0) < antPos && antPos <= (gridHeight, gridWidth ) {
    var currColor = grid[ antPos ];
    grid[antPos] = if currColor == Color.white then Color.black else Color.white ;

    antDir = nextDirection( antDir, currColor == Color.black );
    antPos = antPos + antDir;
  }

  var image = new PBMWriter( height = gridHeight, width = gridWidth );

  for (i, j) in gridDomain {
    image[i,j] = if grid[gridHeight-j+1,gridHeight-i+1] == Color.black then 0 else 1;
  }

  image.writeImage( "output.png" );
}


(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))))))))


       IDENTIFICATION DIVISION.
       PROGRAM-ID. langtons-ant.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       78  Grid-Size               VALUE 100.
       01  grid-area.
           03  grid-x              OCCURS Grid-Size TIMES.
               05  grid-y          OCCURS Grid-Size TIMES.
                   07  cell-colour PIC X VALUE "W".
                       88  black   VALUE "B".
                       88  white   VALUE "W".

       01  ant-x                   PIC 999.
       01  ant-y                   PIC 999.

       01  ant-direction           PIC 9.
           88  upward              VALUE 0.
           88  rightward           VALUE 1.
           88  downward            VALUE 2.
           88  leftward            VALUE 3.

       78  Pause-Time-Ns           VALUE 10000000.

       01  display-y               PIC 999.

       78  Black-Background        VALUE 0.
       78  White-Background        VALUE 7.

       01  i                       PIC 999.
       01  j                       PIC 999.

       01  pause                   PIC X.

       PROCEDURE DIVISION.
       main-line.
           DIVIDE Grid-Size BY 2 GIVING ant-x, ant-y

           PERFORM display-initial-grid
           PERFORM UNTIL (ant-x = Grid-Size OR 0)
                   OR (ant-y = Grid-Size OR 0)
               PERFORM step-simulation
               CALL "CBL_OC_NANOSLEEP" USING Pause-Time-Ns
           END-PERFORM

           DISPLAY "Press enter to quit." AT LINE 1 COLUMN 1
           ACCEPT pause

           GOBACK
           .
       step-simulation.
           IF black (ant-x, ant-y)
               SET white (ant-x, ant-y) TO TRUE
               PERFORM display-ant-cell
               COMPUTE ant-direction =
                   FUNCTION MOD(ant-direction + 1, 4)
           ELSE
               SET black (ant-x, ant-y) TO TRUE
               PERFORM display-ant-cell
               COMPUTE ant-direction =
                   FUNCTION MOD(ant-direction - 1, 4)
           END-IF

           EVALUATE TRUE
               WHEN upward
                   ADD 1 TO ant-y
               WHEN rightward
                   ADD 1 TO ant-x
               WHEN downward
                   SUBTRACT 1 FROM ant-y
               WHEN leftward
                   SUBTRACT 1 FROM ant-x
           END-EVALUATE
           .
       display-ant-cell.
               SUBTRACT ant-y FROM Grid-Size GIVING display-y
               IF black (ant-x, ant-y)
                   DISPLAY SPACE AT LINE display-y COLUMN ant-x
                       WITH BACKGROUND-COLOR Black-Background
               ELSE
                   DISPLAY SPACE AT LINE display-y COLUMN ant-x
                      WITH BACKGROUND-COLOR White-Background
               END-IF
               .
       display-initial-grid.
           PERFORM VARYING i FROM 1 BY 1 UNTIL i > Grid-Size
                   AFTER j FROM 1 BY 1 UNTIL j > Grid-Size
               DISPLAY SPACE AT LINE i COLUMN j
                   WITH BACKGROUND-COLOR White-Background
           END-PERFORM
           .


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()


(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)))


void main() @safe {
    import std.stdio, std.traits;

    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;
    Color[width][height] M;
    auto dir = Direction.up;

    with (Color)
        for (int i = 0; i < maxSteps && x < width && y < height; i++) {
            immutable turn = M[y][x] == black;
            dir = [EnumMembers!Direction][(dir + (turn ? 1 : -1)) & 3];
            M[y][x] = (M[y][x] == black) ? white : black;
            final switch(dir) with (Direction) {
                case up:    y--; break;
                case right: x--; break;
                case down:  y++; break;
                case left:  x++; break;
            }
        }

    writefln("%(%-(%c%)\n%)", M);
}


let xInc = [0, 1, -1, 0]
let yInc = [-1, 0, 0, 1]
let north = 0
let east = 1
let west = 2
let south = 3

let leftTurns  = [ west, north, south, east ]
let rightTurns = [ east, south, north, west ]

func move(ant) {
    ant.position.x += xInc[ant.direction]
    ant.position.y += yInc[ant.direction]
}

func Array.Step(ant) {
    var ptCur = (var x: ant.position.x + ant.origin.x, var y: ant.position.y + ant.origin.y)
    var leftTurn = this[ptCur.x][ptCur.y]
    ant.direction =
        if leftTurn  {
            leftTurns[ant.direction]
        } else {
            rightTurns[ant.direction]
        }
    this[ptCur.x][ptCur.y] = !this[ptCur.x][ptCur.y]
    move(ant)
    ptCur = (x: ant.position.x + ant.origin.x, y: ant.position.y + ant.origin.y)
    ant.outOfBounds =
        ptCur.x < 0 ||
        ptCur.x >= ant.width ||
        ptCur.y < 0 ||
        ptCur.y >= ant.height
    ant.position
}

func newAnt(width, height) {
    (
        var position: (var x: 0, var y: 0),
        var origin: (x: width / 2, y: height / 2),
        var outOfBounds: false,
        var isBlack: [],
        var direction: east,
        var width: width,
        var height: height
    )
}

func run() {
    let w = 100
    let h = 100
    let blacks = Array.Empty(w, () => Array.Empty(h, false))
    let ant = newAnt(w, h)

    while !ant.outOfBounds {
        blacks.Step(ant)
    }

    var iRow = 0;

    while iRow < w {
        var iCol = 0;
        var ln = ""
        while iCol < h {
            ln += if blacks[iCol][iRow] {
                "#"
            } else {
                " "
            }
            iCol += 1
        }
        print(ln)
        iRow += 1
    }
}

run()


len f[] 100 * 100
func show . .
  for y range 100
    for x range 100
      if f[y * 100 + x] = 1
        move x y
        rect 1 1
      .
    .
  .
.
func run x y dir . .
  dx[] = [ 0 1 0 -1 ]
  dy[] = [ -1 0 1 0 ]
  while x >= 0 and x < 100 and y >= 0 and y < 100
    v = f[y * 100 + x]
    f[y * 100 + x] = 1 - v
    dir = (dir + 1 + 2 * v) mod 4
    x += dx[dir]
    y += dy[dir]
  .
.
call run 70 40 0
call show


(lib 'plot)
(lib 'types)

(define (move iter x dir constant: plane turns cmax  width  xmax (cidx 0))
	(while (> iter 0)
	;; get color index of current square
	(set! cidx (vector-ref plane x))

	;; turn
	(if (vector-ref turns cidx)
		(set! dir (if (= dir 3) 0 (1+ dir))) ;; right is #t
		(set! dir (if (= dir 0) 3 (1- dir))))

	;; rotate colors
	(set! cidx (if (= cidx cmax) 0 (1+ cidx)))
	(vector-set! plane x cidx)

	;; move
	;; x = v + h*width for a pixel at (h,v)
	(set! x
		(cond
			((= dir 0) (1+ x))
			((= dir 1) (+ x width))
			((= dir 2) (1- x))
			((= dir 3) (- x width))))

	(when (or (< x 0) (>= x xmax)) (set! iter -666)) ;; out of bounds
	(set! iter (1- iter)))
	iter)

;; a color table of 16 colors
(define colors
   (list 0 (rgb 1 1 1) (rgb 1 0 0) (rgb 0 1 0) (rgb 0 0 1) (rgb 1 1 0) (rgb 1 0 1) (rgb 0 1 1)))
(define colors (list->vector (append colors colors)))

;; transform color index into rgb color, using colors table.
(define (colorize plane xmax)
	(for ((x xmax))
		(vector-set! plane x (vector-ref colors (vector-ref plane x))))
	(vector->pixels plane)
	xmax )

;; ant's patterns
(define turns #(#t #t #f #f #f #t #f #f #f #t #t #t))   ;; RRLLLRLLLRRR
;;(define turns #(#t #t #f #f #f #t #t #f)) ; RRLLLRRL
;;(define turns #(#t #f)) ; RL : basic ant

(define  (ant (iter 100000))
	(plot-clear)
	(define width (first (pixels-dim))) ;; plane dimensions
	(define height (rest (pixels-dim)))
	(define plane (pixels->uint32-vector))
	(define x (+ (quotient width 2) (* width (quotient height 2)))) ;; middle of plane
	(define xmax (* width height))

	(move iter  x 0 plane turns (1- (vector-length turns)) width xmax)
	(colorize plane xmax))

(ant) ;; run


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


defmodule Langtons do
  def ant(sizex, sizey) do
    {px, py} = {div(sizex,2), div(sizey,2)}     # start position
    move(MapSet.new, sizex, sizey, px, py, {1,0}, 0)
  end

  defp move(plane, sx, sy, px, py, _, step) when px<0 or sx<px or py<0 or sy<py, do:
    print(plane, sx, sy, px, py, step)
  defp move(plane, sx, sy, px, py, dir, step) do
    {plane2, {dx,dy}} = if {px,py} in plane,
                          do:   {MapSet.delete(plane, {px,py}), turn_right(dir)},
                          else: {MapSet.put(plane, {px,py}), turn_left(dir)}
    move(plane2, sx, sy, px+dx, py+dy, {dx,dy}, step+1)
  end

  defp turn_right({dx, dy}), do: {dy, -dx}
  defp turn_left({dx, dy}), do: {-dy, dx}

  defp print(plane, sx, sy, px, py, step) do
    IO.puts "out of bounds after #{step} moves: (#{px}, #{py})"
    Enum.each(0..sy, fn j ->
      IO.puts Enum.map(0..sx, fn i -> if {i,j} in plane, do: "#", else: "." end)
    end)
  end
end

Langtons.ant(100, 100)


import Maybe as M
import Matrix
import Time exposing (Time, every, second)
import List exposing (..)
import String exposing (join)
import Html exposing (div, h1, text)
import Html.App exposing (program)
import Svg
import Svg.Attributes exposing (version, viewBox, cx, cy, r, x, y, x1, y1, x2, y2, fill,style, width, height, preserveAspectRatio)

w = 700
h = 700
dt = 0.0001

type Direction = North | West | South | East

type alias Model =
  { rows : Int
  , cols : Int
  , boxes : Matrix.Matrix Bool
  , location : Matrix.Location
  , direction : Direction
  }

initModel : Int -> Int -> Model
initModel cols rows =
     { rows = rows
     , cols = cols
     , boxes = Matrix.matrix rows cols (\location -> False)
     , location = (rows//2,cols//2)
     , direction = North
     }

view model =
  let
    borderLineStyle = style "stroke:black;stroke-width:0.3"

    x1Min = x1 <| toString 0
    y1Min = y1 <| toString 0
    x1Max = x1 <| toString model.cols
    y1Max = y1 <| toString model.rows
    x2Min = x2 <| toString 0
    y2Min = y2 <| toString 0
    x2Max = x2 <| toString model.cols
    y2Max = y2 <| toString model.rows

    borders = [ Svg.line [ x1Min, y1Min, x2Max, y2Min, borderLineStyle ] []
              , Svg.line [ x1Max, y1Min, x2Max, y2Max, borderLineStyle ] []
              , Svg.line [ x1Max, y1Max, x2Min, y2Max, borderLineStyle ] []
              , Svg.line [ x1Min, y1Max, x2Min, y2Min, borderLineStyle ] []
              ]

    circleInBox (row,col) color =
      Svg.circle [ r "0.25"
      , fill (color)
      , cx (toString (toFloat col + 0.5))
      , cy (toString (toFloat row + 0.5))
      ] []

    showUnvisited location box =
       if box then [circleInBox location "black" ]
              else []

    unvisited = model.boxes
                  |> Matrix.mapWithLocation showUnvisited
                  |> Matrix.flatten
                  |> concat

    maze = [ Svg.g [] <| borders ++ unvisited ]

  in
      div
          []
          [ h1 [] [text "Langton's Ant"]
          , Svg.svg
              [ version "1.1"
              , width (toString w)
              , height (toString h)
              , viewBox (join " "
                           [ 0          |> toString
                           , 0          |> toString
                           , model.cols |> toString
                           , model.rows |> toString ])
              ]
              maze
          ]

updateModel : Model -> Model
updateModel model =
      let current = model.location
          inBox =    snd current >= 0 && snd current < model.cols
                  && fst current >= 0 && fst current < model.rows
      in if not inBox then
           model
         else
           let currentValue = Matrix.get current model.boxes |> M.withDefault False

               dir = case (model.direction, currentValue) of
                       (North, True) -> East
                       (East, True) -> South
                       (South, True) -> West
                       (West, True) -> North

                       (North, False) -> West
                       (East, False) -> North
                       (South, False) -> East
                       (West, False) -> South

               next = case dir of
                        North -> (fst current+1, snd current)
                        South -> (fst current-1, snd current)
                        East -> (fst current, snd current+1)
                        West -> (fst current, snd current-1)

               boxes = Matrix.set current (not currentValue) model.boxes

           in {model | boxes=boxes, location=next, direction=dir}

type Msg = Tick Time

subscriptions model = every (dt * second) Tick

main =
  let
    update msg model = (updateModel model, Cmd.none)
    init = (initModel 100 100 , Cmd.none)
  in program
       { init = init
       , view = view
       , update = update
       , subscriptions = subscriptions
       }


-module( langtons_ant ).

-export( [task/0] ).

-record( neighbour, {north, south, east, west} ).
-record( state, {colour=white, controller, max_x, max_y, neighbour, position} ).

task() ->
       Controller = erlang:self(),
       Max_x = Max_y = 100,
       Pid_positions = plane_create( Controller, Max_x, Max_y ),
       Pids = [X || {X, _} <- Pid_positions],
       [X ! {pid_positions, Pid_positions} || X <- Pids],
       {Pid, _Position} = lists:keyfind( {Max_x div 2, Max_y div 2}, 2, Pid_positions ),
       Pid ! {ant_start, north, Controller},
       receive
       {ant_arrives, _Pid} -> ok
       end,
       display( Controller, Max_x, Max_y, Pids ),
       [X ! {stop, Controller} || X <- Pids].

display( Controller, Max_x, Max_y, Pids ) ->
        Positions_colours = display_positions_colours( Pids, Controller ),
        All_lines = [display_line( Max_x, Positions_colours, Y ) || Y <- lists:seq(Max_y, 1, -1)],
        Lines_with_black = [X || X <- All_lines, lists:member(black, X)],
        [io:fwrite( "~s~n", [[display_on_screen(X) || X <- Lines]] ) || Lines <- Lines_with_black].

display_line( Max_x, Positions_colours, Y ) -> [proplists:get_value({X,Y}, Positions_colours, white) || X <- lists:seq(1, Max_x)].

display_on_screen( white ) -> $_;
display_on_screen( black ) -> $#.

display_positions_colours( Pids, Controller ) ->
        [X ! {position_colour, Controller} || X <- Pids],
        [display_positions_colours_receive() || _X <- Pids].

display_positions_colours_receive( ) ->
        receive
        {position_colour, Position, Colour} -> {Position, Colour}
        end.

loop( State ) ->
    receive
    {pid_positions, Pid_positions} ->
        {_My_position, Neighbour} = lists:foldl( fun loop_neighbour/2, {State#state.position, #neighbour{}}, Pid_positions ),
        erlang:garbage_collect(), % Shrink process after using large Pid_positions. For memory starved systems.
        loop( State#state{neighbour=Neighbour} );
    {ant_start, Direction, Controller} when Controller =:= State#state.controller ->
                {Pid, New_state} = loop_ant_departs( Direction, State ),
                Pid ! {ant_arrives, erlang:self()},
                loop( New_state );
    {ant_arrives, From} ->
                {Direction, New_state} = loop_ant_arrives( From, State ),
                {To, Newest_state} = loop_ant_departs( Direction, New_state ),
                To ! {ant_arrives, erlang:self()},
                loop( Newest_state );
    {position_colour, Controller} when Controller =:= State#state.controller ->
                Controller ! {position_colour, State#state.position, State#state.colour},
                loop( State );
    {stop, Controller} when Controller =:= State#state.controller -> ok
    end.

loop_ant_arrives( Pid, State ) ->
        Neighbour = State#state.neighbour,
        From = loop_ant_arrives_direction( Pid, Neighbour ),
        {loop_ant_arrives_new_direction(From, State), State}.

loop_ant_arrives_direction( Pid, #neighbour{north=Pid} ) -> north;
loop_ant_arrives_direction( Pid, #neighbour{south=Pid} ) -> south;
loop_ant_arrives_direction( Pid, #neighbour{east=Pid} ) -> east;
loop_ant_arrives_direction( Pid, #neighbour{west=Pid} ) -> west.

loop_ant_arrives_new_direction( north, #state{colour=white} ) -> west;
loop_ant_arrives_new_direction( north, #state{colour=black} ) -> east;
loop_ant_arrives_new_direction( south, #state{colour=white} ) -> east;
loop_ant_arrives_new_direction( south, #state{colour=black} ) -> west;
loop_ant_arrives_new_direction( east, #state{colour=white} ) -> north;
loop_ant_arrives_new_direction( east, #state{colour=black} ) -> south;
loop_ant_arrives_new_direction( west, #state{colour=white} ) -> south;
loop_ant_arrives_new_direction( west, #state{colour=black} ) -> north.

loop_ant_departs( north, #state{position={_X,Y}, max_y=Y}=State ) ->
        {State#state.controller, State};
loop_ant_departs( south, #state{position={_X,1}}=State ) ->
        {State#state.controller, State};
loop_ant_departs( east, #state{position={X,_Y}, max_x=X}=State ) ->
        {State#state.controller, State};
loop_ant_departs( west, #state{position={1,_Y}}=State ) ->
        {State#state.controller, State};
loop_ant_departs( Direction, State ) ->
        Neighbour = State#state.neighbour,
        Pid = loop_ant_departs_pid( Direction, Neighbour ),
        {Pid, State#state{colour=other_colour(State)}}.

loop_ant_departs_pid( north, #neighbour{north=Pid} ) -> Pid;
loop_ant_departs_pid( south, #neighbour{south=Pid} ) -> Pid;
loop_ant_departs_pid( east, #neighbour{east=Pid} ) -> Pid;
loop_ant_departs_pid( west, #neighbour{west=Pid} ) -> Pid.

loop_neighbour( {Pid, {X, Y}}, {{X, My_y}, Neighbour} ) when Y =:= My_y + 1 -> {{X, My_y}, Neighbour#neighbour{north=Pid}};
loop_neighbour( {Pid, {X, Y}}, {{X, My_y}, Neighbour} ) when Y =:= My_y - 1 -> {{X, My_y}, Neighbour#neighbour{south=Pid}};
loop_neighbour( {Pid, {X, Y}}, {{My_x, Y}, Neighbour} ) when X =:= My_x + 1 -> {{My_x, Y}, Neighbour#neighbour{east=Pid}};
loop_neighbour( {Pid, {X, Y}}, {{My_x, Y}, Neighbour} ) when X =:= My_x - 1 -> {{My_x, Y}, Neighbour#neighbour{west=Pid}};
loop_neighbour( _Pid_position, Acc ) -> Acc.

other_colour( #state{colour=white} ) -> black;
other_colour( #state{colour=black} ) -> white.

plane_create( Controller, Max_x, Max_y ) -> [{plane_create_cell(Controller, Max_x, Max_y, {X, Y}), {X,Y}} || X <- lists:seq(1, Max_x), Y<- lists:seq(1, Max_y)].
plane_create_cell( Controller, Max_x, Max_y, Position ) -> erlang:spawn_link( fun() -> loop( #state{controller=Controller, max_x=Max_x, max_y=Max_y, position=Position} ) end ).


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..'


// Langton's ant  F#   https://rosettacode.org/wiki/Langton%27s_ant

// A list of cells which are black is maintained and then printed out at the end

type Cell = { X : int; Y : int }
type Direction = | North | South | East| West // direction the ant is facing

let withinBounds (dim:int) (cell: Cell) = // ant's cell within dimensions ?
    cell.X < dim && cell.Y < dim && cell.X >= 0 && cell.Y >= 0

let rotateLeft (currentDirection: Direction) =
    match currentDirection with
        | North -> West | South -> East | East -> North | West -> South

let rotateRight (currentDirection: Direction ) =
    match currentDirection with
        | North -> East | South -> West | East -> South | West -> North

let nextCell (dir:Direction) (cell: Cell) = // compute next cell based on the direction
    match dir with
        | North -> {cell with Y = cell.Y + 1 }
        | South -> {cell with Y = cell.Y - 1 }
        | East ->  {cell with X = cell.X + 1 }
        | West ->  {cell with X = cell.X - 1 }

let isBlackCell (blackCells: Cell list) (cell:Cell) =
    blackCells |> List.exists ( fun c -> c = cell)

let toggleCellColor (blackCells: Cell list) (cell: Cell) =
     if cell |> isBlackCell blackCells
     then blackCells |> List.where( fun c -> c <> cell) // remove the cell from list of black cells
     else cell::blackCells // add the cell to the list of black cells

let moveToCell (blackCells: Cell list) (currentDir : Direction) (cell: Cell) =
    let ndir = if cell |> isBlackCell blackCells  // next step direction is computed
                    then rotateLeft currentDir
                    else rotateRight currentDir
    let nlst  = cell |> toggleCellColor blackCells // next step updated list of black cells is computed
    let ncell = cell |> nextCell ndir  // next step cell is computedd
    (nlst, ndir, ncell) // return next step list of black cells, direction it will enter the cell, new cell

let rec doStep (dim:int) (blackCells: Cell list) (dir : Direction) (cell: Cell) =
        let (nlst, ndir, ncell) = moveToCell blackCells dir cell
        if withinBounds dim ncell // check if the next step is within bounds
            then doStep dim nlst ndir ncell // recursive call to next step
            else nlst, ndir, ncell

[<EntryPoint>]
let main _ =
   let dim = 100
   let (blacklist, _, _) = doStep dim []  North { X = dim/2 ; Y = dim/2 } // start with empty blacklist, facing north in the center

    // print out by row, 0th row is at the bottom
   seq { for row in [dim-1..-1..0] do for col in [0..dim-1]  -> (col,row) }
        |> Seq.iter (fun (row,col) -> if {X = row; Y = col } |> isBlackCell blacklist
                                        then printf "#"  else printf " "
                                      if row = (dim - 1 )
                                        then printf "\n"  else  ()
                    )
   0


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")
  }
}


 1 0 0 0                                                          \ pushes orientation of the ant to the stack.

 100 CONSTANT border                                              \ lenght of the side of the grid
 border border * constant size                                    \ size of the grid

 variable antpos                                                  \ for storing position of the ant
 size 2 / border 2 / +  antpos !                                  \ positions ant in the middle of the grid

 create Grid size cells allot
 here constant GridEnd                                            \ creates an array to hold the grid

 : turn.left
	>r rot r> SWAP ;                                          \ rotates ant anti-clockwise

 : turn.right
	turn.left turn.left turn.left ;                           \ rotates ant clockwise

 : stop.ant
	antpos @ DUP 0<  SWAP size > + ;                          \ checks if ant not out of bounds

 : call.pos
	Grid antpos @ cells + @ ;                                 \ pushes ant position to the stack

 : grid.add
	Grid antpos @ cells + @ -1 + Grid antpos @ cells + !   ;  \ pushes -1 to the current position of the ant on the grid

 : swap.pos
	call.pos dup * Grid antpos @ cells + ! ;                  \ multiplies current grid cell by itself to turn -1 into 1

 : swap.col
	grid.add swap.pos ;                                       \ changes current grid cell color

 : go.ant                                                         \ moves ant one step in the direction taken from the stack
	2over 2over                                               \ copies stack for testing
	1 = IF antpos @ border + antpos ! 2DROP DROP ELSE         \ if true moves ant one cell up, drops unused numbers from stack
	1 = IF antpos @ 1 + antpos ! 2DROP ELSE                   \ same, but moves to the right
	1 = IF antpos @ border - antpos ! DROP ELSE               \ here to the left
	1 = IF antpos @ 1 - antpos ! ELSE                         \ and down

	THEN THEN THEN THEN  ;

 : step.ant                                                       \ preforms one full step.
	 call.pos 1 = IF turn.left swap.col ELSE
	 turn.right swap.col

	 THEN go.ant  ;

 : run.ant                                                        \ runs the ant until it leaves the grid
	BEGIN
	step.ant
	stop.ant UNTIL ;

 : square.draw                                                     \ draws an "*" if grid cell is one or " " if zero
	1 = IF 42 EMIT ELSE 32 EMIT THEN ;

 : draw.grid                                                       \ draws grid on screen
	PAGE                                                       \ clear sreen
	size 0 DO I
	I border MOD 0= IF  CR  THEN                               \ breaks the grid into lines
	Grid I cells + @ square.draw DROP

	LOOP ;

 : langton.ant run.ant draw.grid ;                                 \ launches the ant, outputs the result


program Langtons_Ant
  implicit none

  integer, parameter :: csize = 100
  integer :: direction = 0, maxsteps = 20000
  integer :: i, x, y
  logical :: cells(csize,csize) = .true.
  logical :: cflag

  x = csize / 2;   y = x

  do i = 1, maxsteps
    cflag = cells(x,y)
    if(cflag) then
      direction = direction + 1
      if(direction == 4) direction = direction - 4
    else
      direction = direction - 1
      if(direction == -1) direction = direction + 4
    end if

    cells(x,y) = .not. cells(x,y)

    select case(direction)
      case(0)
        y = y - 1
      case(1)
        x = x + 1
      case(2)
        y = y + 1
      case(3)
        x = x - 1
    end select

    if(x < 1 .or. x > csize .or. y < 1 .or. y > csize) exit
  end do

  do y = 1, csize
    do x = 1, csize
      if(cells(x,y)) then
        write(*, "(a)", advance="no") "."
      else
        write(*, "(a)", advance="no") "#"
      end if
    end do
    write(*,*)
  end do
end program


' version 16-10-2016
' compile with: fbc -s gui

' a cell size of 4 x 4 pixels is used
' In FreeBASIC the 0,0 is the top left corner

ScreenRes 400,400,8 ' give a 100 by 100 field
Dim As UByte Ptr p = ScreenPtr
If p = 0 Then End ' p does not point to screen

Palette 0,       0,   0,   0      ' index 0 = black
Palette 255,   255, 255, 255      ' index 225 = white

Line (0, 0) - (799, 799), 255, bf   ' draw box and fill it with white color

Dim As Integer count, offset, x = 199, y = 199
Dim As UByte col   ' = color
' direction, 0 = up, 1 = right, 2 = down, 3 = left
Dim As UByte d     ' d = 0, looking up

Do
  offset = x + y * 400
  col = p[offset]

  If col = 0 Then
    d = (d -1) And 3
  Else
    d = (d +1) And 3
  EndIf

  col = col Xor 255 ' flip the color

  ScreenLock        ' don't update screen while we are drawing

  ' draw a 4*4 block and paint it with palette color [0 | 255]
  Line (x, y) - (x +3, y -3), col, bf

  ScreenUnLock    ' allow screen update's

  'Sleep 100       ' slow the program down if needed

  ' true = 0, false = -1
  If (d And 1) = 1 Then
    x = x + (d = 1) * 4 - (d = 3) * 4
  Else
    y = y - (d = 0) * 4 + (d = 2) * 4
  End If

  count += 1
  ' update step count window title bar
  WindowTitle "Langton's ant step: " + Str(count)

  ' has user clicked on close window "X" then end program
  If InKey = Chr(255) + "k" Then End

Loop Until x < 1 Or x > 398 Or y < 1 Or y > 398

' display total count in window title bar
WindowTitle "Langton's ant has left the field in " + Str(count) + " steps"

' empty keyboard buffer
While InKey <> "" : Wend
'Print : Print "hit any key to end program"
Sleep
End


###sysinclude X.uh
$ff0000 sto szin1
$ffffff sto szin2
2 sto pausetime
maxypixel 100 - sto YRES
maxxpixel       sto XRES
zero ant
// Az ant iránykódjai:
// 0 : fel
// 1 : le
// 2 : jobbra
// 3 : balra
@XRES 2 / sto antx // Az ant kezdeti koordinátái
@YRES 2 / sto anty
myscreen "Furor monitor" @YRES @XRES graphic // Create the graphic screen
."Kilépés: ESC\n"

infiniteloop: {... // infinite loop begins
myscreen @anty @antx [[]][[]] // A pixel színe amin az ant ül épp
@szin2 == { myscreen @anty @antx @szin1 [][] // másik színre átállítjuk a pixelt
2 // Jobbra fog fordulni
}{ myscreen @anty @antx @szin2 [][] // másik színre átállítjuk a pixelt
3 // Balra fog fordulni
}
// Elvégezzük az új koordináta beállítását:
sto direction
@ant 0 == { @direction 2 == then §r1 @direction 3 == then §r2 }
@ant 2 == { @direction 2 == then §r3 @direction 3 == then §r4 }
@ant 1 == { @direction 3 == { r1: antx @XRES  ring 2 goto §beolvas } @direction 2 == { r2: antx @XRES !ring 3 goto §beolvas } }
@ant 3 == { @direction 3 == { r3: anty @YRES !ring 1 goto §beolvas } @direction 2 == { r4: anty @YRES  ring 0 goto §beolvas } }

beolvas: sto ant
myscreen key? sto! billkód  @pausetime usleep $1b ==
|...}
."Made " {...}§infiniteloop print ." steps.\n"
."XRES = " @XRES printnl
."YRES = " @YRES printnl
myscreen !graphic
end
{ „myscreen” }
{ „billkód” }
{ „pausetime” }
{ „XRES” }
{ „YRES” }
{ „szin1” }
{ „szin2” }
{ „ant” }
{ „antx” }
{ „anty” }
{ „direction” }


'This code will create a GUI Form to display the result

hGridView As GridView                                               'The display is on a GridView
iCol As Integer = 38                                                'Column start position
iRow As Integer = 30                                                'Row start position

Public Sub Form_show()

SetUpForm                                                           'Run the SetUpForm routine
Go                                                                  'Run the Go routine

End

Public Sub Go()                                                     'This is what does the work
Dim siDir As Short = 3                                              'Stores the Direction of the ant 0 = North, 1 = East, 2 = South ,3 = West
Dim siCount As Short                                                'Counter

Repeat                                                              'Repeat loop
  Inc siCount                                                       'Increase siCount
  If hGridView[iRow, iCol].background = -1 Then                     'If the Background of the cell is white then..(Right turn)
    hGridView[iRow, iCol].background = 0                            'Make the Background black
    siDir = Direction(siDir, True)                                  'Get the direction to turn
    If siDir = 0 Then Dec iRow                                      'Decrease Row if facing North
    If siDir = 1 Then Inc iCol                                      'Increase Column if facing East
    If siDir = 2 Then Inc iRow                                      'Increase Row if facing South
    If siDir = 3 Then Dec iCol                                      'Decrease Column if facing West
  End If
'Wait                                                                'This will allow you to see the Grid being populated. Rem it out for an instant result
  If hGridView[iRow, iCol].background = 0 Then                      'If the Background of the cell is black then.. Left Turn
    hGridView[iRow, iCol].background = -1                           'Make the Background white
    siDir = Direction(siDir, False)                                 'Get the direction to turn
    If siDir = 0 Then Dec iRow                                      'Decrease Row if facing North
    If siDir = 1 Then Inc iCol                                      'Increase Column if facing East
    If siDir = 2 Then Inc iRow                                      'Increase Row if facing South
    If siDir = 3 Then Dec iCol                                      'Decrease Column if facing West
  End If
Until siCount = 9660                                                'Loop 9660 times

End

Public Sub Direction(siDirection As Short, bWay As Boolean) As Byte 'To workout which way to go

If bWay Then                                                        'If turning Right then
  Inc siDirection                                                   'Increase siDirection e.g. 0 = North to 1 = East
Else                                                                'Else if turning Left
  Dec siDirection                                                   'Decrease siDirection e.g. 2 = South to 1 = East
End If

If siDirection < 0 Then siDirection = 3                             'To address 0 - 1 = -1
If siDirection > 3 Then siDirection = 0                             'To address 3 + 1 = 4

Return siDirection                                                  'Return the correct direction

End

Public Sub SetUpForm()                                              'Set up the Form and Create the Gridview

With Me                                                             'Change the Properties of the Form
  .Height = 1012                                                    'Set the Form Height
  .Width = 1012                                                     'Set the Form Width
  .Arrangement = Arrange.Vertical                                   'Set the Form Arrangement
  .Padding = 5                                                      'Set the Form Padding (Border)
  .title = "Langton's ant"                                          'Set the Form Title
End With

hGridView = New GridView(Me)                                        'Create a GridView
With hGridView                                                      'Change the Properties of the GridView
  .Columns.count = 100                                              'Create 100 Columns
  .Rows.count = 100                                                 'Create 100 Rows
  .Columns.Width = 10                                               'Set the Column Width
  .Rows.Height = 10                                                 'Set the Column Height
  .expand = True                                                    'Set the Gridview to Expand to fill the Form
  .background = -1                                                  'Set the Gridview background to White
End With

End


'
' Langton's ant
'
' World is a global boolean array, 100x100 in size
width%=100
height%=100
DIM world!(width%,height%)
ARRAYFILL world!(),FALSE
' Time in world
time%=0
' Ant is represented by a global three-element array
' holding: x, y, direction [0=north,1=west,2=south,3=east]
DIM ant%(3)
'
@setup_ant
@run_ant
@display_world
'
' Displays the world to file "langton.out": . for false, # for true
'
PROCEDURE display_world
  LOCAL i%,j%
  OPEN "o",#1,"langton.out"
  PRINT #1,"Time in world: ";time%;" ticks"
  FOR i%=0 TO width%-1
    FOR j%=0 TO height%-1
      IF world!(i%,j%)
        PRINT #1,"#";
      ELSE
        PRINT #1,".";
      ENDIF
    NEXT j%
    PRINT #1,""
  NEXT i%
  CLOSE #1
RETURN
'
' Set up the ant to start at (50,50) facing north
'
PROCEDURE setup_ant
  ant%(0)=50
  ant%(1)=50
  ant%(2)=0
RETURN
'
' check if ant position is within world's bounds
'
FUNCTION ant_in_world
  RETURN ant%(0)>=0 AND ant%(0)<width% AND ant%(1)>=0 AND ant%(1)<height%
ENDFUNC
'
' Turn ant direction to left
'
PROCEDURE ant_turn_left
  ant%(2)=(ant%(2)+1) MOD 4
RETURN
'
' Turn ant direction to right
'
PROCEDURE ant_turn_right
  ant%(2)=(ant%(2)+3) MOD 4
RETURN
'
' Ant takes a step forward in current direction
'
PROCEDURE ant_step_forward
  SELECT ant%(2)
  CASE 0
    ant%(0)=ant%(0)+1
  CASE 1
    ant%(1)=ant%(1)+1
  CASE 2
    ant%(0)=ant%(0)-1
  CASE 3
    ant%(1)=ant%(1)-1
  ENDSELECT
RETURN
'
' Run the ant until it falls out of the world
'
PROCEDURE run_ant
  WHILE @ant_in_world
    time%=time%+1
    IF world!(ant%(0),ant%(1)) ! true for white
      world!(ant%(0),ant%(1))=FALSE
      @ant_turn_left
    ELSE ! false for black
      world!(ant%(0),ant%(1))=TRUE
      @ant_turn_right
    ENDIF
    @ant_step_forward
  WEND
RETURN


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)
    }
}


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


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
)


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;
	}
}


// 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();
}


def matrix(m; n; init):
  if m == 0 then [range(0;n)] | map(init)
  elif m > 0 then [range(0;m)][ range(0;m) ] = matrix(0;n;init)
  else error("matrix\(m);_;_) invalid")
  end;

def printout:
  . as $grid
  | ($grid|length) as $height
  | ($grid[0]|length) as $width
  | reduce range(0;$height) as $i ("\u001BH";
    . + reduce range(0;$width) as $j ("\n";
         . + if $grid[$i][$j] then " " else "#" end ) );

def langtons_ant(grid_size):

  def flip(ant):
    # Flip the color of the current square
    .[ant[0]][ant[1]] = (.[ant[0]][ant[1]] | not)
  ;

  # input/output: the ant's state: [x, y, direction]
  # where direction is one of (0,1,2,3)
  def move(grid):
    # 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;
    (if grid[.[0]][.[1]] then 1 else 3 end) as $turn
    | .[2] = ((.[2] + $turn) % 4)
    | if   .[2] == 0 then .[0] += 1
      elif .[2] == 1 then .[1] += 1
      elif .[2] == 2 then .[0] += -1
      else                .[1] += -1
      end
  ;

  # state: [ant, grid]
  def iterate:
    .[0] as $ant | .[1] as $grid
    # exit if the ant is outside the grid
    | if $ant[0] < 1 or $ant[0] > grid_size
      or $ant[1] < 1 or $ant[1] > grid_size
      then [ $ant, $grid ]
      else
        ($grid | flip($ant)) as $grid
        | ($ant | move($grid)) as $ant
        | [$ant, $grid] | iterate
      end
  ;

  ((grid_size/2) | floor | [ ., ., 0]) as $ant
  | matrix(grid_size; grid_size; true) as $grid
  | [$ant, $grid] | iterate
  | .[1]
  | printout
;

langtons_ant(100)


function ant(width, height)
    y, x = fld(height, 2), fld(width, 2)
    M = falses(height, width)

    dir = im
    for i in 0:100000
        x in 1:width && y in 1:height || break
        dir *= M[y, x] ? im : -im
        M[y, x] = !M[y, x]
        x, y = reim(x + im * y + dir)
    end

    for row in 1:size(M,1)
        println(mapreduce(x -> x ? 'x' : '.', *, M[row,:]))
    end
end

ant(100, 100)


// version 1.2.0

enum class Direction { UP, RIGHT, DOWN, LEFT }

const val WHITE = 0
const val BLACK = 1

fun main(args: Array<String>) {
    val width = 75
    val height = 52
    val maxSteps = 12_000
    var x = width / 2
    var y = height / 2
    val m = Array(height) { IntArray(width) }
    var dir = Direction.UP
    var i = 0
    while (i < maxSteps && x in 0 until width && y in 0 until height) {
        val turn = m[y][x] == BLACK
        val index = (dir.ordinal + if (turn) 1 else -1) and 3
        dir = Direction.values()[index]
        m[y][x] = if (m[y][x] == BLACK) WHITE else BLACK
        when (dir) {
             Direction.UP    -> y--
             Direction.RIGHT -> x--
             Direction.DOWN  -> y++
             Direction.LEFT  -> x++
        }
        i++
    }
    for (j in 0 until height) {
        for (k in 0 until width) print(if(m[j][k] == WHITE) '.' else '#')
        println()
    }
}