from Snake import Snake from Vec import Vec2 from Box import Box from Door import Door from PressurePlate import PressurePlate from Trail import Trail class Walls: """Contains the walls of a game. Supports iterating over the walls and checking if there is a wall at a specific coordinate. Useful as a wrapper to later increase performance of these operations.""" _walls = [] def __init__(self, walls): self._walls = walls def fromString(wallString): walls = [] y = 0 for line in wallString.split('\n'): x = 0 for char in line: if char == "#": walls.append(Vec2(x, y)) x += 1 y += 1 return Walls(walls) def walls(self): return self._walls def wallAt(self, pos): return (pos in self._walls) def width(self): return max(self._walls, key=lambda p: p.x).x + 1 def height(self): return max(self._walls, key=lambda p: p.y).y + 1 class Game: """Class responsible for the main logic of a game. For a game, this will probably be a singleton.""" snake = None boxes = [] walls = None statics = [] def __init__(self): self.snake = Snake([Vec2(6, 6), Vec2(6, 7), Vec2(6,8), Vec2(7,8), Vec2(8, 8), Vec2(9, 8)], self) _box1 = Box(Vec2(11, 4)) _box2 = Box(Vec2(3, 10)) self.boxes = [_box1, _box2] self.statics = [Door(Vec2(0, 6)), Door(Vec2(6, 11)), PressurePlate(Vec2(6, 9))] self.statics.append(Trail(Vec2(6,10), self.statics[1])) self.statics[2].addTrail(self.statics[3]) self.walls = Walls.fromString("""############### # # # f # # # # b # # # D h # # t # # tttt # # _ # # b # ######D###### # # f # ###############""") def width(self): return self.walls.width() def height(self): return self.walls.height() def tick(self): self.snake.move() for static in self.statics: match static: case PressurePlate(): if static.isActive() and (not (static.pos in self.snake.cells)) and (not (static.pos in map(lambda box: box.pos, self.boxes))): static.deactivate() elif (not static.isActive()) and ((static.pos in self.snake.cells) or (static.pos in map(lambda box: box.pos, self.boxes))): static.activate() case Door(): if static.isOpen() and not static.isActive(): if not (static.pos in self.snake.cells or static.pos in map(lambda box: box.pos, self.boxes)): static.close() def isLost(self): return self.snake.hasCollided def closedDoorAt(self, pos: Vec2) -> bool: res = False for static in self.statics: match static: case Door(): res = res or (static.pos == pos and not static.isOpen()) return res def switchAt(self, pos: Vec2): for static in self.statics: match static: case PressurePlate(): if static.pos == pos: return static return None def enter(self, pos: Vec2, inDir: Vec2) -> bool: boxAt = next(filter(lambda box: box.pos == pos, self.boxes), None) if self.walls.wallAt(pos) or self.closedDoorAt(pos): return False elif pos in self.snake.cells: return False elif boxAt != None: if self.enter(pos + inDir, inDir): boxAt.pos = pos + inDir return True else: return False else: return True