langton s ant https en wikipedia orgwikilangton27sant https upload wikimedia orgwikipediacommons009langtonsantanimated gif represents the main langonsant algorithm la langtonsant2 2 la board true true true true la antposition 1 1 each square is either true or false where true is white and false is black initially pointing left similar to the wikipedia image 0 0 1 90 2 180 3 270 performs three tasks 1 the ant turns either clockwise or anticlockwise according to the colour of the square that it is currently on if the square is white the ant turns clockwise and if the square is black the ant turns anticlockwise 2 the ant moves one square in the direction that it is currently facing 3 the square the ant was previously on is inverted white black and black white if display is true the board will also be displayed on the axes la langtonsant2 2 la moveantnone true 0 la board true true true false la moveantnone true 0 la board true false true false turn clockwise or anticlockwise according to colour of square the square is white so turn 90 clockwise the square is black so turn 90 anticlockwise move ant flip colour of square display the board on the axes displays the board without delay in a matplotlib plot to visually understand and track the ant langtonsantwidth height assign animation to a variable to prevent it from getting garbage collected represents the main langonsant algorithm la langtonsant 2 2 la board true true true true la ant_position 1 1 each square is either true or false where true is white and false is black initially pointing left similar to the wikipedia image 0 0 1 90 2 180 3 270 performs three tasks 1 the ant turns either clockwise or anti clockwise according to the colour of the square that it is currently on if the square is white the ant turns clockwise and if the square is black the ant turns anti clockwise 2 the ant moves one square in the direction that it is currently facing 3 the square the ant was previously on is inverted white black and black white if display is true the board will also be displayed on the axes la langtonsant 2 2 la move_ant none true 0 la board true true true false la move_ant none true 0 la board true false true false 0 90 180 270 turn clockwise or anti clockwise according to colour of square the square is white so turn 90 clockwise the square is black so turn 90 anti clockwise move ant flip colour of square display the board on the axes displays the board without delay in a matplotlib plot to visually understand and track the ant _ langtonsant width height assign animation to a variable to prevent it from getting garbage collected
from functools import partial

from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation

WIDTH = 80
HEIGHT = 80


class LangtonsAnt:
    

    def __init__(self, width: int, height: int) -> None:
        
        self.board = [[True] * width for _ in range(height)]
        self.ant_position: tuple[int, int] = (width // 2, height // 2)

        
        
        self.ant_direction: int = 3

    def move_ant(self, axes: plt.Axes | None, display: bool, _frame: int) -> None:
        
        directions = {
            0: (-1, 0),  
            1: (0, 1),  
            2: (1, 0),  
            3: (0, -1),  
        }
        x, y = self.ant_position

        
        if self.board[x][y] is True:
            
            self.ant_direction = (self.ant_direction + 1) % 4
        else:
            
            self.ant_direction = (self.ant_direction - 1) % 4

        
        move_x, move_y = directions[self.ant_direction]
        self.ant_position = (x + move_x, y + move_y)

        
        self.board[x][y] = not self.board[x][y]

        if display and axes:
            
            axes.get_xaxis().set_ticks([])
            axes.get_yaxis().set_ticks([])
            axes.imshow(self.board, cmap="gray", interpolation="nearest")

    def display(self, frames: int = 100_000) -> None:
        
        fig, ax = plt.subplots()
        
        self.animation = FuncAnimation(
            fig, partial(self.move_ant, ax, True), frames=frames, interval=1
        )
        plt.show()


if __name__ == "__main__":
    import doctest

    doctest.testmod()

    LangtonsAnt(WIDTH, HEIGHT).display()