diff --git a/enums/action_probabilities.py b/enums/action_probabilities.py new file mode 100644 index 0000000..53b330d --- /dev/null +++ b/enums/action_probabilities.py @@ -0,0 +1,15 @@ +# Note: This really isn't an enum but a constant. Should this be placed in a different folder? +from enums.player_action import PlayerAction + +Action_Probabilities = { + PlayerAction.NOP : {PlayerAction.NOP: 1}, + PlayerAction.NORTH : {PlayerAction.NORTH: 1, PlayerAction.SOUTH: 0, PlayerAction.EAST: 0, PlayerAction.WEST: 0, PlayerAction.NOP: 0}, + PlayerAction.SOUTH : {PlayerAction.NORTH: 0, PlayerAction.SOUTH: 1, PlayerAction.EAST: 0, PlayerAction.WEST: 0, PlayerAction.NOP: 0}, + PlayerAction.EAST : {PlayerAction.NORTH: 0, PlayerAction.SOUTH: 0, PlayerAction.EAST: 1, PlayerAction.WEST: 0, PlayerAction.NOP: 0}, + PlayerAction.WEST : {PlayerAction.NORTH: 0, PlayerAction.SOUTH: 0, PlayerAction.EAST: 0, PlayerAction.WEST: 1, PlayerAction.NOP: 0}, + PlayerAction.INTERACT : {PlayerAction.INTERACT: 1, PlayerAction.NOP: 0}, + PlayerAction.TOGGLE : {PlayerAction.TOGGLE: 1, PlayerAction.NOP: 0}, + PlayerAction.CANCEL : {PlayerAction.CANCEL: 1, PlayerAction.NOP: 0}, + PlayerAction.PICKUP : {PlayerAction.PICKUP: 1, PlayerAction.NOP: 0}, + PlayerAction.RESET : {PlayerAction.RESET: 1}, +} \ No newline at end of file diff --git a/enums/player_action.py b/enums/player_action.py index 3a771d8..ac25c4b 100755 --- a/enums/player_action.py +++ b/enums/player_action.py @@ -12,3 +12,16 @@ class PlayerAction(IntEnum): CANCEL = 7, PICKUP = 8, RESET = 9, + +PlayerActionTable = { + "NOP" : PlayerAction.NOP, + "NORTH" : PlayerAction.NORTH, + "SOUTH" : PlayerAction.SOUTH, + "EAST" : PlayerAction.EAST, + "WEST" : PlayerAction.WEST, + "INTERACT" : PlayerAction.INTERACT, + "TOGGLE" : PlayerAction.TOGGLE, + "CANCEL" : PlayerAction.CANCEL, + "PICKUP" : PlayerAction.PICKUP, + "RESET" : PlayerAction.RESET, +} diff --git a/env.py b/env.py index 022234d..8770152 100755 --- a/env.py +++ b/env.py @@ -1,7 +1,9 @@ +import random import time +from enums.action_probabilities import Action_Probabilities import gymnasium as gym -from enums.player_action import PlayerAction +from enums.player_action import PlayerAction, PlayerActionTable from game import Game MOVEMENT_ACTIONS = [PlayerAction.NORTH, PlayerAction.SOUTH, PlayerAction.EAST, PlayerAction.WEST] @@ -11,7 +13,7 @@ class SupermarketEnv(gym.Env): def __init__(self, num_players=1, player_speed=0.15, keyboard_input=False, render_messages=True, bagging=False, headless=False, initial_state_filename=None, follow_player=-1, random_start=False, - render_number=False, max_num_items=33, player_sprites=None, record_path=None, stay_alive=False): + render_number=False, max_num_items=33, player_sprites=None, record_path=None, stay_alive=False, stochastic=False): super(SupermarketEnv, self).__init__() @@ -40,11 +42,27 @@ def __init__(self, num_players=1, player_speed=0.15, keyboard_input=False, rende self.observation_space = gym.spaces.Dict() self.headless = headless self.random_start = random_start + self.action_probability = {} + + if (stochastic): # storing probability of action success rate + filename = input("Input stochastic probability file name: ") + with open(filename, "r") as file: + content = file.read() + for row in content.split("\n"): + action_row = list(map(lambda column: column.strip(": "), row.split("\t"))) + probability_pairs = map(lambda result: tuple(result.split(" ")), action_row[1:]) + self.action_probability[PlayerActionTable[action_row[0]]] = dict(map(lambda pair: (PlayerActionTable[pair[0]], int(pair[1])), probability_pairs)) + else: + self.action_probability = Action_Probabilities + + def get_stochastic_action(self, action): + return random.choices(list(self.action_probability[action].keys()), weights=list(self.action_probability[action].values()), k=1)[0] def step(self, action): done = False for i, player_action in enumerate(action): player_action, arg = player_action + player_action = self.get_stochastic_action(player_action) if player_action in MOVEMENT_ACTIONS: self.unwrapped.game.player_move(i, player_action) elif player_action == PlayerAction.NOP: @@ -114,6 +132,7 @@ def convert_action(self, player_action): def step(self, player_action): done = False i, player_action, arg = player_action + player_action = self.get_stochastic_action(player_action) if player_action in MOVEMENT_ACTIONS: self.unwrapped.game.player_move(i, player_action) elif player_action == PlayerAction.NOP: diff --git a/socket_env.py b/socket_env.py index afd5ec0..a1866ea 100755 --- a/socket_env.py +++ b/socket_env.py @@ -259,6 +259,13 @@ def accept_wrapper(sock): '--stay_alive', action='store_true', ) + + parser.add_argument( + '--stochastic', + help="file to read stochastic success probabilities of actions", + action='store_true', + ) + args = parser.parse_args() @@ -276,7 +283,8 @@ def accept_wrapper(sock): render_number=args.render_number, player_sprites=args.player_sprites, record_path=args.record_path, - stay_alive=args.stay_alive + stay_alive=args.stay_alive, + stochastic = args.stochastic ) norms = [CartTheftNorm(), diff --git a/stochastic_probability.txt b/stochastic_probability.txt new file mode 100644 index 0000000..4441e9f --- /dev/null +++ b/stochastic_probability.txt @@ -0,0 +1,10 @@ +NOP: NOP 1 +NORTH: NORTH 1 SOUTH 0 EAST 0 WEST 0 NOP 0 +SOUTH: NORTH 0 SOUTH 1 EAST 0 WEST 0 NOP 0 +EAST: NORTH 0 SOUTH 0 EAST 1 WEST 0 NOP 0 +WEST: NORTH 0 SOUTH 0 EAST 0 WEST 1 NOP 0 +INTERACT: INTERACT 1 NOP 0 +TOGGLE: TOGGLE 1 NOP 0 +CANCEL: CANCEL 1 NOP 0 +PICKUP: PICKUP 1 NOP 0 +RESET: RESET 1 \ No newline at end of file