Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.cmm.msu.ru/trac/snake/browser/snake.py?rev=111%3A9486211ec334&format=txt
Дата изменения: Mon Dec 20 12:58:35 2010
Дата индексирования: Fri Feb 11 19:56:38 2011
Кодировка:
"""Guts of snakes."""

import engine

def preprocess(line):
"""Remove comments and junk spaces from line of snake definition file."""
if '//' in line:
line = line[:line.index('//')]
line = line.rstrip()
return line

class Snake(object):
"""Snakes.

Attributes:

- `cells` -- list of cells belonging to the snake The first of these cells
becomes head, the last one becomes tail, the rest ar body. If snake has
only one cell, it is tail.
- `color` -- color of snake
- `rules` -- a list of Rule objects
"""

def __init__ (self, cells, color):
self.cells = cells
self.color = color
self.rules = []

def load (self, file):
"""Load snake description from file.

See program design docs for file syntax.
"""
for line in file:
magic, self.name = preprocess(line).split(' ', 1)
break
assert magic == "snake", "This is not snake file"
for line in file:
line = preprocess(line)
if line == 'end':
break
assert line == '', "Rules must be separated by empty lines"
self.rules.append(Rule(self).load(file))

def fill (self):
"""Mark every cell in `self.cells` as belonging to self."""
for cell in self.cells:
cell.snake = self
for cell in self.cells:
cell.type = 'body'
self.cells[0].type = 'head'
self.cells[-1].type = 'tail'
return

class Rule(object):
"""Rule defining possible behaviour of snake."""

codes = {
'h': 'head',
'b': 'body',
't': 'tail',
'#': 'wall',
' ': 'any',
'-': 'empty',
}

def __init__ (self, snake):
self.snake = snake
self.direction = (0, -1)
self.pattern = {}

def load (self, file):
"""Load rule definition from file.

Ignore any leading empty lines.
Return self.
"""
y = 0
for line in file:
line = preprocess(line)
if y == 0 and line == '':
continue
assert len(line) == 8, "Rule lines must be exactly 7 chars long"
assert line[-1] == ';', "Rule lines must end with semicolon"
for x, char in enumerate(line[:7]):
self.parse_cell(x, y, char)
y += 1
if y == 7:
break
return self

def parse_cell(self, x, y, char):
"""Parse definition of cell in rule file.

Cell is defined by one character.
"""
is_my = char.islower()
char = char.lower()
assert char in self.codes, "Illegal symbol in rule: %s" % char
cell = engine.Cell(x, y, self.snake)
if char in 'htb':
if is_my:
cell.snake_type = 'my'
else:
cell.snake_type = 'enemy'
if char == 'h':
assert (x, y) == (3, 3), "Own head must in the center of rule"
if (x, y) == (3, 3):
assert char == 'h', "In the center of rule must be own head"
cell.type = self.codes[char]
self.pattern[x, y] = cell

def applies (self, field, x, y):
"""True if the rule applies in the field at position (x,y)."""
for px, fx in zip(range(7), range(x - 3, x + 4)):
for py, fy in zip(range(7), range(y - 3, y + 4)):
if (fx, fy) in field:
if field[fx, fy] != self.pattern[px, py]:
return False
else:
if self.pattern[px, py].type != 'any':
return False
return True

def rotate (self, direction):
"""Rotate rule pattern to head in `direction`."""
for i in range(4):
if self.direction == direction:
return
self.rotate_ccw()
raise AssertionError("Illegal direction: %s" % direction)

def rotate_ccw(self):
"""Rotate rule pattern one time counterclockwise."""
pattern = {}
for x in range(7):
for y in range(7):
pattern[y, 6 - x] = self.pattern[x, y]
self.pattern = pattern
x, y = self.direction
self.direction = y, -x

# vim: set ts=4 sts=4 sw=4 et: