DEATH

a multiplayer variant of conways game of LIFE
git clone https://git.ce9e.org/DEATH.git

commit
2a886d021ab0079e1c7155a1829c859d9c1166b3
parent
7b45ad2e1f1526b3d3a91208eea2bb7323499d0c
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2018-09-14 12:34
major refactoring

Diffstat

D DEATH/DeathCliMenu.py 191 ------------------------------------------------------------
M DEATH/__init__.py 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A DEATH/__main__.py 3 +++
D DEATH/abk.py 8 --------
D DEATH/death.py 69 ------------------------------------------------------------
D DEATH/death_ui.py 153 ------------------------------------------------------------
D DEATH/matrix.py 103 ------------------------------------------------------------
A DEATH/rules.py 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D DEATH/win.py 41 -----------------------------------------

9 files changed, 230 insertions, 565 deletions


diff --git a/DEATH/DeathCliMenu.py b/DEATH/DeathCliMenu.py

@@ -1,191 +0,0 @@
    1    -1 #!/usr/bin/env python
    2    -1 # -*- coding: utf-8 -*-
    3    -1 
    4    -1 import curses
    5    -1 from death_ui import DeathUI
    6    -1 from death import Death
    7    -1 from matrix import Map
    8    -1 
    9    -1 help = """
   10    -1 Welcome to DEATH !
   11    -1 DEATH is a variant to Conways game of LIFE.
   12    -1 Every LIFE game can be described by two sets of numbers:
   13    -1 What I added is mulitiplayer support:
   14    -1 * numbers of friendly neighbors for a friendly item to survive
   15    -1 * numbers of friendly neighbors for a friendly item to be born
   16    -1 * numbers of friendly neighbors for a foe item to be killed
   17    -1 the players take turns.
   18    -1 
   19    -1 CONTROLS:
   20    -1 arrow-keys - move cursor
   21    -1 space      - toggle field value
   22    -1 
   23    -1 backspace  - clear field value
   24    -1 return     - submit
   25    -1 
   26    -1 
   27    -1 h          - display this help screen
   28    -1 escape     - quit
   29    -1 
   30    -1 return with any key
   31    -1 """
   32    -1 
   33    -1 
   34    -1 class Crs(object):
   35    -1 	def __init__(self, screen):
   36    -1 		self.screen = screen
   37    -1 		self.screen.clear()
   38    -1 		curses.curs_set(0)
   39    -1 		self.screen.keypad(1)
   40    -1 		curses.start_color()
   41    -1 		curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
   42    -1 		curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
   43    -1 
   44    -1 	def run(self):
   45    -1 		while self.main():
   46    -1 			pass
   47    -1 
   48    -1 	def main(self):
   49    -1 		x0 = (self.screen.getmaxyx()[1] - 20) / 2
   50    -1 		y0 = (self.screen.getmaxyx()[0] - 2) / 2
   51    -1 		# n
   52    -1 		self.screen.clear()
   53    -1 		n = 1
   54    -1 		while 1:
   55    -1 			self.screen.addstr(y0, x0, 'number of players: %s' % n,
   56    -1 				curses.color_pair(2))
   57    -1 			key = self.screen.getch()
   58    -1 			if key == curses.KEY_UP:
   59    -1 				n += 1
   60    -1 			elif key == curses.KEY_DOWN:
   61    -1 				if n > 1:
   62    -1 					n -= 1
   63    -1 			elif key == ord('h'):
   64    -1 				self.screen.clear()
   65    -1 				self.screen.addstr(0, 0, help, curses.color_pair(2))
   66    -1 				self.screen.getch()
   67    -1 				self.screen.clear()
   68    -1 			elif key == ord('\n'):
   69    -1 				break
   70    -1 			elif key == 27:
   71    -1 				return False
   72    -1 		# map size
   73    -1 		self.screen.clear()
   74    -1 		rows = 10
   75    -1 		while 1:
   76    -1 			self.screen.addstr(y0, x0, 'number of rows: %s' % rows,
   77    -1 				curses.color_pair(2))
   78    -1 			key = self.screen.getch()
   79    -1 			if key == curses.KEY_UP:
   80    -1 				if rows < self.screen.getmaxyx()[0] - 2:
   81    -1 					rows += 1
   82    -1 			elif key == curses.KEY_DOWN:
   83    -1 				if rows > 1:
   84    -1 					rows -= 1
   85    -1 			elif key == ord('h'):
   86    -1 				self.screen.clear()
   87    -1 				self.screen.addstr(0, 0, help, curses.color_pair(2))
   88    -1 				self.screen.getch()
   89    -1 				self.screen.clear()
   90    -1 			elif key == ord('\n'):
   91    -1 				break
   92    -1 			elif key == 27:
   93    -1 				return False
   94    -1 		cols = 10
   95    -1 		while 1:
   96    -1 			self.screen.addstr(y0, x0, 'number of columns: %s' % cols,
   97    -1 				curses.color_pair(2))
   98    -1 			key = self.screen.getch()
   99    -1 			if key == curses.KEY_UP:
  100    -1 				if cols < self.screen.getmaxyx()[1] / 2 - 1:
  101    -1 					cols += 1
  102    -1 			elif key == curses.KEY_DOWN:
  103    -1 				if cols > 1:
  104    -1 					cols -= 1
  105    -1 			elif key == ord('h'):
  106    -1 				self.screen.clear()
  107    -1 				self.screen.addstr(0, 0, help, curses.color_pair(2))
  108    -1 				self.screen.getch()
  109    -1 				self.screen.clear()
  110    -1 			elif key == ord('\n'):
  111    -1 				break
  112    -1 			elif key == 27:
  113    -1 				return False
  114    -1 		# alive born kill
  115    -1 		"""
  116    -1 			Diplay manu for every user
  117    -1 			and append the results to the three lists afterwards
  118    -1 		"""
  119    -1 		alive = []
  120    -1 		born = []
  121    -1 		kill = []
  122    -1 		for player in range(n):
  123    -1 			abk = [[], [], []]
  124    -1 			_abk = 0
  125    -1 			_i = 0
  126    -1 			while 1:
  127    -1 				self.screen.clear()
  128    -1 				self.screen.addstr(y0 - 1, x0 - 10, 'Player %s' % str(player + 1),
  129    -1 					curses.color_pair(2))
  130    -1 				self.screen.addstr(y0, x0 - 10, 'alive', curses.color_pair(2))
  131    -1 				self.screen.addstr(y0 + 1, x0 - 10, 'born', curses.color_pair(2))
  132    -1 				self.screen.addstr(y0 + 2, x0 - 10, 'kill', curses.color_pair(2))
  133    -1 				for i in range(9):
  134    -1 					self.screen.addstr(y0 - 1, x0 + 2*i, str(i), curses.color_pair(2))
  135    -1 					for __abk in range(3):
  136    -1 						if _abk == __abk and _i == i:
  137    -1 							color = curses.color_pair(1)
  138    -1 						else:
  139    -1 							color = curses.color_pair(2)
  140    -1 						if i in abk[__abk]:
  141    -1 							self.screen.addstr(y0 + __abk, x0 + 2*i, 'X', color)
  142    -1 						else:
  143    -1 							self.screen.addstr(y0 + __abk, x0 + 2*i, ' ', color)
  144    -1 
  145    -1 				key = self.screen.getch()
  146    -1 				if key == curses.KEY_UP:
  147    -1 					if _abk > 0:
  148    -1 						_abk -= 1
  149    -1 				elif key == curses.KEY_DOWN:
  150    -1 					if _abk < 2:
  151    -1 						_abk += 1
  152    -1 				if key == curses.KEY_LEFT:
  153    -1 					if _i > 0:
  154    -1 						_i -= 1
  155    -1 				elif key == curses.KEY_RIGHT:
  156    -1 					if _i < 10 - 1:
  157    -1 						_i += 1
  158    -1 				elif key == ord(' '):
  159    -1 					if _i in abk[_abk]:
  160    -1 						abk[_abk] = filter(lambda x: x != _i, abk[_abk])
  161    -1 					else:
  162    -1 						abk[_abk].append(_i)
  163    -1 				elif key == curses.KEY_BACKSPACE:
  164    -1 					abk[_abk] = filter(lambda x: x != _i, abk[_abk])
  165    -1 				elif key == ord('h'):
  166    -1 					self.screen.clear()
  167    -1 					self.screen.addstr(0, 0, help, curses.color_pair(2))
  168    -1 					self.screen.getch()
  169    -1 					self.screen.clear()
  170    -1 				elif key == ord('\n'):
  171    -1 					break
  172    -1 				elif key == 27:
  173    -1 					return False
  174    -1 			alive.append(abk[0])
  175    -1 			born.append(abk[1])
  176    -1 			kill.append(abk[2])
  177    -1 
  178    -1 		_map = Map(rows, cols)
  179    -1 		d = Death(_map, n, alive, born, kill)
  180    -1 		DeathUI(self.screen, d, title='default')
  181    -1 		return True
  182    -1 
  183    -1 
  184    -1 if __name__ == '__main__':
  185    -1 	screen = curses.initscr()
  186    -1 	crs = Crs(screen)
  187    -1 	try:
  188    -1 		crs.run()
  189    -1 	except Exception as ex:
  190    -1 		print(ex)
  191    -1 	curses.endwin()

diff --git a/DEATH/__init__.py b/DEATH/__init__.py

@@ -0,0 +1,160 @@
   -1     1 from . import rules
   -1     2 
   -1     3 try:
   -1     4 	from ncurses import curses
   -1     5 except ImportError:
   -1     6 	import curses
   -1     7 
   -1     8 
   -1     9 class Screen:
   -1    10 	def __init__(self):
   -1    11 		self.screen = curses.initscr()
   -1    12 		self.screen.keypad(1)
   -1    13 		curses.curs_set(0)
   -1    14 		curses.noecho()
   -1    15 
   -1    16 	def __enter__(self):
   -1    17 		return self.screen
   -1    18 
   -1    19 	def __exit__(self, *args):
   -1    20 		curses.endwin()
   -1    21 
   -1    22 
   -1    23 class Grid:
   -1    24 	def __init__(self, rows, cols):
   -1    25 		self.rows = rows
   -1    26 		self.cols = cols
   -1    27 		self.data = []
   -1    28 		for y in range(rows):
   -1    29 			self.data.append([])
   -1    30 			for x in range(cols):
   -1    31 				self.data[y].append(None)
   -1    32 
   -1    33 	def set(self, y, x, value):
   -1    34 		self.data[y][x] = value
   -1    35 
   -1    36 	def get(self, y, x):
   -1    37 		if y < 0 or x < 0:
   -1    38 			raise IndexError
   -1    39 		return self.data[y][x]
   -1    40 
   -1    41 	def apply(self, f):
   -1    42 		result = Grid(self.rows, self.cols)
   -1    43 		for y in range(self.rows):
   -1    44 			for x in range(self.cols):
   -1    45 				result.set(y, x, f(self, y, x))
   -1    46 		self.data = result.data
   -1    47 
   -1    48 	def count(self, value):
   -1    49 		count = 0
   -1    50 		for row in self.data:
   -1    51 			for cell in row:
   -1    52 				if cell == value:
   -1    53 					count += 1
   -1    54 		return count
   -1    55 
   -1    56 	def count_neighbors(self, y, x, value, diagonal=True):
   -1    57 		coods = [
   -1    58 			(y + 1, x),
   -1    59 			(y, x + 1),
   -1    60 			(y - 1, x),
   -1    61 			(y, x - 1),
   -1    62 		]
   -1    63 		if diagonal:
   -1    64 			coods += [
   -1    65 				(y + 1, x + 1),
   -1    66 				(y + 1, x - 1),
   -1    67 				(y - 1, x + 1),
   -1    68 				(y - 1, x - 1),
   -1    69 			]
   -1    70 
   -1    71 		count = 0
   -1    72 		for yy, xx in coods:
   -1    73 			if yy in range(self.rows) and xx in range(self.cols):
   -1    74 				if self.get(yy, xx) == value:
   -1    75 					count += 1
   -1    76 		return count
   -1    77 
   -1    78 
   -1    79 class Game:
   -1    80 	def __init__(self, rows, cols, players, rules, screen):
   -1    81 		self.grid = Grid(rows, cols)
   -1    82 		self.players = players
   -1    83 		self.player = 0
   -1    84 		self.rules = rules
   -1    85 		self.screen = screen
   -1    86 		self.cursor_y = 0
   -1    87 		self.cursor_x = 0
   -1    88 
   -1    89 	def draw(self):
   -1    90 		for y in range(self.grid.rows):
   -1    91 			for x in range(self.grid.cols):
   -1    92 				value = self.grid.get(y, x)
   -1    93 				if value is None:
   -1    94 					ch = ' '
   -1    95 				else:
   -1    96 					ch = str(value)
   -1    97 				attr = curses.A_NORMAL
   -1    98 				if y == self.cursor_y and x == self.cursor_x:
   -1    99 					attr |= curses.A_REVERSE
   -1   100 				if value == self.player:
   -1   101 					attr |= curses.A_BOLD
   -1   102 				self.screen.addch(y, x, ch, attr)
   -1   103 
   -1   104 	def step(self):
   -1   105 		def f(grid, y, x):
   -1   106 			neighbors = grid.count_neighbors(
   -1   107 				y, x, self.player, diagonal=self.rules.diagonal)
   -1   108 			value = grid.get(y, x)
   -1   109 
   -1   110 			if value is None:
   -1   111 				if neighbors in self.rules.born:
   -1   112 					return self.player
   -1   113 			elif value == self.player:
   -1   114 				if neighbors not in self.rules.alive:
   -1   115 					return None
   -1   116 			else:
   -1   117 				if neighbors in self.rules.kill:
   -1   118 					return None
   -1   119 			return value
   -1   120 
   -1   121 		self.grid.apply(f)
   -1   122 
   -1   123 	def next_player(self):
   -1   124 		self.player = (self.player + 1) % self.players
   -1   125 
   -1   126 	def run(self):
   -1   127 		self.draw()
   -1   128 		while True:
   -1   129 			key = self.screen.getch()
   -1   130 			if key == curses.KEY_DOWN:
   -1   131 				if self.cursor_y + 1 < self.grid.rows:
   -1   132 					self.cursor_y += 1
   -1   133 			elif key == curses.KEY_UP:
   -1   134 				if self.cursor_y > 0:
   -1   135 					self.cursor_y -= 1
   -1   136 			elif key == curses.KEY_RIGHT:
   -1   137 				if self.cursor_x + 1 < self.grid.cols:
   -1   138 					self.cursor_x += 1
   -1   139 			elif key == curses.KEY_LEFT:
   -1   140 				if self.cursor_x > 0:
   -1   141 					self.cursor_x -= 1
   -1   142 			elif key == ord(' '):
   -1   143 				value = self.grid.get(self.cursor_y, self.cursor_x)
   -1   144 				if value is None:
   -1   145 					self.grid.set(self.cursor_y, self.cursor_x, self.player)
   -1   146 				elif value == self.player:
   -1   147 					self.grid.set(self.cursor_y, self.cursor_x, None)
   -1   148 				self.next_player()
   -1   149 			elif key == ord('\n'):
   -1   150 				self.step()
   -1   151 				self.next_player()
   -1   152 			elif key == ord('q'):
   -1   153 				return
   -1   154 			self.draw()
   -1   155 
   -1   156 
   -1   157 def main():
   -1   158 	with Screen() as screen:
   -1   159 		game = Game(20, 20, 2, rules.Conway, screen)
   -1   160 		game.run()

diff --git a/DEATH/__main__.py b/DEATH/__main__.py

@@ -0,0 +1,3 @@
   -1     1 from . import main
   -1     2 
   -1     3 main()

diff --git a/DEATH/abk.py b/DEATH/abk.py

@@ -1,8 +0,0 @@
    1    -1 #!/usr/bin/env python
    2    -1 # -*- coding: utf-8 -*-
    3    -1 
    4    -1 "alive|born|kill"
    5    -1 
    6    -1 
    7    -1 static_borders1 = [[0, 1, 2, 3, 4, 5, 6, 7, 8], [3, 4], [4, 5, 6, 7, 8]]
    8    -1 conway = [[2, 3], [3], []]

diff --git a/DEATH/death.py b/DEATH/death.py

@@ -1,69 +0,0 @@
    1    -1 #!/usr/bin/env python
    2    -1 # -*- coding: utf-8 -*-
    3    -1 
    4    -1 """
    5    -1 mulitplayer life
    6    -1 
    7    -1 in life you define the rules by giving two lists if ints
    8    -1 alive [2,3] - numbers of neighbors for an item to survive
    9    -1 born   [3]  - numbers of neighbors for an item to be born
   10    -1 
   11    -1 in multiplayer this gets more complicated.
   12    -1 here's what i thought of:
   13    -1 alive - number of friendly neighbors for a frinedly item to survive
   14    -1 born  - number of friendly neighbors for a friendly item to be born
   15    -1 kill  - number of friendly neighbors for a foe item to be killed
   16    -1 this happens in turns
   17    -1 """
   18    -1 
   19    -1 from matrix import Map
   20    -1 
   21    -1 
   22    -1 class Death(object):
   23    -1 	def __init__(self, _map, n=1, alive=[[2, 3]], born=[[3]], kill=[[]],
   24    -1 			win=lambda _map, n: None):
   25    -1 		# the defaults make death the standart life
   26    -1 		self.n = n
   27    -1 		self.alive = alive
   28    -1 		self.born = born
   29    -1 		self.kill = kill
   30    -1 		self.map = _map
   31    -1 		self.player = 0
   32    -1 		self._win = win
   33    -1 
   34    -1 	def step_one(self, player):
   35    -1 		# main logic of the game
   36    -1 		def f(x):
   37    -1 			if x[0] < 0:
   38    -1 				if x[1] in self.born[player]:
   39    -1 					return player
   40    -1 				else:
   41    -1 					return x[0]
   42    -1 			elif x[0] == player:
   43    -1 				if x[1] in self.alive[player]:
   44    -1 					return x[0]
   45    -1 				else:
   46    -1 					return -1
   47    -1 			else:
   48    -1 				if x[1] in self.kill[player]:
   49    -1 					return -1
   50    -1 				else:
   51    -1 					return x[0]
   52    -1 		self.map.join([self.map, self.map.neighbors([player])])
   53    -1 		self.map.apply_f(f)
   54    -1 
   55    -1 	def step(self):
   56    -1 		for player in range(self.n):
   57    -1 			self.step_one(player)
   58    -1 
   59    -1 	def next(self):
   60    -1 		self.player = (self.player + 1) % self.n
   61    -1 
   62    -1 	def count(self):
   63    -1 		c = []
   64    -1 		for player in range(self.n):
   65    -1 			c.append(self.map.count(player))
   66    -1 		return c
   67    -1 
   68    -1 	def win(self):
   69    -1 		return self._win(self.map, self.n)

diff --git a/DEATH/death_ui.py b/DEATH/death_ui.py

@@ -1,153 +0,0 @@
    1    -1 #!/usr/bin/env python
    2    -1 # -*- coding: utf-8 -*-
    3    -1 
    4    -1 import curses
    5    -1 
    6    -1 from matrix import Map
    7    -1 from death import Death
    8    -1 import win
    9    -1 import abk
   10    -1 
   11    -1 help = """
   12    -1 Welcome to DEATH !
   13    -1 DEATH is a variant to Conways game of LIFE.
   14    -1 Every LIFE game can be described by two sets of numbers:
   15    -1 What I added is mulitiplayer support:
   16    -1 * numbers of friendly neighbors for a friendly item to survive
   17    -1 * numbers of friendly neighbors for a friendly item to be born
   18    -1 * numbers of friendly neighbors for a foe item to be killed
   19    -1 the players take turns.
   20    -1 
   21    -1 CONTROLS:
   22    -1 arrow-keys - move cursor
   23    -1 space      - toggle field value
   24    -1              after that it is the next players' turn
   25    -1 backspace  - clear field value
   26    -1 return     - perform a full step (one for every player)
   27    -1 tab        - perform a single step (only for the active player)
   28    -1              after that it is the next players' turn
   29    -1 h          - display this help screen
   30    -1 escape     - return to menu
   31    -1 
   32    -1 return with any key
   33    -1 """
   34    -1 
   35    -1 
   36    -1 class DeathUI(object):
   37    -1 	def __init__(self, screen, death, title=''):
   38    -1 		self.screen = screen
   39    -1 		self.death = death
   40    -1 		self.title = title
   41    -1 		self.screen.clear()
   42    -1 		curses.curs_set(0)
   43    -1 		self.screen.keypad(1)
   44    -1 		curses.start_color()
   45    -1 		curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
   46    -1 		curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
   47    -1 		self.row = 0
   48    -1 		self.col = 0
   49    -1 
   50    -1 	def run(self):
   51    -1 		self.draw()
   52    -1 		while self.mainloop():
   53    -1 			winner = self.death.win()
   54    -1 			if winner:
   55    -1 				print('Player %s wins!' % (winner + 1))
   56    -1 				self.screen.getch()
   57    -1 				break
   58    -1 
   59    -1 	def draw(self):
   60    -1 		w = 2 * self.death.map.cols - 1
   61    -1 		h = self.death.map.rows
   62    -1 		x0 = (self.screen.getmaxyx()[1] - w) / 2
   63    -1 		y0 = (self.screen.getmaxyx()[0] - h) / 2
   64    -1 		# margin
   65    -1 		for x in range(w):
   66    -1 			self.screen.addstr(y0 - 1, x0 + x, '-', curses.color_pair(2))
   67    -1 			self.screen.addstr(y0 + h, x0 + x, '-', curses.color_pair(2))
   68    -1 		for y in range(h):
   69    -1 			self.screen.addstr(y0 + y, x0 - 1, '|', curses.color_pair(2))
   70    -1 			self.screen.addstr(y0 + y, x0 + w, '|', curses.color_pair(2))
   71    -1 		self.screen.addstr(y0 + h, x0 + w, str(self.death.player + 1),
   72    -1 			curses.color_pair(2))
   73    -1 		# count
   74    -1 		self.screen.addstr(y0 - 1, x0 + 2,
   75    -1 			'|'.join([str(a) for a in self.death.count()]),
   76    -1 			curses.color_pair(2))
   77    -1 		# title
   78    -1 		self.screen.addstr(y0 - 1, x0 + w - len(self.title), self.title,
   79    -1 			curses.color_pair(2))
   80    -1 		# map
   81    -1 		for i in range(self.death.map.rows):
   82    -1 			for j in range(self.death.map.cols):
   83    -1 				field = self.death.map.getitem(i, j)
   84    -1 				if field < 0:
   85    -1 					s = ' '
   86    -1 				else:
   87    -1 					s = str(field + 1)
   88    -1 				if i == self.row and j == self.col:
   89    -1 					self.screen.addstr(y0 + i, x0 + 2*j, s, curses.color_pair(1))
   90    -1 				else:
   91    -1 					self.screen.addstr(y0 + i, x0 + 2*j, s, curses.color_pair(2))
   92    -1 
   93    -1 	def mainloop(self):
   94    -1 		key = self.screen.getch()
   95    -1 		if key == curses.KEY_DOWN:
   96    -1 			if self.row < self.death.map.rows - 1:
   97    -1 				self.row += 1
   98    -1 		elif key == curses.KEY_UP:
   99    -1 			if self.row > 0:
  100    -1 				self.row -= 1
  101    -1 		elif key == curses.KEY_RIGHT:
  102    -1 			if self.col < self.death.map.cols - 1:
  103    -1 				self.col += 1
  104    -1 		elif key == curses.KEY_LEFT:
  105    -1 			if self.col > 0:
  106    -1 				self.col -= 1
  107    -1 		elif key == ord(' '):
  108    -1 			self.death.map.setitem(self.row, self.col, self.death.player)
  109    -1 			self.death.next()
  110    -1 		elif key == curses.KEY_BACKSPACE:
  111    -1 			self.death.map.clear(self.row, self.col)
  112    -1 		elif key == ord('\n'):
  113    -1 			self.death.step()
  114    -1 		elif key == ord('\t'):
  115    -1 			self.death.step_one(self.death.player)
  116    -1 			self.death.next()
  117    -1 		elif key == ord('h'):
  118    -1 			self.screen.clear()
  119    -1 			self.screen.addstr(0, 0, help, curses.color_pair(2))
  120    -1 			self.screen.getch()
  121    -1 			self.screen.clear()
  122    -1 			self.draw()
  123    -1 		elif key == 27:
  124    -1 			self.screen.clear()
  125    -1 			return False
  126    -1 		self.screen.clear()
  127    -1 		self.draw()
  128    -1 		return True
  129    -1 
  130    -1 
  131    -1 def main():
  132    -1 	screen = curses.initscr()
  133    -1 	map = Map(rows, cols)
  134    -1 	alive = []
  135    -1 	born = []
  136    -1 	kill = []
  137    -1 	for player in range(n):
  138    -1 		alive.append(abk.conway[0])
  139    -1 		born.append(abk.conway[1])
  140    -1 		kill.append(abk.conway[2])
  141    -1 	death = Death(map, n, alive, born, kill, win.economy)
  142    -1 
  143    -1 	ui = DeathUI(screen, death)
  144    -1 
  145    -1 	try:
  146    -1 		ui.run()
  147    -1 	except Exception as ex:
  148    -1 		print(ex)
  149    -1 	curses.endwin()
  150    -1 
  151    -1 
  152    -1 if __name__ == '__main__':
  153    -1 	main()

diff --git a/DEATH/matrix.py b/DEATH/matrix.py

@@ -1,103 +0,0 @@
    1    -1 #!/usr/bin/env python
    2    -1 # -*- coding: utf-8 -*-
    3    -1 
    4    -1 
    5    -1 class Matrix(object):
    6    -1 	def __init__(self, rows, cols, value=-1):
    7    -1 		self.rows = rows
    8    -1 		self.cols = cols
    9    -1 		self.value = value
   10    -1 		self.data = []
   11    -1 		for i in range(rows):
   12    -1 			self.data.append([])
   13    -1 			for j in range(cols):
   14    -1 				self.data[i].append(value)
   15    -1 
   16    -1 	def setitem(self, row, col, value):
   17    -1 		self.data[row][col] = value
   18    -1 
   19    -1 	def getitem(self, row, col):
   20    -1 		if row < 0 or col < 0:
   21    -1 			raise IndexError
   22    -1 		return self.data[row][col]
   23    -1 
   24    -1 	def draw(self):
   25    -1 		for row in self.data:
   26    -1 			print(row)
   27    -1 
   28    -1 	def apply_f(self, f):
   29    -1 		for i in range(self.rows):
   30    -1 			for j in range(self.cols):
   31    -1 				self.setitem(i, j, f(self.getitem(i, j)))
   32    -1 
   33    -1 	def join(self, mats):
   34    -1 		for mat in mats:
   35    -1 			if mat.rows != self.rows or mat.cols != self.cols:
   36    -1 				raise Exception
   37    -1 		for i in range(self.rows):
   38    -1 			for j in range(self.cols):
   39    -1 				self.setitem(i, j, [mat.getitem(i, j) for mat in mats])
   40    -1 
   41    -1 	def count(self, _item):
   42    -1 		c = 0
   43    -1 		for row in self.data:
   44    -1 			for item in row:
   45    -1 				if item == _item:
   46    -1 					c += 1
   47    -1 		return c
   48    -1 
   49    -1 	def save(filename, seperator=';'):
   50    -1 		f = open(filename, 'w')
   51    -1 		f.write('bla')
   52    -1 		pass  # TODO
   53    -1 		f.close()
   54    -1 
   55    -1 	def load(filename, seperator=';'):
   56    -1 		f = open(filename, 'r')
   57    -1 		pass  # TODO
   58    -1 		f.close()
   59    -1 
   60    -1 
   61    -1 class Map(Matrix):
   62    -1 	def __init__(self, rows=15, cols=15, diagonal=True, value=-1):
   63    -1 		Matrix.__init__(self, rows, cols, value)
   64    -1 		self.diagonal = diagonal
   65    -1 
   66    -1 	def clear(self, i, j):
   67    -1 		self.setitem(i, j, -1)
   68    -1 
   69    -1 	def field_neighbors(self, i, j, players):
   70    -1 		coods = [
   71    -1 			(i + 1, j),
   72    -1 			(i, j + 1),
   73    -1 			(i - 1, j),
   74    -1 			(i, j - 1),
   75    -1 		]
   76    -1 		if self.diagonal:
   77    -1 			coods += [
   78    -1 				(i + 1, j + 1),
   79    -1 				(i + 1, j - 1),
   80    -1 				(i - 1, j + 1),
   81    -1 				(i - 1, j - 1),
   82    -1 			]
   83    -1 
   84    -1 		a = 0
   85    -1 		for _row, _col in coods:
   86    -1 			if _row in range(self.rows) and _col in range(self.cols):
   87    -1 				if self.getitem(_row, _col) in players:
   88    -1 					a += 1
   89    -1 		return a
   90    -1 
   91    -1 	def neighbors(self, players):
   92    -1 		result = Matrix(self.rows, self.cols)
   93    -1 		for i in range(self.rows):
   94    -1 			for j in range(self.cols):
   95    -1 				result.setitem(i, j, self.field_neighbors(i, j,  players))
   96    -1 		return result
   97    -1 
   98    -1 	def clone(self):
   99    -1 		result = Map(self.rows, self.cols, self.diagonal, self.value)
  100    -1 		for i in range(self.rows):
  101    -1 			for j in range(self.cols):
  102    -1 				result.setitem(i, j, self.getitem(i, j))
  103    -1 		return result

diff --git a/DEATH/rules.py b/DEATH/rules.py

@@ -0,0 +1,67 @@
   -1     1 class Rules:
   -1     2 	diagonal = True
   -1     3 	alive = []
   -1     4 	born = []
   -1     5 	kill = []
   -1     6 
   -1     7 	def winner(self, grid):
   -1     8 		raise NotImplementedError
   -1     9 
   -1    10 
   -1    11 class UserDefinedRules(Rules):
   -1    12 	def __init__(self, alive, born, kill):
   -1    13 		self.alive = alive
   -1    14 		self.born = born
   -1    15 		self.kill = kill
   -1    16 
   -1    17 
   -1    18 class Conway(Rules):
   -1    19 	alive = [2, 3]
   -1    20 	born = [3]
   -1    21 
   -1    22 	def winner(self, grid):
   -1    23 		return None
   -1    24 
   -1    25 
   -1    26 class DeathMatch(UserDefinedRules):
   -1    27 	def winner(self, grid):
   -1    28 		values = []
   -1    29 		for y in range(grid.rows):
   -1    30 			for x in range(grid.cols):
   -1    31 				value = grid.get(y, x)
   -1    32 				if value is None:
   -1    33 					pass
   -1    34 				elif len(values) == 0:
   -1    35 					values.append(value)
   -1    36 				else:
   -1    37 					return None
   -1    38 		return values[0]
   -1    39 
   -1    40 
   -1    41 class CaptureTheFlag(UserDefinedRules):
   -1    42 	def winner(self, grid):
   -1    43 		flag1 = grid.get(0, 0)
   -1    44 		flag2 = grid.get(0, grid.cols - 1)
   -1    45 		flag3 = grid.get(grid.rows - 1, 0)
   -1    46 		flag4 = grid.get(grid.rows - 1, grid.cols - 1)
   -1    47 
   -1    48 		if flag1 == flag2 and flag2 == flag3 and flag3 == flag4:
   -1    49 			return flag1
   -1    50 
   -1    51 
   -1    52 class Economy(UserDefinedRules):
   -1    53 	fraction = 0.2
   -1    54 
   -1    55 	def winner(self, grid):
   -1    56 		counts = {}
   -1    57 		for y in range(grid.rows):
   -1    58 			for x in range(grid.cols):
   -1    59 				value = grid.get(y, x)
   -1    60 				if value not in counts:
   -1    61 					counts[value] = 0
   -1    62 				counts[value] += 1
   -1    63 
   -1    64 		best = max(counts, key=lambda key: counts[key])
   -1    65 		required = int(grid.rows * grid.cols * self.fraction)
   -1    66 		if best > required:
   -1    67 			return best

