summaryrefslogtreecommitdiff
path: root/Game.py
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-11-02 22:36:35 +0200
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-11-02 22:36:35 +0200
commit1475dd4020ec24df8b29f5d90d89843b64f93f95 (patch)
tree7965e1d9cdaceb0a02a945b8f39b1437be3ed7e7 /Game.py
parent314be3895ece7dbeb47bcdd85a05acbc4bc0ff9c (diff)
downloadSnakePuzzle-1475dd4020ec24df8b29f5d90d89843b64f93f95.tar.gz
SnakePuzzle-1475dd4020ec24df8b29f5d90d89843b64f93f95.zip
feat: hacky level changing and parsing system, also fixed unintentional class-wide variables
Diffstat (limited to 'Game.py')
-rw-r--r--Game.py164
1 files changed, 105 insertions, 59 deletions
diff --git a/Game.py b/Game.py
index f61fbdd..59d410a 100644
--- a/Game.py
+++ b/Game.py
@@ -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: