diff options
Diffstat (limited to 'Game.py')
| -rw-r--r-- | Game.py | 164 |
1 files changed, 105 insertions, 59 deletions
@@ -1,96 +1,133 @@ from Snake import Snake from Vec import Vec2 +import Vec from Box import Box from Door import Door from PressurePlate import PressurePlate from Trail import Trail +from Walls import Walls -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.""" +class Game: + """Class responsible for the main logic of a game. + For a game, this will probably be a singleton.""" + - _walls = [] + def __init__(self, levels): + self.snake = None + self.boxes = [] + self.walls = None + self.statics = [] + self.levelIn = None + self.level = -1 + self.levels = [] + self.levels = levels + self.nextLevel() - def __init__(self, walls): - self._walls = walls - def fromString(wallString): - walls = [] + def nextLevel(self): + self.level += 1 + + self.walls = Walls.fromString(self.levels[self.level]) + self.snake = None + self.statics = [] + self.boxes = [] + y = 0 - for line in wallString.split('\n'): + for line in self.levels[self.level].split('\n'): x = 0 for char in line: - if char == "#": - walls.append(Vec2(x, y)) + if char == "b": + self.boxes.append(Box(Vec2(x, y))) + elif char == "D": + if self.doorAt(Vec2(x, y)) == None: + self.statics.append(Door(Vec2(x, y))) + elif char == "_": + self.parseSwitchTrail(self.levels[self.level], Vec2(x, y)) + elif char == "I": + self.levelIn = 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 + self.snake = Snake([self.levelIn, self.levelIn, self.levelIn, self.levelIn], self) + self.statics.append(Door(self.levelIn)) + self.snake.heading = Vec.up - def height(self): - return max(self._walls, key=lambda p: p.y).y + 1 + def parseSwitchTrail(self, level: str, platePos: Vec2): + level = level.split('\n') + startSwitch = None + if level[platePos.y][platePos.x] == "_": + startSwitch = PressurePlate(platePos) + self.statics.append(startSwitch) + else: + raise ValueError + + visited = [] + def inner(pos: Vec2): + visited.append(pos) + if level[pos.y][pos.x] == "+": + directions = filter(lambda p: not p in visited, + map(lambda p: pos + p, + [Vec.up, Vec.down, Vec.left, Vec.right] + ) + ) + nextPart = filter(lambda x: x != None, map(lambda x: inner(x), directions)) + #assert len(nextPart) == 1 + trail = Trail(pos, next(nextPart)) + self.statics.append(trail) + return trail + elif level[pos.y][pos.x] == "_" and pos == platePos: + directions = filter(lambda p: not p in visited, + map(lambda p: pos + p, + [Vec.up, Vec.down, Vec.left, Vec.right] + ) + ) + nextPart = filter(lambda x: x != None, map(lambda x: inner(x), directions)) + for trail in nextPart: + startSwitch.addTrail(trail) + elif level[pos.y][pos.x] == "D": + door = self.doorAt(pos) + if door != None: + return door + + door = Door(pos) + self.statics.append(door) + return door + inner(platePos) + for static in self.statics: + match static: + case PressurePlate(): + trailString = map( lambda x: x.pos.toString(), static._trails) -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 _movableSolidAt(self, pos: Vec2) -> bool: + return (pos in self.snake.cells) or (pos in map(lambda box: box.pos, self.boxes)) + def tick(self): + lastSnakeCell = self.snake.cells[len(self.snake.cells) - 1] + if (lastSnakeCell.x < 0 or lastSnakeCell.x >= self.width()) or (lastSnakeCell.y < 0 or lastSnakeCell.y >= self.height()): + self.nextLevel() + return + 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))): + if static.isActive() and not self._movableSolidAt(static.pos): static.deactivate() - elif (not static.isActive()) and ((static.pos in self.snake.cells) or (static.pos in map(lambda box: box.pos, self.boxes))): + elif (not static.isActive()) and self._movableSolidAt(static.pos): static.activate() + for static in self.statics: + match static: 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)): + if not self._movableSolidAt(static.pos): static.close() @@ -98,6 +135,15 @@ D h # return self.snake.hasCollided + def doorAt(self, pos: Vec2): + for static in self.statics: + match static: + case Door(): + if static.pos == pos: + return static + return None + + def closedDoorAt(self, pos: Vec2) -> bool: res = False for static in self.statics: |
