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

snake

view snake.py @ 70:e8eabd9530a1

snake.Rule.load returns self for convenience
author Danya Alexeyevsky <me.dendik@gmail.com>
date Mon, 20 Dec 2010 00:43:36 +0300
parents 2d4b7e24d914
children ae4bbffb80fe 2ca1c6a7561a
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.
75 Ignore any leading empty lines.
76 Return self.
77 """
78 y = 0
79 for line in file:
80 line = preprocess(line)
81 if y == 0 and line == '':
82 continue
83 assert len(line) == 8, "Rule lines must be exactly 7 chars long"
84 assert line[-1] == ';', "Rule lines must end with semicolon"
85 for x, char in enumerate(line[:7]):
86 self.parse_cell(x, y, char)
87 y += 1
88 if y == 7:
89 break
90 return self
92 def parse_cell(self, x, y, char):
93 """Parse definition of cell in rule file.
95 Cell is defined by one character.
96 """
97 assert char.lower() in self.codes, "Illegal symbol in rule: %s" % char
98 cell = engine.Cell(x, y, self.snake)
99 if char in 'htb':
100 if char.islower():
101 cell.snake_type = 'my'
102 else:
103 cell.snake_type = 'enemy'
104 if char == 'h':
105 assert (x, y) == (3, 3), "Own head must in the center of rule"
106 if (x, y) == (3, 3):
107 assert char == 'h', "In the center of rule must be own head"
108 cell.type = self.codes[char.lower()]
109 self.pattern[x, y] = cell
111 def applies (self, field, x, y):
112 """True if the rule applies in the field at position (x,y)."""
113 for px, fx in zip(range(7), range(x - 3, x + 4)):
114 for py, fy in zip(range(7), range(y - 3, y + 4)):
115 if (fx, fy) in field:
116 if field[fx, fy] != self.pattern[px, py]:
117 return False
118 else:
119 if self.pattern[px, py].type != 'any':
120 return False
121 return True
123 def rotate (self, rot):
124 """Rotate rule pattern `rot` times counterclockwise."""
125 for i in range(((rot % 4) + 4) % 4):
126 self.rotate_ccw()
128 def rotate_ccw(self):
129 """Rotate rule pattern one time counterclockwise."""
130 pattern = {}
131 for x in range(7):
132 for y in range(7):
133 pattern[y, 6 - x] = self.pattern[x, y]
134 self.pattern = pattern
135 x, y = self.direction
136 self.direction = y, -x
138 # vim: set ts=4 sts=4 sw=4 et: