Advertisement
Guest User

Untitled

a guest
Aug 1st, 2015
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.74 KB | None | 0 0
  1. from __future__ import print_function
  2. from copy import deepcopy
  3. import curses
  4. from time import sleep
  5. import random
  6. import os
  7. from collections import namedtuple
  8. from line_profiler import LineProfiler
  9.  
  10.  
  11. try:
  12. range = xrange
  13. except NameError:
  14. pass
  15.  
  16.  
  17. Area = namedtuple('Area', ['x', 'y'])
  18. A = Area
  19. Point = namedtuple('Point', ['x', 'y'])
  20. P = Point
  21.  
  22. profiler = LineProfiler()
  23.  
  24.  
  25. class Board(object):
  26.  
  27. def __init__(self, seed_or_area, fill=False):
  28. if isinstance(seed_or_area, Area):
  29. self = self.make(seed_or_area, fill)
  30. return
  31. self.seed = seed_or_area
  32. self.grid = deepcopy(self.seed)
  33.  
  34. @classmethod
  35. def make(cls, area, fill=False):
  36. return cls([[fill for _ in range(area.x)]
  37. for _ in range(area.y)])
  38.  
  39. @classmethod
  40. def make_random(cls, area):
  41. return cls([[random.choice([True, False]) for _ in range(area.x)]
  42. for _ in range(area.y)])
  43.  
  44. @classmethod
  45. def parse(cls, s, alive='o'):
  46. return cls([[cell == alive for cell in row] for row in s.split('\n') if row])
  47.  
  48. @property
  49. def width(self):
  50. return len(self.grid[0])
  51.  
  52. @property
  53. def height(self):
  54. return len(self.grid)
  55.  
  56. @property
  57. def area(self):
  58. return Area(x=self.width,
  59. y=self.height)
  60.  
  61. def __repr__(self):
  62. return '<{}.{} {}x{} at 0x{:x}>'.format(
  63. __name__,
  64. self.__class__.__name__,
  65. self.width,
  66. self.height,
  67. hash(self),
  68. )
  69.  
  70. def __str__(self):
  71. return '\n'.join(''.join('o' if cell else '-' for cell in row) for row in self.grid)
  72.  
  73. def __getitem__(self, key):
  74. return self.grid[key]
  75.  
  76. # @profile
  77. # def get_neighbor_points(self, point):
  78. # for other in (Point(x=point.x+x_offset, y=point.y+y_offset)
  79. # for x_offset in range(-1, 2)
  80. # for y_offset in range(-1, 2)):
  81. # if other == point:
  82. # continue
  83. # if not -1 < other.x < self.width:
  84. # continue
  85. # if not -1 < other.y < self.height:
  86. # continue
  87. # yield other
  88.  
  89. @profile
  90. def get_all_neighbor_points(self, point):
  91. yield Point(x=point.x-1, y=point.y-1)
  92. yield Point(x=point.x, y=point.y-1)
  93. yield Point(x=point.x+1, y=point.y-1)
  94. yield Point(x=point.x-1, y=point.y)
  95. yield Point(x=point.x+1, y=point.y)
  96. yield Point(x=point.x-1, y=point.y+1)
  97. yield Point(x=point.x, y=point.y+1)
  98. yield Point(x=point.x+1, y=point.y+1)
  99.  
  100. @profile
  101. def get_neighbor_points(self, point):
  102. for pt in self.get_all_neighbor_points(point):
  103. if not -1 < pt.x < self.width:
  104. continue
  105. if not -1 < pt.y < self.height:
  106. continue
  107. yield pt
  108.  
  109. @profile
  110. def get_neighbors(self, point):
  111. return (self.grid[pt.y][pt.x] for pt in self.get_neighbor_points(point))
  112.  
  113. @property
  114. def cell_count(self):
  115. return self.width * self.height
  116.  
  117. @property
  118. def alive(self):
  119. return sum(cell for row in self.grid for cell in row)
  120.  
  121. @property
  122. def dead(self):
  123. return self.cell_count - self.alive
  124.  
  125.  
  126.  
  127. class ConwaysGameOfLife(object):
  128.  
  129. def __init__(self, seed_or_board):
  130. self.board = seed_or_board if isinstance(seed_or_board, Board) else Board(seed_or_board)
  131. self.generation = 0
  132.  
  133. def __getitem__(self, key):
  134. return self.board[key]
  135.  
  136. def __getattr__(self, attr):
  137. return getattr(self.board, attr)
  138.  
  139. @profile
  140. def age(self, generations=1):
  141. new_grid = deepcopy(self.board.grid)
  142. for x in range(self.width):
  143. for y in range(self.height):
  144. pt = Point(x=x, y=y)
  145. neighbors = self.get_neighbors(pt)
  146. alive = sum(neighbors)
  147.  
  148. if alive < 2:
  149. living = False
  150. elif alive > 3:
  151. living = False
  152. elif alive == 3:
  153. living = True
  154. else:
  155. living = None
  156.  
  157. if living is not None:
  158. new_grid[pt.y][pt.x] = living
  159.  
  160. self.board.grid = new_grid
  161.  
  162. self.generation += 1
  163.  
  164.  
  165. def prompt(window, options):
  166. window.clear()
  167. s = '\n'.join('({}) {}'.format(opt[0], opt[1]) for opt in enumerate(options))
  168. window.addstr(0, 0, s)
  169. y, x = window.getmaxyx()
  170. window.move(y-1, x-1)
  171. choice = int(window.getkey())
  172. return choice
  173.  
  174.  
  175. def inner_main(window):
  176. y, x = window.getmaxyx()
  177. area = A(x=x-1, y=y-1)
  178. idx = prompt(window, ['All alive', 'Random', 'Common seed'])
  179. if idx == 0:
  180. seed = Board.make(area)
  181. elif idx == 1:
  182. seed = Board.make_random(area)
  183. else:
  184. seed = COMMON
  185. curses.noecho()
  186. curses.cbreak()
  187. window.nodelay(True)
  188. window.clear()
  189. bottom_row = y - 1
  190. game = ConwaysGameOfLife(seed)
  191. fmt = 'Generation: {} | A/D/T: {}/{}/{} | {:2.2%} alive'
  192. while True:
  193. window.clear()
  194. window.addstr(0, 0, str(game.board))#, curses.A_NORMAL)
  195. # for x in range(game.width):
  196. # for y in range(game.height):
  197. # alive = game[y][x]
  198. # ch = ord('o' if alive else '-')
  199. # window.addch(y, x, ch)
  200. window.addstr(bottom_row, 0, fmt.format(
  201. game.generation,
  202. game.alive,
  203. game.dead,
  204. game.cell_count,
  205. float(game.alive) / game.cell_count,
  206. ))#, curses.A_REVERSE | curses.A_DIM)
  207. y, x = window.getmaxyx()
  208. window.move(y-1, x-1)
  209. game.age()
  210. window.refresh()
  211. sleep(.01)
  212. c = window.getch()
  213. if c > 0 and chr(c) == 'q':
  214. return
  215.  
  216. def main():
  217. curses.wrapper(inner_main)
  218.  
  219.  
  220. COMMON = Board.parse("""
  221. --------------------------------------
  222. -oo---oo----oo---oo----o---------oo---
  223. -oo--o--o--o--o--o-o---o----ooo--o----
  224. ------oo----o-o---o----o---ooo------o-
  225. -------------o---------------------oo-
  226. --------------------------------------
  227. --------------------------------------
  228. -----o-----o--------------------------
  229. -----o-----o--------------------------
  230. -----oo---oo--------------------------
  231. --------------------------------------
  232. -ooo--oo-oo--ooo----------------------
  233. ---o-o-o-o-o-o------------------------
  234. -----oo---oo--------------------------
  235. --------------------------------------
  236. -----oo---oo--------------------------
  237. ---o-o-o-o-o-o------------------------
  238. -ooo--oo-oo--ooo----------------------
  239. --------------------------------------
  240. -----oo---oo--------------------------
  241. -----o-----o--------------------------
  242. -----o-----o--------------------------
  243. --------------------------------------
  244. """)
  245.  
  246.  
  247. if __name__ == '__main__':
  248. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement