Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/snake/file/e9c803523da4/snake.py
Дата изменения: Unknown
Дата индексирования: Sun Feb 3 08:35:22 2013
Кодировка:
snake: e9c803523da4 snake.py

snake

view snake.py @ 65:e9c803523da4

snake load methods: Python complains about mixing iterators & methods on file object; fixed that
author Danya Alexeyevsky <me.dendik@gmail.com>
date Mon, 20 Dec 2010 00:33:24 +0300
parents 27a43636ab6e
children 2d4b7e24d914
line source
1 """Guts of snakes."""
3 import engine
5 def preprocess(line):
6 """Remove comments and junk spaces from line of snake definition file."""
7 if '//' in line:
8 line = line[:line.index('//')]
9 line = line.rstrip()
10 return line
12 class Snake(object):
13 """Snakes.
15 Attributes:
17 - `cells` -- list of cells belonging to the snake The first of these cells
18 becomes head, the last one becomes tail, the rest ar body. If snake has
19 only one cell, it is tail.
20 - `color` -- color of snake
21 - `rules` -- a list of Rule objects
22 """
24 def __init__ (self, cells, color):
25 self.cells = cells
26 self.color = color
27 self.rules = []
29 def load (self, file):
30 """Load snake description from file.
32 See program design docs for file syntax.
33 """
34 for line in file:
35 magic, name = preprocess(line).split(' ', 1)
36 break
37 assert magic == "snake", "This is not snake file"
38 for line in file:
39 line = preprocess(line)
40 if line == 'end':
41 break
42 assert line == '', "Rules must be separated by empty lines"
43 self.rules.append(Rule(self).load(file))
45 def fill (self):
46 """Mark every cell in `self.cells` as belonging to self."""
47 for cell in self.cells:
48 cell.snake = self
49 snake.cells[0].type = 'head'
50 for cell in self.cells[1:-1]:
51 cell.type = 'body'
52 snake.cells[-1].type = 'tail'
53 return
55 class Rule(object):
56 """Rule defining possible behaviour of snake."""
58 codes = {
59 'h': 'head',
60 'b': 'body',
61 't': 'tail',
62 '#': 'wall',
63 ' ': 'any',
64 '-': 'empty',
65 }
67 def __init__ (self, snake):
68 self.snake = snake
69 self.direction = (1, 0)
70 self.pattern = {}
72 def load (self, file):
73 """Load rule definition from file. Ignore any leading empty lines."""
74 y = 0
75 for line in file:
76 line = preprocess(line)
77 if y == 0 and line == '':
78 continue
79 if y == 7:
80 break
81 assert len(line) == 8, "Rule lines must be exactly 7 chars long"
82 assert line[-1] == ';', "Rule lines must end with semicolon"
83 for x, char in enumerate(line[:7]):
84 self.parse_cell(x, y, char)
85 y += 1
87 def parse_cell(self, x, y, char):
88 """Parse definition of cell in rule file.
90 Cell is defined by one character.
91 """
92 assert char.lower() in self.codes, "Illegal symbol in rule: %s" % char
93 cell = engine.Cell(x, y, self.snake)
94 if char in 'htb':
95 if char.islower():
96 cell.snake_type = 'my'
97 else:
98 cell.snake_type = 'enemy'
99 if char == 'h':
100 assert (x, y) == (3, 3), "Own head must in the center of rule"
101 if (x, y) == (3, 3):
102 assert char == 'h', "In the center of rule must be own head"
103 cell.type = self.codes[char.lower()]
104 self.pattern[x, y] = cell
106 def applies (self, field, x, y):
107 """True if the rule applies in the field at position (x,y)."""
108 for px, fx in zip(range(7), range(x - 3, x + 4)):
109 for py, fy in zip(range(7), range(y - 3, y + 4)):
110 if (fx, fy) in field:
111 if field[fx, fy] != self.pattern[px, py]:
112 return False
113 else:
114 if self.pattern[px, py].type != 'any':
115 return False
116 return True
118 def rotate (self, rot):
119 """Rotate rule pattern `rot` times counterclockwise."""
120 for i in range(((rot % 4) + 4) % 4):
121 self.rotate_ccw()
123 def rotate_ccw(self):
124 """Rotate rule pattern one time counterclockwise."""
125 pattern = {}
126 for x in range(7):
127 for y in range(7):
128 pattern[y, 6 - x] = self.pattern[x, y]
129 self.pattern = pattern
130 x, y = self.direction
131 self.direction = y, -x
133 # vim: set ts=4 sts=4 sw=4 et: