Langton's Ant in Python
A full explanation is given here.
1 2 #************************************************ 3 # Rules of the game 4 # 1. If the ant is on a black square, it turns 5 # right 90 and moves forward one unit 6 # 2. If the ant is on a white square, it turns 7 # left 90 and moves forward one unit 8 # 3. When the ant leaves a square, it inverts 9 # colour 10 # 11 # SEE: http://mathworld.wolfram.com/LangtonsAnt.html 12 #************************************************ 13 14 import sys, pygame 15 from pygame.locals import * 16 import time 17 18 dirs = ( 19 (-1, 0), 20 (0, 1), 21 (1, 0), 22 (0, -1) 23 ) 24 25 cellSize = 12 # size in pixels of the board (4 pixels are used to draw the grid) 26 numCells = 64 # length of the side of the board 27 background = 0, 0, 0 # background colour; black here 28 foreground = 23, 23, 23 # foreground colour; the grid's colour; dark gray here 29 textcol = 177, 177, 177 # the colour of the step display in the upper left of the screen 30 antwalk = 44, 88, 44 # the ant's trail; greenish here 31 antant = 222, 44, 44 # the ant's colour; red here 32 fps = 1.0 / 40 # time between steps; 1.0 / 40 means 40 steps per second 33 34 def main(): 35 pygame.init() 36 37 size = width, height = numCells * cellSize, numCells * cellSize 38 39 pygame.display.set_caption("Langton's Ant") 40 41 screen = pygame.display.set_mode(size) # Screen is now an object representing the window in which we paint 42 screen.fill(background) 43 pygame.display.flip() # IMPORTANT: No changes are displayed until this function gets called 44 45 for i in xrange(1, numCells): 46 pygame.draw.line(screen, foreground, (i * cellSize, 1), (i * cellSize, numCells * cellSize), 2) 47 pygame.draw.line(screen, foreground, (1, i * cellSize), (numCells * cellSize, i * cellSize), 2) 48 pygame.display.flip() # IMPORTANT: No changes are displayed until this function gets called 49 50 font = pygame.font.Font(None, 36) 51 52 antx, anty = numCells / 2, numCells / 2 53 antdir = 0 54 board = [[False] * numCells for e in xrange(numCells)] 55 56 step = 1 57 pause = False 58 while True: 59 for event in pygame.event.get(): 60 if event.type == QUIT: 61 return 62 elif event.type == KEYUP: 63 if event.key == 32: # If space pressed, pause or unpause 64 pause = not pause 65 elif event.key == 115: 66 pygame.image.save(screen, "Step%d.tga" % (step)) 67 68 if pause: 69 time.sleep(fps) 70 continue 71 72 text = font.render("%d " % (step), True, textcol, background) 73 screen.blit(text, (10, 10)) 74 75 if board[antx][anty]: 76 board[antx][anty] = False # See rule 3 77 screen.fill(background, pygame.Rect(antx * cellSize + 1, anty * cellSize + 1, cellSize - 2, cellSize - 2)) 78 antdir = (antdir + 1) % 4 # See rule 1 79 else: 80 board[antx][anty] = True # See rule 3 81 screen.fill(antwalk, pygame.Rect(antx * cellSize + 1, anty * cellSize + 1, cellSize - 2, cellSize - 2)) 82 antdir = (antdir + 3) % 4 # See rule 2 83 84 antx = (antx + dirs[antdir][0]) % numCells 85 anty = (anty + dirs[antdir][1]) % numCells 86 87 # The current square (i.e. the ant) is painted a different colour 88 screen.fill(antant, pygame.Rect(antx * cellSize + 1, anty * cellSize + 1, cellSize -2, cellSize -2)) 89 90 pygame.display.flip() # IMPORTANT: No changes are displayed until this function gets called 91 92 step += 1 93 time.sleep(fps) 94 95 if __name__ == "__main__": 96 main()