Илия обнови решението на 11.05.2013 23:22 (преди над 11 години)
+from collections import namedtuple, deque
+
+
+class Vec2D(namedtuple('Vec2D', 'x y')):
+
+ def __add__(self, other):
+ return Vec2D(self.x + other.x, self.y + other.y)
+
+ def __sub__(self, other):
+ return Vec2D(self.x - other.x, self.y - other.y)
+
+ def __mul__(self, other):
+ return Vec2D(self.x * other, self.y * other)
+
+ def are_inside_world_with_size(self, size):
+ return self.x in range(size) and self.y in range(size)
+
+
+class WorldObject:
+ pass
+
+
+class Food(WorldObject):
+
+ def __init__(self, energy=0):
+ self.energy = energy
+
+
+class Cell():
+
+ def __init__(self, contents=None):
+ if not isinstance(contents, (WorldObject, type(None))):
+ raise TypeError
+ self.contents = contents
+
+ def is_empty(self):
+ return self.contents is None
+
+ def empty(self):
+ self.contents = None
+
+ def contains(self, type_):
+ return isinstance(self.contents, type_)
+
+
+class World():
+
+ def __init__(self, width):
+ self.width = width
+ self.matrix = [[Cell() for y in range(width)] for x in range(width)]
+
+ def __len__(self):
+ return self.width
+
+ def __getitem__(self, key):
+ if isinstance(key, Vec2D):
+ return self.matrix[key.y][key.x]
+ return self.matrix[key]
+
+
+class Python:
+ LEFT = Vec2D(-1, 0)
+ RIGHT = Vec2D(1, 0)
+ UP = Vec2D(0, -1)
+ DOWN = Vec2D(0, 1)
+
+ def __init__(self, world, coords, size, direction):
+ self.world, self.size, self.direction = world, size, direction
+ self.energy = 0
+
+ self.body_coords = deque(
+ [coords - direction * i for i in range(size + 1)])
+ for coords in self.body_coords:
+ self.world[coords].contents = PythonPart(self)
+
+ self.head = PythonHead(self)
+ self.world[self.body_coords[0]].contents = self.head
+
+ def eat(self, food):
+ self.energy += food.energy
+ self.size += 1
+
+ def move(self, direction):
+ if direction == self.direction * (-1):
+ raise ValueError("Cannot go in opposite direction")
+
+ new_coords = self.body_coords[0] + direction
+
+ if not new_coords.are_inside_world_with_size(len(self.world)):
+ raise Death("You went to another world")
+
+ if self.world[new_coords].contains(Food):
+ self.eat(self.world[new_coords].contents)
+ elif self.world[new_coords].is_empty():
+ self.world[self.body_coords.pop()].empty()
+ else:
+ raise Death("You bumped into something")
+
+ self.body_coords.appendleft(new_coords)
+ self.world[self.body_coords[0]].contents = self.head
+ self.world[self.body_coords[1]].contents = PythonPart(self)
+
+
+class PythonPart(WorldObject):
+
+ def __init__(self, owner):
+ self.owner = owner
+
+
+class PythonHead(PythonPart):
+ pass
+
+
+class Death(Exception):
+ pass