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

snake

view snake.py @ 124:bc310be50e73

pattern cell always has snake_type
author Daniil Alexeyevsky <me.dendik@gmail.com>
date Mon, 20 Dec 2010 15:48:15 +0300
parents a8549a69f959
children cfe29cb793eb
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 File(object):
13 """Wrapper around file that saves the current line number."""
14 def __init__(self, file):
15 self.file = file
16 self.name = file.name
17 self.line_no = 0
18 self.iterator = self.enumerate_lines()
19 def __iter__(self):
20 return self.iterator
21 def enumerate_lines(self):
22 for line_no, line in enumerate(self.file, self.line_no):
23 self.line_no = line_no
24 yield line
26 class Snake(object):
27 """Snakes.
29 Attributes:
31 - `cells` -- list of cells belonging to the snake The first of these cells
32 becomes head, the last one becomes tail, the rest ar body. If snake has
33 only one cell, it is tail.
34 - `color` -- color of snake
35 - `rules` -- a list of Rule objects
36 """
38 def __init__ (self, cells, color):
39 self.cells = cells
40 self.color = color
41 self.rules = []
43 def load (self, file):
44 """Load snake description from file.
46 See program design docs for file syntax.
47 """
48 file = File(file)
49 try:
50 self._load(file)
51 except Exception, e:
52 raise Exception("%s:%s: %s" % (file.name, file.line_no, e))
54 def _load (self, file):
55 """Actually do the loading."""
56 for line in file:
57 magic, self.name = preprocess(line).split(' ', 1)
58 break
59 assert magic == "snake", "This is not snake file"
60 for line in file:
61 line = preprocess(line)
62 if line == 'end':
63 break
64 assert line == '', "Rules must be separated by empty lines"
65 self.rules.append(Rule(self).load(file))
67 def fill (self):
68 """Mark every cell in `self.cells` as belonging to self."""
69 for cell in self.cells:
70 cell.snake = self
71 for cell in self.cells:
72 cell.type = 'body'
73 self.cells[0].type = 'head'
74 self.cells[-1].type = 'tail'
75 return
77 class Rule(object):
78 """Rule defining possible behaviour of snake."""
80 codes = {
81 'h': 'head',
82 'b': 'body',
83 't': 'tail',
84 '#': 'wall',
85 ' ': 'any',
86 '-': 'empty',
87 }
89 def __init__ (self, snake):
90 self.snake = snake
91 self.direction = (0, -1)
92 self.pattern = {}
94 def load (self, file):
95 """Load rule definition from file.
97 Ignore any leading empty lines.
98 Return self.
99 """
100 y = 0
101 for line in file:
102 line = preprocess(line)
103 if y == 0 and line == '':
104 continue
105 assert len(line) == 8, "Rule lines must be exactly 7 chars long"
106 assert line[-1] == ';', "Rule lines must end with semicolon"
107 for x, char in enumerate(line[:7]):
108 self.parse_cell(x, y, char)
109 y += 1
110 if y == 7:
111 break
112 return self
114 def parse_cell(self, x, y, char):
115 """Parse definition of cell in rule file.
117 Cell is defined by one character.
118 """
119 is_my = char.islower()
120 char = char.lower()
121 assert char in self.codes, "Illegal symbol in rule: %s" % char
122 cell = engine.Cell(x, y)
123 cell.snake = self.snake
124 cell.snake_type = None
125 if char in 'htb':
126 if is_my:
127 cell.snake_type = 'my'
128 else:
129 cell.snake_type = 'enemy'
130 if char == 'h':
131 assert (x, y) == (3, 3), "Own head must in the center of rule"
132 if (x, y) == (3, 3):
133 assert char == 'h', "In the center of rule must be own head"
134 cell.type = self.codes[char]
135 self.pattern[x, y] = cell
137 def applies (self, field, x, y):
138 """True if the rule applies in the field at position (x,y)."""
139 wall = engine.Cell(-1, -1)
140 wall.type = 'void'
142 for px, fx in zip(range(7), range(x - 3, x + 4)):
143 for py, fy in zip(range(7), range(y - 3, y + 4)):
144 if field.get((fx, fy), wall) != self.pattern[px, py]:
145 return False
146 return True
148 def rotate (self, direction):
149 """Rotate rule pattern to head in `direction`."""
150 for i in range(4):
151 if self.direction == direction:
152 return
153 self.rotate_ccw()
154 raise AssertionError("Illegal direction: %s" % direction)
156 def rotate_ccw(self):
157 """Rotate rule pattern one time counterclockwise."""
158 pattern = {}
159 for x in range(7):
160 for y in range(7):
161 pattern[y, 6 - x] = self.pattern[x, y]
162 self.pattern = pattern
163 x, y = self.direction
164 self.direction = y, -x
166 # vim: set ts=4 sts=4 sw=4 et: