《付録》life.py

# -*- coding: utf-8 -*-
#===============================================================================
#    Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部
#
# History: Life Game
#    1988/05, Smalltalk
#    2004/09, Java
#    2005/02, C#
#    2005/03, Jython
#===============================================================================

#===============================================================================
#    配列と別れる50の方法
#===============================================================================
from game import *

#===============================================================================
class LifeGameFrame(DefaultFrame):
    def initialize(self):
        self.panel = LifeGamePanel()
        self.button = JButton("Next Generation", 
            actionPerformed=self.actionPerformed)
        
    def initializeComponent(self):
        self.layout = BorderLayout()
        self.add(self.panel, BorderLayout.CENTER)
        self.add(self.button, BorderLayout.SOUTH)
        
    def actionPerformed(self, e):
        self.panel.nextGeneration()
	
#===============================================================================
class LifeGamePanel(GameBoardPanel):
    dim = 48
        
    def locateItems(self):
        points = [(x, y)
            for y in range(self.dim)
            for x in range(self.dim)]
        for x, y in points:
            self.items.append(Life(x, y))

    def settle(self):
        self.addNeighbor()

    def addNeighbor(self):
        for e in self.items:
            self.addNeighbor1(e)

    def addNeighbor1(self, life):
        ix = life.x
        iy = life.y
        points = [(x, y)
            for y in (iy-1, iy, iy+1)
            for x in (ix-1, ix, ix+1)]
        for x, y in points:
            if (x, y) == (ix, iy): continue
            life.add(self.detect(x, y))

    def prepare(self):
        side = min(self.width, self.height) / self.dim
        self.__class__.itemExtent = side, side

    def this_mouseClicked(self, e):
        life = self.detectLife(e)
        print ">>>", life
        life.reverse();
        self.repaint();
        
    def detectLife(self, e):
        width, height = self.__class__.itemExtent
        return self.detect(e.x/height, e.y/height)

    def nullObject(self):
        return Null

    def nextGeneration(self):
        self.updateFuture()
        self.updatePresent()
        self.repaint()
        
    def updateFuture(self):
        for e in self.items:
            e.updateFuture()

    def updatePresent(self):
        for e in self.items:
            e.updatePresent()

#===============================================================================
class Life(GameItem):

    def __init__(self, x, y):
        GameItem.__init__(self, x, y)
        self.present = False
        self.future  = False
        self.neighbor = []
        
    def __repr__(self):
        s = StringBuffer();
        s.append(self.xyString())
        s.append(`self.present` + "->")
        s.append(`self.future` + ":")
        for e in self.neighbor:
            s.append(e.xyString())
        s.append(":" + `self.neighbors()`)
        return `s`
        
    def xyString(self):
        return "(%s,%s)"%(self.x, self.y)

    def neighbors(self):
        return len([None for e in self.neighbor if e.present])

    def paintBackground(self, g): pass
        
    def paintItem(self, g):
        width, height = LifeGamePanel.itemExtent
        x = self.x * width
        y = self.y * height
        g.setColor(self.fillColor())
        g.fillRect(x, y, width, height)
        g.setColor(Color.black)
        g.drawRect(x, y, width, height)
            
    def fillColor(self):
        return (Color.white, Color.red)[self.present]
            
    def add(self, life):
        self.neighbor.append(life)
        
    def reverse(self):
        self.present = not self.present

    def updateFuture(self):
        n = self.neighbors()
        if n == 2:
            self.future = self.present
        elif n == 3:
            self.future = True
        else:
            self.future = False

    def updatePresent(self):
         self.present = self.future

Null = Life(0, 0)
Null.xyString = lambda: "()"
Null.reverse  = lambda: None

#===============================================================================
def example():
    LifeGameFrame("Life Game", (300, 360))

#===============================================================================
from _jython2_ import *
signature("-", __file__, '1.0.1')
#===============================================================================