Personal tools
You are here: Home メンバー 菊地時夫 授業 大学基礎論 life.py
Document Actions

life.py

by 菊地時夫 last modified 2008-04-22 17:20

Click here to get the file

Size 5.3 kB - File type text/python-source

File contents

#!/usr/bin/env python
# 2006 Guyon Moree ( http://gumuz.looz.net/ )

# python implementation of Conway's game of life using pygame ( http://www.pygame.org )

# controls:
#   space       = start/stop evolution
#   +/-         = faster/slower evolution
#   r           = seed the grid random
#   c           = clear grid
#   mouseclick  = paint cell

import sys, pygame
import random, time


pygame.init()

size = width, height = 800, 600
black = 0, 0, 0
blocksize = 10

# Initial pattern for glider
glider = ((-1,0),(-1,1),(0,-1),(0,1),(1,1))

# Initial pattern for gliergun
glidergun = ((25,1),
	(23,2),(25,2),
	(13,3),(14,3),(21,3),(22,3),(35,3),(36,3),
	(12,4),(16,4),(21,4),(22,4),(35,4),(36,4),
	(1,5),(2,5),(11,5),(17,5),(21,5),(22,5),
	(1,6),(2,6),(11,6),(15,6),(17,6),(18,6),(23,6),(25,6),
	(11,7),(17,7),(25,7),
	(12,8),(16,8),
	(13,9),(14,9))

patterns = { ord('g'): glider,
	     ord('f'): glidergun,
           }

def putpattern(pattern):
    grid = startgrid()
    xc = width/blocksize/4
    yc = height/blocksize/4
    for x,y in pattern:
        grid[y + yc][x + xc] = 1
    return grid

screen = pygame.display.set_mode(size)

def startagegrid(grid):
    agegrid = []
    for r in grid:
        row = []
        for c in r:
            row.append(0)
        agegrid.append(row)
    return agegrid


def startgrid(rnd=False):
    """ generate emtpy or randomly filled grid """
    grid = []
    for y in range(height/blocksize):
        row = []
        for x in range(width/blocksize):
            if rnd:
                row.append(random.choice([0,1]))
            else:
                row.append(0)
        grid.append(row)
    return grid

def getneighbours(grid, x,y):
    """ find all 8 possible neigbours """
    offsets = ((-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1))
    count = 0
    for a,b in offsets:
        ny,nx = (y+a)%len(grid), (x+b)%len(grid[y])
        count += grid[ny][nx]
    return count

def evolvegrid(grid, agegrid=None):
    """ evolve grid to next generation """
    dupe = []
    for row in grid:
        dupe.append(row[:])
    for y in range(height/blocksize):
        for x in range(width/blocksize):
            pop = grid[y][x]
            neighbours = getneighbours(grid, x, y)
            # next step?
            if pop:
                if neighbours < 2 or neighbours > 3:
                    dupe[y][x] = 0
            else:
                if neighbours == 3:
                    dupe[y][x] = 1
            if agegrid:
                if pop and dupe[y][x] and agegrid[y][x] < 250:
                    agegrid[y][x] += 15
                elif not dupe[y][x]:
                    agegrid[y][x] = 0
    return dupe

def paintgrid(surface, grid, agegrid=None):
    """ paint grid to screen """
    for y in range(height/blocksize):
        for x in range(width/blocksize):
            if grid[y][x]:
                if agegrid:
                    color = (255-agegrid[y][x],255-agegrid[y][x],255)
                else:
                    color = (255,255,255)
                surface.fill(color, pygame.Rect((x*blocksize,y*blocksize), (blocksize, blocksize)))

def paintcell(grid, pos, brush):
    """ paint a cell in the gid """
    x,y = pos
    grid[y/blocksize][x/blocksize] = brush
    return grid

# init the grid
grid = startgrid()
agegrid = startagegrid(grid)

# init some vars
evolve = False
mousedown = False
interval = 0
brush = 1
step = False

# main loop
while 1:
    for event in pygame.event.get():
        """ handle events """
        # escape
        if event.type == pygame.QUIT: sys.exit()

        # space play/pause
        if event.type == pygame.KEYDOWN and event.key == 32: #SP
             evolve = not evolve
        # step 1 generation
        if event.type == pygame.KEYDOWN and event.key == 115: # s
             step = True

        # randomise/reset grid
        if event.type == pygame.KEYDOWN and event.key == 114: # r
            grid = startgrid(True)
        if event.type == pygame.KEYDOWN and event.key == 99: # c
             grid = startgrid()
        # Hack! patterns
        if event.type == pygame.KEYDOWN and event.key in patterns.keys():
             grid = putpattern(patterns[event.key])

        # speed control
        if event.type == pygame.KEYDOWN and event.key == 270:
            if interval > 0: interval -= .1
            if interval < 0: interval = 0
        if event.type == pygame.KEYDOWN and event.key == 269:
            interval += .1

        # mouse paint
        if event.type == pygame.MOUSEBUTTONDOWN:
             mousedown = True
             x,y = event.pos
             brush = not grid[y/blocksize][x/blocksize]
             grid = paintcell(grid, event.pos, brush)

        if event.type == pygame.MOUSEBUTTONUP:
             mousedown = False
        if event.type == pygame.MOUSEMOTION and mousedown:
             grid = paintcell(grid, event.pos, brush)


    # reset screen 
    screen.fill(black)
    # paint the grid
    paintgrid(screen, grid, agegrid)
    # if not paused or 'step' was pressed and no mousedown, evolve the grid
    if (evolve or step) and not mousedown:
        grid = evolvegrid(grid, agegrid)
        time.sleep(interval)
        step = False
    # display to screen
    pygame.display.flip()

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: