Skip to content

Commit

Permalink
switch from rotation being an angle to rotation being true or false f…
Browse files Browse the repository at this point in the history
…or the tile status, uses vflip and hflip for 180 in status instead
  • Loading branch information
mwinkens committed Jun 4, 2024
1 parent e62c370 commit 5680134
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 58 deletions.
11 changes: 4 additions & 7 deletions src/backend/tile_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,18 @@ def getPossibleNeighborhoods(self) -> List["TileConnection"]:
return ret

"""
rotates 45 degree
rotate 90 degrees
"""
def rotate45(self) -> "TileConnection":
def rot(self) -> "TileConnection":
neighbors = [0] * EIGHT_NEIGHBORS

# index of rotating neighbors
to_swap = [3, 0, 1, 5, 2, 6, 7, 4] # TODO use enum
to_swap = [2, 4, 7, 1, 6, 0, 3, 5] # TODO use enum

for i in range(EIGHT_NEIGHBORS):
neighbors[i] = self._neighbors[to_swap[i]]
neighbors[to_swap[i]] = self._neighbors[i]
return TileConnection(neighbors)

def rotate90(self) -> "TileConnection":
return self.rotate45().rotate45() # yes, this could be optimized

def vFlip(self) -> "TileConnection":
neighbors = [0] * EIGHT_NEIGHBORS
to_swap = [2, 1, 0, 4, 3, 7, 6, 5] # TODO use enum
Expand Down
26 changes: 15 additions & 11 deletions src/backend/tile_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def getAllPossibleModifications(self) -> List[TileMapState]:
# the modifications describe, how the tile connections can be manipulated
con_list = [(self.con.__copy__(), self.status.__copy__())]

# add original rotations
if self.mods.can_rot:
con_list.extend(self._getPossibleModificationsRotation(self.con, self.status))

# add h flip variants
if self.mods.can_h_flip:
con_list.append((self.con.hFlip(), self.status.hFlip()))
Expand All @@ -40,9 +44,10 @@ def getAllPossibleModifications(self) -> List[TileMapState]:
# add v flip and h flip
if self.mods.can_v_flip and self.mods.can_h_flip:
con_list.append((self.con.vFlip().hFlip(), self.status.vFlip().hFlip()))

# add original rotations
con_list.extend(self._getPossibleModificationsRotation(self.con, self.status))
if self.mods.can_rot:
con_list.extend(
self._getPossibleModificationsRotation(self.con.vFlip().hFlip(), self.status.vFlip().hFlip())
)

# remove duplicates TODO all of this can be optimized
unique_ids = set()
Expand All @@ -56,15 +61,14 @@ def getAllPossibleModifications(self) -> List[TileMapState]:
return ret

def _getPossibleModificationsRotation(self, con: TileConnection, status: TileStatus):
con_list = []
if self.mods.can_rot:
con_rot1, status_rot1 = con.rotate90(), status.rot90()
con_rot2, status_rot2 = con_rot1.rotate90(), status_rot1.rot90()
con_rot3, status_rot3 = con_rot2.rotate90(), status_rot2.rot90()
con_list.append((con_rot1, status_rot1))
con_list.append((con_rot2, status_rot2))
con_list.append((con_rot3, status_rot3))
return con_list
con_rot1, status_rot1 = con.rot(), status.rotate()
con_rot2, status_rot2 = con_rot1.rot(), status_rot1.rotate()
con_rot3, status_rot3 = con_rot2.rot(), status_rot2.rotate()
return [(con_rot1, status_rot1),
(con_rot2, status_rot2),
(con_rot3, status_rot3)]
return []

def getAllPossibleTileStates(self) -> List[TileMapState]:
all_possible_modifications = self.getAllPossibleModifications()
Expand Down
23 changes: 13 additions & 10 deletions src/backend/tile_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class TileStatus:
def __init__(self):
self.v_flip = False
self.h_flip = False
self.rot = 0
self.rot = False
self.empty = False

def __copy__(self) -> "TileStatus":
Expand All @@ -27,16 +27,19 @@ def hFlip(self):
status.h_flip = not self.h_flip
return status

def rot45(self):
def rotate(self):
"""
rotate 90 degrees
NOTE: rotated can only be on or off, rotated by 180 degree means NOT rotated, hflipped and vflipped,
while rotated by 270 degree means hflipped, vflipped and rotated
"""
status = self.__copy__()
status.rot += 45
status.rot %= 360
return status

