Skip to content

Commit

Permalink
Function to transform a 2D matrix into Gridworld's serialization format
Browse files Browse the repository at this point in the history
  • Loading branch information
jessesnyder committed Oct 12, 2023
1 parent 630d01f commit 0cd84ee
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 0 deletions.
61 changes: 61 additions & 0 deletions dlgr/griduniverse/csv_gridworlds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import re
from collections import defaultdict

from dlgr.griduniverse.experiment import Gridworld

player_regex = re.compile(r"(p\d+)(c\d+)?")
color_names = Gridworld.player_color_names


def matrix2gridworld(matrix):
"""Transform a 2D matrix representing an initial grid state
into the serialized format used by Gridworld.
"""
result = defaultdict(list)

result["rows"] = len(matrix)
if matrix:
result["columns"] = len(matrix[0])
else:
result["columns"] = 0

for row_num, row in enumerate(matrix):
for col_num, cell in enumerate(row):
position = [col_num, row_num]
cell = cell.strip()
player_match = player_regex.match(cell)
if not cell:
# emtpy
continue
if cell == "w":
result["walls"].append(position)
elif player_match:
id_str, color_str = player_match.groups()
player_id = int(id_str.replace("p", ""))
player_data = {
"id": player_id,
"position": position,
}
if color_str is not None:
player_color_index = int(color_str.replace("c", "")) - 1
try:
player_data["color"] = color_names[player_color_index]
except IndexError:
max_color = len(color_names)
raise ValueError(
f"Invalid player color specified in {cell}. Max color is {max_color}"
)

result["players"].append(player_data)
else:
# assume an Item
id_and_maybe_uses = [s.strip() for s in cell.split("|")]
item_data = {
"item_id": id_and_maybe_uses[0],
"position": position,
}
if len(id_and_maybe_uses) == 2:
item_data["remaining_uses"] = int(id_and_maybe_uses[1])
result["items"].append(item_data)

return dict(result)
166 changes: 166 additions & 0 deletions test/test_gridworld.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,169 @@ def test_instructions(self, gridworld):
# Just test something basic
html = gridworld.instructions()
assert "🫐 Gooseberry (3 points)" in html


class TestMatrix2SerializedGridworld(object):
"""Tests for converting a list of lists extracted from matrix
representation of initial grid state into the format used in
Gridworld [de]serialization.
"""

@property
def subject(self):
from dlgr.griduniverse.csv_gridworlds import matrix2gridworld

return matrix2gridworld

def test_transformation_one_row(self):
csv = [["w", "stone", "", "gooseberry_bush|3", "p1c2"]]

result = self.subject(csv)

assert result == {
"columns": 5,
"rows": 1,
"items": [
{
"item_id": "stone",
"position": [1, 0],
},
{
"item_id": "gooseberry_bush",
"position": [3, 0],
"remaining_uses": 3,
},
],
"walls": [
[0, 0],
],
"players": [
{
"color": "YELLOW",
"position": [4, 0],
"id": 1,
}
],
}

def test_transformation_multirow(self):
csv = [
["w", "stone", "", "gooseberry_bush|3", "p1c1"],
["", "w", "", "", ""],
["", "p2c1", "w", "", ""],
["", "", "", "w", ""],
["", "", "", "p3c2", "w"],
["", "", "", "", "w"],
["gooseberry_bush|4", "", "", "", ""],
["", "big_hard_rock", "", "", ""],
["", "p4c2", "", "", ""],
["", "", "p5c3", "", ""],
]

result = self.subject(csv)

assert result == {
"columns": 5,
"rows": 10,
"items": [
{
"item_id": "stone",
"position": [1, 0],
},
{
"item_id": "gooseberry_bush",
"position": [3, 0],
"remaining_uses": 3,
},
{
"item_id": "gooseberry_bush",
"position": [0, 6],
"remaining_uses": 4,
},
{
"item_id": "big_hard_rock",
"position": [1, 7],
},
],
"walls": [
[0, 0],
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[4, 5],
],
"players": [
{
"color": "BLUE",
"position": [4, 0],
"id": 1,
},
{
"color": "BLUE",
"position": [1, 2],
"id": 2,
},
{
"color": "YELLOW",
"position": [3, 4],
"id": 3,
},
{
"color": "YELLOW",
"position": [1, 8],
"id": 4,
},
{
"color": "ORANGE",
"position": [2, 9],
"id": 5,
},
],
}

def test_transformation_empty_matrix(self):
csv = []

result = self.subject(csv)

assert result == {"rows": 0, "columns": 0}

def test_transformation_not_confused_by_whitepace(self):
csv = [["w ", " stone", " ", " gooseberry_bush | 3 ", " p1c2"]]

result = self.subject(csv)

assert result == {
"columns": 5,
"rows": 1,
"items": [
{
"item_id": "stone",
"position": [1, 0],
},
{
"item_id": "gooseberry_bush",
"position": [3, 0],
"remaining_uses": 3,
},
],
"walls": [
[0, 0],
],
"players": [
{
"color": "YELLOW",
"position": [4, 0],
"id": 1,
}
],
}

def test_transformation_explains_invalid_player_colors(self):
csv = [["p1c999"]]

with pytest.raises(ValueError) as exc_info:
self.subject(csv)

assert exc_info.match("Invalid player color")

0 comments on commit 0cd84ee

Please sign in to comment.