-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.py
105 lines (79 loc) · 3.17 KB
/
common.py
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
"""Common data structures. Can be used by any module."""
from __future__ import annotations
import math
from dataclasses import dataclass
@dataclass
class Coordinates:
"""Coordinates data class."""
x: int
y: int
class MapException(Exception):
"""Exception Moving Pieces."""
class Map:
"""Representation of a map."""
empty_tile = "o"
wall_tile = "x"
player_car = "A"
def __init__(self, txt: str):
"""Initialize Map from string."""
pieces, grid, movements = txt.split(" ")
self.pieces = int(pieces)
self.movements = int(movements)
self.grid_size = int(math.sqrt(len(grid)))
self.grid = []
line = []
for i, pos in enumerate(grid):
line.append(pos)
if (i + 1) % self.grid_size == 0:
self.grid.append(line)
line = []
def __repr__(self):
"""Revert map object to string."""
raw = ""
for line in self.grid:
for column in line:
raw += column
return f"{self.pieces} {raw} {self.movements}"
@property
def coordinates(self):
"""Representation of ocupied map positions through tuples x,y,value."""
_coordinates = []
for y, line in enumerate(self.grid):
for x, column in enumerate(line):
if column != self.empty_tile:
_coordinates.append((x, y, column))
return _coordinates
def get(self, cursor: Coordinates):
"""Return piece at cursor position."""
if 0 <= cursor.x < self.grid_size and 0 <= cursor.y < self.grid_size:
return self.grid[int(cursor.y)][int(cursor.x)]
raise MapException("Out of the grid")
def piece_coordinates(self, piece: str):
"""List coordinates holding a piece."""
return [Coordinates(x, y) for (x, y, p) in self.coordinates if p == piece]
def move(self, piece: str, direction: Coordinates):
"""Move piece in direction fiven by a vector."""
if piece == self.wall_tile:
raise MapException("Blocked piece")
piece_coord = self.piece_coordinates(piece)
# Don't move vertical pieces sideways
if direction.x != 0 and any([line.count(piece) == 1 for line in self.grid]):
raise MapException("Can't move sideways")
# Don't move horizontal pieces up-down
if direction.y != 0 and any([line.count(piece) > 1 for line in self.grid]):
raise MapException("Can't move up-down")
def sum(a: Coordinates, b: Coordinates):
return Coordinates(a.x + b.x, a.y + b.y)
for pos in piece_coord:
if not self.get(sum(pos, direction)) in [piece, self.empty_tile]:
raise MapException("Blocked piece")
for pos in piece_coord:
self.grid[pos.y][pos.x] = self.empty_tile
for pos in piece_coord:
new_pos = sum(pos, direction)
self.grid[new_pos.y][new_pos.x] = piece
def test_win(self):
"""Test if player_car has crossed the left most column."""
return any(
[c.x == self.grid_size - 1 for c in self.piece_coordinates(self.player_car)]
)