Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/snake/annotate/8e75e931bfd2/snake.py
Дата изменения: Unknown
Дата индексирования: Fri Feb 28 20:41:10 2014
Кодировка:

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

snake

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