1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
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
|