-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issues/268 initial map csv #296
Changes from all commits
9cad056
429d16e
6f0ab4a
e24a6c8
4084c3a
03985d2
d43d465
2d67882
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
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. | ||
|
||
Example: | ||
|
||
+---------------+---------+--------------------+ | ||
| w | stone | gooseberry_bush|3 | | ||
| p1c1 | w | w | | ||
| | | p3c2 | | ||
| | p4c2 | | | ||
| big_hard_rock | w | p2c1 | | ||
+---------------+---------+--------------------+ | ||
|
||
Explanation: | ||
|
||
- "w": a wall | ||
- "stone": item defined by item_id "stone" in game_config.yml | ||
- "gooseberry_bush|3": similar to the above, with the added detail | ||
that the item has 3 remaining uses | ||
- "p2c1": player ID 2, who is on team (color) 1 | ||
- Empty cells: empty space in the grid | ||
""" | ||
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): | ||
# NB: we use [y, x] format in GU!! (╯°□°)╯︵ ┻━┻ | ||
position = [row_num, col_num] | ||
cell = cell.strip() | ||
player_match = player_regex.match(cell) | ||
if not cell: | ||
# emtpy | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. empty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what the suggestion is here? |
||
continue | ||
if cell == "w": | ||
result["walls"].append(position) | ||
elif player_match: | ||
id_str, color_str = player_match.groups() | ||
player_id = 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}" at postion {position}. ' | ||
f"Max color value is {max_color}, " | ||
f"but you specified {player_color_index + 1}." | ||
) | ||
|
||
result["players"].append(player_data) | ||
else: | ||
# assume an Item | ||
id_and_maybe_uses = [s.strip() for s in cell.split("|")] | ||
item_data = { | ||
"id": len(result["items"]) + 1, | ||
"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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm.... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do think a |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
"""The Griduniverse.""" | ||
|
||
import collections | ||
import csv | ||
import datetime | ||
import itertools | ||
import json | ||
|
@@ -94,6 +95,7 @@ | |
"difi_group_label": unicode, | ||
"difi_group_image": unicode, | ||
"fun_survey": bool, | ||
"map_csv": unicode, | ||
"pre_difi_question": bool, | ||
"pre_difi_group_label": unicode, | ||
"pre_difi_group_image": unicode, | ||
|
@@ -507,6 +509,18 @@ def compute_payoffs(self): | |
player.payoff *= inter_proportions[player.color_idx] | ||
player.payoff *= self.dollars_per_point | ||
|
||
def load_map(self, csv_file_path): | ||
with open(csv_file_path) as csv_file: | ||
grid_state = self.csv_to_grid_state(csv_file) | ||
self.deserialize(grid_state) | ||
|
||
def csv_to_grid_state(self, csv_file): | ||
from .csv_gridworlds import matrix2gridworld # avoid circular import | ||
|
||
reader = csv.reader(csv_file) | ||
grid_state = matrix2gridworld(list(reader)) | ||
return grid_state | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
def build_labyrinth(self): | ||
if self.walls_density and not self.wall_locations: | ||
start = time.time() | ||
|
@@ -561,7 +575,7 @@ def deserialize(self, state): | |
self.columns, | ||
) | ||
) | ||
self.round = state["round"] | ||
self.round = state.get("round", 0) | ||
# @@@ can't set donation_active because it's a property | ||
# self.donation_active = state['donation_active'] | ||
|
||
|
@@ -857,7 +871,7 @@ class Item: | |
""" | ||
|
||
item_config: dict | ||
id: int = field(default_factory=lambda: uuid.uuid4()) | ||
id: int = field(default_factory=lambda: uuid.uuid4().int) | ||
creation_timestamp: float = field(default_factory=time.time) | ||
position: tuple = (0, 0) | ||
remaining_uses: int = field(default=None) | ||
|
@@ -1353,7 +1367,7 @@ def handle_connect(self, msg): | |
return | ||
|
||
logger.info("Client {} has connected.".format(player_id)) | ||
client_count = len(self.grid.players) | ||
client_count = len(self.node_by_player_id) | ||
logger.info("Grid num players: {}".format(self.grid.num_players)) | ||
if client_count < self.grid.num_players: | ||
participant = self.session.query(dallinger.models.Participant).get( | ||
|
@@ -1370,13 +1384,14 @@ def handle_connect(self, msg): | |
# We use the current node id modulo the number of colours | ||
# to pick the user's colour. This ensures that players are | ||
# allocated to colours uniformly. | ||
self.grid.spawn_player( | ||
id=player_id, | ||
color_name=self.grid.limited_player_color_names[ | ||
node.id % self.grid.num_colors | ||
], | ||
recruiter_id=participant.recruiter_id, | ||
) | ||
if player_id not in self.grid.players: | ||
self.grid.spawn_player( | ||
id=player_id, | ||
color_name=self.grid.limited_player_color_names[ | ||
node.id % self.grid.num_colors | ||
], | ||
recruiter_id=participant.recruiter_id, | ||
) | ||
else: | ||
logger.info("No free network found for player {}".format(player_id)) | ||
|
||
|
@@ -1721,7 +1736,10 @@ def send_state_thread(self): | |
def game_loop(self): | ||
"""Update the world state.""" | ||
gevent.sleep(0.1) | ||
if not self.config.get("replay", False): | ||
map_csv_path = self.config.get("map_csv", None) | ||
if map_csv_path is not None: | ||
self.grid.load_map(map_csv_path) | ||
elif not self.config.get("replay", False): | ||
self.grid.build_labyrinth() | ||
logger.info("Spawning items") | ||
for item_type in self.item_config.values(): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result["columns"] = len(matrix[0]) if matrix else 0