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

Поисковые слова: tail
snake: 8e75e931bfd2 snake.py

snake

view snake.py @ 134:8e75e931bfd2

example.snake: better rules for chasing enemy tail
author Daniil Alexeyevsky <me.dendik@gmail.com>
date Mon, 20 Dec 2010 17:01:39 +0300
parents bc310be50e73
children cd7658cb90eb
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 if self.cells == []:
72 return
73 for cell in self.cells:
74 cell.type = 'body'
75 self.cells[0].type = 'head'
76 self.cells[-1].type = 'tail'
78 class Rule(object):
79 """Rule defining possible behaviour of snake."""
81 codes = {
82 'h': 'head',
83 'b': 'body',
84 't': 'tail',
85 '#': 'wall',
86 ' ': 'any',
87 '-': 'empty',
88 }
90 def __init__ (self, snake):
91 self.snake = snake
92 self.direction = (0, -1)
93 self.pattern = {}
95 def load (self, file):
96 """Load rule definition from file.
98 Ignore any leading empty lines.
99 Return self.
100 """
101 y = 0
102 for line in file:
103 line = preprocess(line)
104 if y == 0 and line == '':
105 continue
106 assert len(line) == 8, "Rule lines must be exactly 7 chars long"
107 assert line[-1] == ';', "Rule lines must end with semicolon"
108 for x, char in enumerate(line[:7]):
109 self.parse_cell(x, y, char)
110 y += 1
111 if y == 7:
112 break
113 return self
115 def parse_cell(self, x, y, char):
116 """Parse definition of cell in rule file.
118 Cell is defined by one character.
119 """
120 is_my = char.islower()
121 char = char.lower()
122 assert char in self.codes, "Illegal symbol in rule: %s" % char
123 cell = engine.Cell(x, y)
124 cell.snake = self.snake
125 cell.snake_type = None
126 if char in 'htb':
127 if is_my:
128 cell.snake_type = 'my'
129 else:
130 cell.snake_type = 'enemy'
131 if char == 'h':
132 assert (x, y) == (3, 3), "Own head must in the center of rule"
133 if (x, y) == (3, 3):
134 assert char == 'h', "In the center of rule must be own head"
135 cell.type = self.codes[char]
136 self.pattern[x, y] = cell
138 def applies (self, field, x, y):
139 """True if the rule applies in the field at position (x,y)."""
140 wall = engine.Cell(-1, -1)
141 wall.type = 'void'
143 for px, fx in zip(range(7), range(x - 3, x + 4)):
144 for py, fy in zip(range(7), range(y - 3, y + 4)):
145 if field.get((fx, fy), wall) != self.pattern[px, py]:
146 return False
147 return True
149 def rotate (self, direction):
150 """Rotate rule pattern to head in `direction`."""
151 for i in range(4):
152 if self.direction == direction:
153 return
154 self.rotate_ccw()
155 raise AssertionError("Illegal direction: %s" % direction)
157 def rotate_ccw(self):
158 """Rotate rule pattern one time counterclockwise."""
159 pattern = {}
160 for x in range(7):
161 for y in range(7):
162 pattern[y, 6 - x] = self.pattern[x, y]
163 self.pattern = pattern
164 x, y = self.direction
165 self.direction = y, -x
167 # vim: set ts=4 sts=4 sw=4 et: