生命体が占有するセルを配置する
テストケースの動作を確認するために、2つの生命体をコロニーに配置します。
class ExWindow(Window): def init(self): target = "canvas", self._Controls(target) self.colony = self._colony()
インスタンス属性 self.colony は、多数の生命体が集うコロニーを管理します。
def _colony(self): colony = Colony() for e in [ ExHexStone(self, 2, 2, False, Stroke=Brushes.Blue, Fill=Brushes.Cyan ), ExHexStone(self, 4, 2, False, Stroke=Brushes.Red, Fill=Brushes.Yellow), ]: self.canvas.Children.Add(e.shape) colony.addCell(e) return colony
2つの生命体(青/赤)が占有するセルを用意して、それぞれをコロニー colony に追加 addCell します。
生命体が占有するセルを生成する
既存のモジュール hexOthello.py を再利用するとともに、WPF に固有の情報を付加します。
class ExHexStone:
def __init__(self, client, x, y, state, Stroke=None, Fill=None):
self.client = client
self.name = "_%d_%d"%(x, y)
self.shape = self._shape(x, y)
if Stroke:
self.shape.Stroke = Stroke
if Fill:
self.shape.Fill = Fill
生命体が占有するセルを生成するときに、輪郭(Stroke=)内部(Fill=)の色を設定できるようにします。
def _shape(self, x, y): name = "_%d_%d"%(x, y) x = HexStone._dx + x * HexStone._width y = HexStone._dy + y * HexStone._height points = PointCollection() for dx, dy in HexStone(x, y, False).vertices: points.Add(Point(x+dx*2, y+dy*2)) s = Polygon( Name=name, HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=Brushes.Black, StrokeThickness=1, Fill=Brushes.Green, Points=points, ) s.MouseUp += self.mouseUp return s
セルを構成するときには、既存のモジュール hexOthello.py を再利用します。プロバティー Name= を使って、各セルを識別します。
def mouseUp(self, sender, e): life = self.client.combineLife(sender.Name) points = PointCollection() for e in life.points: points.Add(e) self.client.addShape(Polygon( HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=sender.Stroke, StrokeThickness=3, Points=points, ))
選択したセルの識別情報 sender.Name をもとに、一方の生命体を指定すると、隣接する他方の生命体と接合した、新たな多細胞生命体 life が得られます。その頂点の座標 life.points をもとに、新たな多角形をキャンバスに追加 addShape します。
《付録》organism.py
# -*- coding: utf-8 -*- #=============================================================================== # Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部 # # Change History: Games # 1988/05, Smalltalk # 2004/09, Java # 2005/02, C# # 2005/03, Jython # Change History: WPF examples # 2008/01/25, IronPython 1.1.1 (download) # 2008/08/22, IronPython 1.1.2 (download) # 2008/03/16, ver.2.0, WPF # 2008/00/00, ver.2.1, IronPython 1.1.2 #=============================================================================== from hexOthello import HexStone ## -------------------- class Colony: # 生命体: life-form def __init__(self): self.lives = def addCell(self, cell): life = Unicellular(cell) for e in self.lives: e.adjoin(life) self.lives.append(life) def detectLife(self, name): life = None for e in self.lives: if e.cell.name == name: life = e; break return life ## -------------------- class Organism: def merge(self, s1, i1, s2, i2): p = (i1+4)%len(s2) q = 6-i2; d = 5-q return s1[:i1+1] + self.circulate(s2, p, q) + s1[i1+d:] def circulate(self, s, p, q): size = len(s) start = p+1; stop = p+q+1 if size < stop: s = s[start:] + s[:stop-size] else: s = s[start:stop] return s ## -------------------- class Unicellular(Organism): # 単細胞生物: unicellular organism def __init__(self, cell): self.cell = cell self.surroundings = def __repr__(self): return str(self.cell) def adjoin(self, cell): self.surroundings.append(cell) cell.surroundings.append(self) def combine(self): target = self.surroundings[0] indexes = self.intersection(target) print "target::", target.name(), indexes points = self.merge( target.points(), indexes[0], self.points(), len(indexes), ) return Multicellular([self, target], points) def intersection(self, target): return [i for i, e in enumerate(target.points()) if e in self.points()] def points(self): return self.cell.points() def name(self): return self.cell.name ## -------------------- class Multicellular(Organism): # 多細胞生物: multicellular organism def __init__(self, lives, points): self.lives = lives self.points = points def __repr__(self): s = [] for e in self.points: s.append("(%d,%d) "%(e.X, e.Y)) return "%s %s"%(self.lives, "".join(s)) ## --------------------