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

snake

view snake.py @ 44:a7e53eb3f54d

snake.py: added some (ugly) docstrings, closes #7
author Daniil Alexeyevsky <me.dendik@gmail.com>
date Sun, 19 Dec 2010 23:24:15 +0300
parents 2a7b76d66e78
children acaa43cb15ad
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 magic, name = preprocess(file.readline()).split(' ', 1)
35 assert magic == "snake", "This is not snake file"
36 while True:
37 line = preprocess(file.readline())
38 if line == 'end':
39 break
40 assert line == '', "Rules must be separated by empty lines"
41 self.rules.append(Rule().load(file))
43 def fill (self):
44 """Mark every cell in `self.cells` as belonging to self."""
45 for cell in self.cells:
46 cell.snake = self
47 snake.cells[0].type = 'head'
48 snake.cells[1:-1].type = 'body'
49 snake.cells[-1].type = 'tail'
50 return
52 class Rule(object):
53 """Rule defining possible behaviour of snake."""
55 codes = {
56 'h': 'head',
57 'b': 'body',
58 't': 'tail',
59 '#': 'wall',
60 ' ': 'any',
61 '-': 'empty',
62 }
64 def __init__ (self, snake):
65 self.snake = snake
66 self.direction = (1, 0)
67 self.pattern = {}
69 def load (self, file):
70 """Load rule definition from file. Ignore any leading empty lines."""
71 y = 0
72 for line in file:
73 line = preprocess(line)
74 if y == 0 and line == '':
75 continue
76 if y == 7:
77 break
78 assert len(line) == 8, "Rule lines must be exactly 7 chars long"
79 assert line[-1] == ';', "Rule lines must end with semicolon"
80 for x, char in enumerate(line[:8]):
81 self.parse_cell(x, y, char)
82 y += 1
84 def parse_cell(self, x, y, char):
85 """Parse definition of cell in rule file.
87 Cell is defined by one character.
88 """
89 assert char.lower() in self.codes, "Illegal symbol in rule: %s" % char
90 cell = engine.Cell(x, y, None)
91 if char in 'htb':
92 if char.islower():
93 cell.snake = 'my'
94 else:
95 cell.snake = 'enemy'
96 if char == 'h':
97 assert (x, y) == (3, 3), "Own head must in the center of rule"
98 if (x, y) == (3, 3):
99 assert char == 'h', "In the center of rule must be own head"
100 cell.type = self.codes[char.lower()]
101 self.pattern[x, y] = cell
103 def applies (self, field, x, y):
104 """True if the rule applies in the field at position (x,y)."""
105 for px, fx in zip(range(7), range(x - 3, x + 4)):
106 for py, fy in zip(range(7), range(y - 3, y + 4)):
107 if fx, fy in field:
108 if field[fx, fy] != self.pattern[px, py]:
109 return False
110 else:
111 if self.pattern[px, py].type != 'any':
112 return False
113 return True
115 def rotate (self, rot):
116 """Rotate rule pattern `rot` times counterclockwise."""
117 for i in range(((rot % 4) + 4) % 4):
118 self.rotate_ccw()
120 def rotate_ccw(self):
121 """Rotate rule pattern one time counterclockwise."""
122 pattern = {}
123 for x in range(7):
124 for y in range(7):
125 pattern[y, 6 - x] = self.pattern[x, y]
126 self.pattern = pattern
127 x, y = self.direction
128 self.direction = y, -x
130 # vim: set ts=4 sts=4 sw=4 et: