From 8373a98bc92a08ddb7cd9a2bccbeda1951669483 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20Schr=C3=B6der?=
 <fschroeder@techfak.uni-bielefeld.de>
Date: Thu, 29 Feb 2024 17:45:13 +0100
Subject: [PATCH] Update player readiness and game configuration

The 'all_players_ready' field was moved from 'state_representation.py' to 'game_server.py'. Instead of being part of the initial state of the game, it's now part of the server environment, making it easier to keep track of the readiness of all players. Additionally, the game configuration in 'study_config.yaml' was updated to accommodate one player instead of two and no bots.
---
 .../configs/study/study_config.yaml           |  4 +-
 cooperative_cuisine/environment.py            | 51 +++++++++----------
 cooperative_cuisine/game_server.py            |  9 ++--
 cooperative_cuisine/state_representation.py   |  3 +-
 4 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/cooperative_cuisine/configs/study/study_config.yaml b/cooperative_cuisine/configs/study/study_config.yaml
index eb241e93..5d33271e 100644
--- a/cooperative_cuisine/configs/study/study_config.yaml
+++ b/cooperative_cuisine/configs/study/study_config.yaml
@@ -15,5 +15,5 @@ levels:
     name: "Level 1-4: Bottleneck"
 
 
-num_players: 2
-num_bots: 12
+num_players: 1
+num_bots: 0
diff --git a/cooperative_cuisine/environment.py b/cooperative_cuisine/environment.py
index 169565e0..c0eb6804 100644
--- a/cooperative_cuisine/environment.py
+++ b/cooperative_cuisine/environment.py
@@ -318,8 +318,6 @@ class Environment:
             env_start_time_worldtime=datetime.now(),
         )
 
-        self.all_players_ready = False
-
     def overwrite_counters(self, counters):
         self.counters = counters
         self.movement.counter_positions = np.array([c.pos for c in self.counters])
@@ -464,32 +462,14 @@ class Environment:
                 effect_manager.progress(passed_time=passed_time, now=self.env_time)
         self.hook(POST_STEP, passed_time=passed_time)
 
-    def get_state(self):
+    def get_state(self, player_id: str = None, additional_key_values: dict = None):
         """Get the current state of the game environment. The state here is accessible by the current python objects.
 
-        Returns: Dict of lists of the current relevant game objects.
-
-        """
-        return {
-            "players": self.players,
-            "counters": self.counters,
-            "score": self.score,
-            "orders": self.order_manager.open_orders,
-            "ended": self.game_ended,
-            "env_time": self.env_time,
-            "remaining_time": max(self.env_time_end - self.env_time, timedelta(0)),
-        }
-
-    def get_json_state(
-        self,
-        player_id: str = None,
-    ) -> str:
-        """Return the current state of the game formatted in json dict.
-
         Args:
             player_id: The player for which to get the state.
+            additional_key_values: Additional dict that is added to the state
 
-        Returns: The state of the game formatted as a json-string
+        Returns: The state of the game as a dict.
 
         """
         if player_id in self.players:
@@ -500,7 +480,6 @@ class Environment:
                 "kitchen": {"width": self.kitchen_width, "height": self.kitchen_height},
                 "score": self.score,
                 "orders": self.order_manager.order_state(),
-                "all_players_ready": self.all_players_ready,
                 "ended": self.game_ended,
                 "env_time": self.env_time.isoformat(),
                 "remaining_time": max(
@@ -528,14 +507,30 @@ class Environment:
                     if msg["start_time"] < self.env_time
                     and msg["end_time"] > self.env_time
                 ],
+                **(additional_key_values if additional_key_values else {}),
             }
             self.hook(STATE_DICT, state=state, player_id=player_id)
-            json_data = json.dumps(state)
-            self.hook(JSON_STATE, json_data=json_data, player_id=player_id)
-            # assert StateRepresentation.model_validate_json(json_data=json_data)
-            return json_data
+            return state
         raise ValueError(f"No valid {player_id=}")
 
+    def get_json_state(
+        self, player_id: str = None, additional_key_values: dict = None
+    ) -> str:
+        """Return the current state of the game formatted in json dict.
+
+        Args:
+            player_id: The player for which to get the state.
+            additional_key_values: Additional dict that is added to the state
+
+        Returns: The state of the game formatted as a json-string
+
+        """
+        state = self.get_state(player_id, additional_key_values)
+        json_data = json.dumps(state)
+        self.hook(JSON_STATE, json_data=json_data, player_id=player_id)
+        # assert additional_key_values is None or StateRepresentation.model_validate_json(json_data=json_data)
+        return json_data
+
     def reset_env_time(self):
         """Reset the env time to the initial time, defined by `create_init_env_time`."""
         self.hook(PRE_RESET_ENV_TIME)
diff --git a/cooperative_cuisine/game_server.py b/cooperative_cuisine/game_server.py
index 4f1656a6..56ae02dc 100644
--- a/cooperative_cuisine/game_server.py
+++ b/cooperative_cuisine/game_server.py
@@ -81,6 +81,7 @@ class EnvironmentData:
     stop_reason: str = ""
     start_time: datetime | None = None
     last_step_time: int | None = None
+    all_players_ready: bool = False
 
     # add manager_id?
 
@@ -227,7 +228,7 @@ class EnvironmentHandler:
             self.envs[env_id].start_time = start_time
             self.envs[env_id].last_step_time = time.time_ns()
             self.envs[env_id].environment.reset_env_time()
-            self.envs[env_id].environment.all_players_ready = True
+            self.envs[env_id].all_players_ready = True
 
     def get_state(
         self, player_hash: str
@@ -245,10 +246,10 @@ class EnvironmentHandler:
             player_hash in self.player_data
             and self.player_data[player_hash].env_id in self.envs
         ):
-            state = self.envs[
-                self.player_data[player_hash].env_id
-            ].environment.get_json_state(
+            env_data = self.envs[self.player_data[player_hash].env_id]
+            state = env_data.environment.get_json_state(
                 self.player_data[player_hash].player_id,
+                additional_key_values={"all_players_ready": env_data.all_players_ready},
             )
             return state
         if player_hash not in self.player_data:
diff --git a/cooperative_cuisine/state_representation.py b/cooperative_cuisine/state_representation.py
index 4479c392..cfa023f8 100644
--- a/cooperative_cuisine/state_representation.py
+++ b/cooperative_cuisine/state_representation.py
@@ -96,13 +96,14 @@ class StateRepresentation(BaseModel):
     kitchen: KitchenInfo
     score: float | int
     orders: list[OrderState]
-    all_players_ready: bool
     ended: bool
     env_time: datetime  # isoformat str
     remaining_time: float
     view_restrictions: None | list[ViewRestriction]
     served_meals: list[tuple[str, str]]
     info_msg: list[tuple[str, str]]
+    # is added:
+    # all_players_ready: bool
 
 
 def create_json_schema():
-- 
GitLab