summaryrefslogtreecommitdiff
path: root/Game.py
blob: f61fbdd24153b33f545ae29c5f5fc35cd4a2ac07 (plain)
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