def rot90(self):
status = self.__copy__()
status.rot += 90
status.rot %= 360
if self.rot:
status.rot = False
status.v_flip = not self.v_flip
status.h_flip = not self.h_flip
else:
status.rot = True
return status

def __eq__(self, other):
Expand Down
2 changes: 1 addition & 1 deletion src/widgets/widget_base_tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def paintEvent(self, e: Any, _: Any = None) -> None:
transform = transform.scale(-1, 1)

if self.tile_data.status.rot:
transform.rotate(self.tile_data.status.rot)
transform.rotate(90) # fixed 90 degrees always, but can also flip, too!
transform.translate(-pm.width() // 2, -pm.height() // 2)

# draw tile
Expand Down
18 changes: 4 additions & 14 deletions tests/logic/test_tile_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,12 @@ def test_get_empty(self, expected, neighbors):
assert t2.encodeSmall() == expected

@pytest.mark.parametrize("neighbors", correct_neighbors())
def test_rotate45(self, neighbors):
t = TileConnection(neighbors)
t2 = t.__copy__()
for i in range(8): # rotate 360
t2 = t2.rotate45()
assert t2 == t
assert t2.rotate45().rotate45() == t.rotate90()

@pytest.mark.parametrize("neighbors", correct_neighbors())
def test_rotate90(self, neighbors):
def test_rotate(self, neighbors):
t = TileConnection(neighbors)
t2 = t.__copy__()
for i in range(4): # rotate 360
t2 = t2.rotate90()
t2 = t2.rot()
assert t2 == t
assert t2.rotate45().rotate45() == t.rotate90()

@pytest.mark.parametrize("rotated, neighbors", [
[0b00100000, [1, 0, 0, 0, 0, 0, 0, 0]],
Expand All @@ -158,7 +148,7 @@ def test_rotate90(self, neighbors):
])
def test_rotation_is_clockwise(self, rotated, neighbors):
t = TileConnection(neighbors)
rot = t.rotate90()
rot = t.rot()
assert rot.encodeSmall() == rotated

@pytest.mark.parametrize("neighbors", correct_neighbors())
Expand All @@ -179,7 +169,7 @@ def test_h_flip(self, neighbors):
def test_flip_rot_sanity(self, neighbors):
t = TileConnection(neighbors)
t2 = t.__copy__()
assert t.rotate90().rotate90() == t2.hFlip().vFlip()
assert t.rot().rot() == t2.hFlip().vFlip()

@pytest.mark.parametrize("expected, neighbors", [
[[0], [0] * 8],
Expand Down
24 changes: 9 additions & 15 deletions tests/logic/test_tile_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ def test_init(self):

@staticmethod
def create_tile_status(v_flip, h_flip, rot, empty) -> TileStatus:
assert rot % 90 == 0
t = TileStatus()
t.v_flip = v_flip
t.h_flip = h_flip
Expand All @@ -21,10 +20,10 @@ def create_tile_status(v_flip, h_flip, rot, empty) -> TileStatus:
def status_list(create_tile_status):
return [
TileStatus(),
create_tile_status(True, False, 90, False),
create_tile_status(False, False, 180, True),
create_tile_status(True, True, 270, True),
create_tile_status(False, True, 90, False),
create_tile_status(True, False, True, False),
create_tile_status(False, False, False, True),
create_tile_status(True, True, False, True),
create_tile_status(False, True, False, False),
]

@pytest.mark.parametrize("status", status_list(create_tile_status))
Expand All @@ -40,16 +39,11 @@ def test_copy_and_equal(self, status):
@pytest.mark.parametrize("status", status_list(create_tile_status))
def test_rot90(self, status):
rot = status.rot
rot_status = status.rot90()
assert rot_status.rot % 90 == 0
assert rot_status.rot < 360
# make sure it's clockwise
assert rot_status.rot == 0 or rot_status.rot > rot
assert status == status.rot90().rot90().rot90().rot90()

@pytest.mark.parametrize("status", status_list(create_tile_status))
def test_rot45(self, status):
assert status.rot45().rot45() == status.rot90()
rot_status = status.rotate()
assert rot_status.rot != rot
assert status == status.rotate().rotate().rotate().rotate()
# sanity check
assert status.rotate().rotate() == status.vFlip().hFlip()

@pytest.mark.parametrize("status", status_list(create_tile_status))
def test_v_flip(self, status):
Expand Down

0 comments on commit 5680134

Please sign in to comment.