diff --git a/DEATH/win.py b/DEATH/win.py

@@ -1,41 +0,0 @@
    1    -1 #!/usr/bin/env python
    2    -1 # -*- coding: utf-8 -*-
    3    -1 
    4    -1 """
    5    -1 win-functions
    6    -1 * take a Map and number of players and
    7    -1 * return the id of the winnig player or None
    8    -1 """
    9    -1 
   10    -1 
   11    -1 def death_match(_map, n):
   12    -1 	"""destroy every foe unit"""
   13    -1 	winner = None
   14    -1 	for player in range(n):
   15    -1 		if _map.count(player) > 0:
   16    -1 			if winner:
   17    -1 				return None
   18    -1 			else:
   19    -1 				winner = player
   20    -1 	return winner
   21    -1 
   22    -1 
   23    -1 def capturetheflag(_map, n):
   24    -1 	"""capture the four corners"""
   25    -1 	flag1 = _map.getitem(0, 0)
   26    -1 	flag2 = _map.getitem(0, _map.cols - 1)
   27    -1 	flag3 = _map.getitem(_map.rows - 1, _map.cols - 1)
   28    -1 	flag4 = _map.getitem(_map.rows - 1, 0)
   29    -1 	if flag1 == flag2 and flag2 == flag3 and flag3 == flag4:
   30    -1 		return flag1 - 1
   31    -1 	else:
   32    -1 		return None
   33    -1 
   34    -1 
   35    -1 def economy(_map, n):
   36    -1 	"""be first to capture a given fraction of the map"""
   37    -1 	k = int(_map.rows * _map.cols / n * 0.2)  # TODO?
   38    -1 	for player in range(n):
   39    -1 		if _map.count(player) >= k:
   40    -1 			return player
   41    -1 	return None