Skip to content
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

New games #114

Merged
merged 9 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ Additional details can be found in the <a href="https://docs.diambra.ai/envs/gam
| :------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------: |
| Dead<br>Or<br>Alive ++ | Street<br>Fighter III<br>3rd Strike | Tekken Tag<br>Tournament | Ultimate<br>Mortal<br>Kombat 3 | Samurai<br>Showdown<br>5 Special | The King of<br>Fighers '98<br>Ultimate<br>Match Hero |

| <img src="https://raw.githubusercontent.com/diambra/arena/main/img/mvsc.jpg" alt="mvsc" width="125"/> | <img src="https://raw.githubusercontent.com/diambra/arena/main/img/xmvsf.jpg" alt="xmvsf" width="125"/> | <img src="https://raw.githubusercontent.com/diambra/arena/main/img/soulclbr.jpg" alt="soulclbr" width="125"/> |
| :------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------: |
| Marvel<br>VS<br>Capcom | X-Men<br>VS<br>Street Fighter | Soul<br>Calibur |

**Many more are coming soon...**

## Competition Platform
Expand Down
3 changes: 3 additions & 0 deletions diambra/arena/arena_gym.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ def show_obs(self, observation, wait_key=1, viz=True, string="observation", key=
if key.startswith("character"):
char_idx = observation if type(observation) == int else np.where(observation == 1)[0][0]
print(string + ": {} / {}".format(observation, self.env_info.characters_info.char_list[char_idx]))
elif key == "partner":
partner_idx = observation if type(observation) == int else np.where(observation == 1)[0][0]
print(string + ": {} / {}".format(observation, self.env_info.characters_info.partner_list[partner_idx]))
else:
print(string + ": {}".format(observation))
else:
Expand Down
42 changes: 32 additions & 10 deletions diambra/arena/env_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class EnvironmentSettingsBase:
pb_model: model = None

episode_settings = ["seed", "difficulty", "continue_game", "show_final", "tower", "role",
"characters", "outfits", "super_art", "fighting_style", "ultimate_style"]
"characters", "outfits", "super_art", "fighting_style", "ultimate_style", "speed_mode"]

# Transforming env settings dict to pb request
def get_pb_request(self, init=False):
Expand Down Expand Up @@ -217,8 +217,9 @@ class EnvironmentSettings(EnvironmentSettingsBase):
characters: Union[None, str, Tuple[str], Tuple[str, str], Tuple[str, str, str]] = None
outfits: int = 1
super_art: Union[None, int] = None # SFIII Specific
fighting_style: Union[None, int] = None # KOF Specific
fighting_style: Union[None, int] = None # KOF, MVSC Specific
ultimate_style: Union[None, Tuple[int, int, int]] = None # KOF Specific
speed_mode: Union[None, int] = None # MVSC, XMVSF Specific

def _sanity_check(self):
super()._sanity_check()
Expand All @@ -241,10 +242,15 @@ def _sanity_check(self):
check_val_in_list("characters[{}]".format(idx), self.characters[idx], char_list)
check_num_in_range("outfits", self.outfits, self.games_dict[self.game_id]["outfits"])
check_val_in_list("super_art", self.super_art, [None, 1, 2, 3])
check_val_in_list("fighting_style", self.fighting_style, [None, 1, 2, 3])
if self.game_id == "kof98umh":
check_val_in_list("fighting_style", self.fighting_style, [None, 1, 2, 3])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw I recently learned about https://docs.pydantic.dev which would could help improving these validations. Just something to check out whenever

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw I recently learned about https://docs.pydantic.dev which would could help improving these validations. Just something to check out whenever

Thanks a lot for the suggestion, will add this as a task!

else:
check_val_in_list("fighting_style", self.fighting_style, [None, 1, 2])

if self.ultimate_style is not None:
for idx in range(3):
check_val_in_list("ultimate_style[{}]".format(idx), self.ultimate_style[idx], [1, 2])
check_val_in_list("speed_mode", self.speed_mode, [None, 1, 2])

def _get_action_spaces(self):
return [self.action_space]
Expand All @@ -266,9 +272,14 @@ def _process_random_values(self):
if self.super_art is None:
self.super_art = random.choice(list(range(1, 4)))
if self.fighting_style is None:
self.fighting_style = random.choice(list(range(1, 4)))
maxFightingStyle = 3
if self.game_id == "kof98umh":
maxFightingStyle = 4
self.fighting_style = random.choice(list(range(1, maxFightingStyle)))
if self.ultimate_style is None:
self.ultimate_style = tuple([random.choice(list(range(1, 3))) for _ in range(3)])
if self.speed_mode is None:
self.speed_mode = random.choice(list(range(1, 3)))

def _get_player_specific_values(self):
player_settings = model.EnvSettings.EpisodeSettings.PlayerSettings(
Expand All @@ -277,7 +288,8 @@ def _get_player_specific_values(self):
outfits=self.outfits,
super_art=self.super_art,
fighting_style=self.fighting_style,
ultimate_style={"dash": self.ultimate_style[0], "evade": self.ultimate_style[1], "bar": self.ultimate_style[2]}
ultimate_style={"dash": self.ultimate_style[0], "evade": self.ultimate_style[1], "bar": self.ultimate_style[2]},
speed_mode=self.speed_mode,
)

return [player_settings]
Expand All @@ -296,8 +308,9 @@ class EnvironmentSettingsMultiAgent(EnvironmentSettingsBase):
Tuple[Tuple[str, str, str], Tuple[str, str, str]]] = (None, None)
outfits: Tuple[int, int] = (1, 1)
super_art: Union[Tuple[None, None], Tuple[int, int]] = (None, None) # SFIII Specific
fighting_style: Union[Tuple[None, None], Tuple[int, int]] = (None, None) # KOF Specific
fighting_style: Union[Tuple[None, None], Tuple[int, int]] = (None, None) # KOF, MVSC Specific
ultimate_style: Union[Tuple[None, None], Tuple[Tuple[int, int, int], Tuple[int, int, int]]] = (None, None) # KOF Specific
speed_mode: Union[Tuple[None, None], Tuple[int, int]] = (None, None) # MVSC, XMVSF Specific

def _sanity_check(self):
super()._sanity_check()
Expand Down Expand Up @@ -325,10 +338,14 @@ def _sanity_check(self):
check_val_in_list("characters[{}][{}]".format(idx, jdx), self.characters[idx][jdx], char_list)
check_num_in_range("outfits[{}]".format(idx), self.outfits[idx], self.games_dict[self.game_id]["outfits"])
check_val_in_list("super_art[{}]".format(idx), self.super_art[idx], [None, 1, 2, 3])
check_val_in_list("fighting_style[{}]".format(idx), self.fighting_style[idx], [None, 1, 2, 3])
if self.game_id == "kof98umh":
check_val_in_list("fighting_style[{}]".format(idx), self.fighting_style[idx], [None, 1, 2, 3])
else:
check_val_in_list("fighting_style[{}]".format(idx), self.fighting_style[idx], [None, 1, 2])
if self.ultimate_style[idx] is not None:
for jdx in range(3):
check_val_in_list("ultimate_style[{}][{}]".format(idx, jdx), self.ultimate_style[idx][jdx], [1, 2])
check_val_in_list("speed_mode[{}]".format(idx), self.speed_mode[idx], [None, 1, 2])

def _process_random_values(self):
super()._process_random_values()
Expand Down Expand Up @@ -356,8 +373,12 @@ def _process_random_values(self):
self.role = (self.role[0], Roles.P1 if self.role[0] == Roles.P2 else Roles.P2)

self.super_art = tuple([random.choice(list(range(1, 4))) if self.super_art[idx] is None else self.super_art[idx] for idx in range(2)])
self.fighting_style = tuple([random.choice(list(range(1, 4))) if self.fighting_style[idx] is None else self.fighting_style[idx] for idx in range(2)])
maxFightingStyle = 3
if self.game_id == "kof98umh":
maxFightingStyle = 4
self.fighting_style = tuple([random.choice(list(range(1, maxFightingStyle))) if self.fighting_style[idx] is None else self.fighting_style[idx] for idx in range(2)])
self.ultimate_style = tuple([[random.choice(list(range(1, 3))) for _ in range(3)] if self.ultimate_style[idx] is None else self.ultimate_style[idx] for idx in range(2)])
self.speed_mode = tuple([random.choice(list(range(1, 3))) if self.speed_mode[idx] is None else self.speed_mode[idx] for idx in range(2)])

def _get_action_spaces(self):
return [action_space for action_space in self.action_space]
Expand All @@ -372,7 +393,8 @@ def _get_player_specific_values(self):
outfits=self.outfits[idx],
super_art=self.super_art[idx],
fighting_style=self.fighting_style[idx],
ultimate_style={"dash": self.ultimate_style[idx][0], "evade": self.ultimate_style[idx][1], "bar": self.ultimate_style[idx][2]}
ultimate_style={"dash": self.ultimate_style[idx][0], "evade": self.ultimate_style[idx][1], "bar": self.ultimate_style[idx][2]},
speed_mode=self.speed_mode[idx],
)

players_env_settings.append(player_settings)
Expand Down Expand Up @@ -407,7 +429,7 @@ def sanity_check(self):
check_num_in_range("normalization_factor", self.normalization_factor, [0.0, 1000000])
check_type("clip_reward", self.clip_reward, bool, admit_none=False)
check_type("no_attack_buttons_combinations", self.no_attack_buttons_combinations, bool, admit_none=False)
check_val_in_list("frame_shape[2]", self.frame_shape[2], [0, 1, 3])
check_val_in_list("frame_shape[2]", self.frame_shape[2], [0, 1])
check_num_in_range("frame_shape[0]", self.frame_shape[0], [0, MAX_FRAME_RES])
check_num_in_range("frame_shape[1]", self.frame_shape[1], [0, MAX_FRAME_RES])
if (min(self.frame_shape[0], self.frame_shape[1]) == 0 and
Expand Down
12 changes: 0 additions & 12 deletions diambra/arena/utils/gym_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,6 @@ def gym_obs_dict_space_to_standard_dict(observation_space_dict):

return standard_dict

# Utility to create a Gym compliant Dict Space from the InternalObsDict
def standard_dict_to_gym_obs_dict(obsstandard_dict):

for k, v in obsstandard_dict.items():
if isinstance(v, dict):
obsstandard_dict[k] = standard_dict_to_gym_obs_dict(v)
else:
obsstandard_dict[k] = v

return spaces.Dict(obsstandard_dict)


# Discrete to multidiscrete action conversion
def discrete_to_multi_discrete_action(action, n_move_actions):

Expand Down
177 changes: 177 additions & 0 deletions diambra/arena/utils/integratedGames.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,5 +351,182 @@
}
},
"cfg": {"WP": "But1", "WK": "But2", "SP": "But3", "SK": "But4"}
},
"mvsc":
{
"name": "Marvel VS Capcom",
"id": "mvsc",
"original_rom_name": "mvsc.zip",
"search_keywords": ["marvel vs capcom clash of super heroes", "marvel-vs.-capcom-clash-of-super-heroes-euro-980123", "5511", "wowroms"],
"notes": "Requires the QSound_HLE sound driver to be placed in the roms folder. Search keywords: \"qsound_hle.zip\", \"dl-1425.bin\"",
"nvram_save": "",
"sha256": "6f63627cc37c554f74e8bf07b21730fa7f85511c7d5d07449850be98dde91da8",
"char_list": ["Chun-Li", "Ryu", "Zangief", "Morrigan", "Captain Commando",
"Megaman", "Strider Hiryu", "Spider Man", "Jin", "Captain America",
"Venom", "Hulk", "Gambit", "War Machine", "Wolverine", "Roll",
"Onslaught", "Alt-Venom", "Alt-Hulk", "Alt-War Machine",
"Shadow Lady", "Alt-Morrigan"],
"char_forbidden_list": ["Roll", "Onslaught", "Alt-Venom", "Alt-Hulk", "Alt-War Machine",
"Shadow Lady", "Alt-Morrigan"],
"char_homonymy_map": {},
"partner_list": ["Lou", "Juggernaut", "Magneto", "Psylocke", "Cyclops",
"Colossus", "Unknown Soldier", "Ton Pooh", "Arthur",
"Saki", "Miechele Heart", "Thor", "Storm", "Rogue",
"Iceman", "Pure&Fur", "US Agent", "Anita", "Devilot",
"Jubilee", "Shadow", "Sentinel"],
"outfits": [1, 2],
"difficulty": [1, 8, 2],
"difficulty_to_cluster_map": {
"1": "Easy",
"2": "Easy",
"3": "Easy",
"4": "Easy",
"5": "Medium",
"6": "Medium",
"7": "Hard",
"8": "Hard"
},
"cluster_to_difficulty_map": {
"Easy": 4,
"Medium": 6,
"Hard": 8
},
"rounds_per_stage": 1,
"stages_per_game": 8,
"number_of_chars_per_round": 2,
"number_of_chars_to_select": 2,
"n_actions": [9, 19, 7],
"health": [0, 144],
"frame_shape": [224, 384, 3],
"ram_states": {
"common": {
"stage": ["BOX", 1, 8],
"timer": ["BOX", 0, 99]
},
"Px": {
"side": ["BINARY", 0, 1],
"wins": ["BOX", 0, 1],
"character": ["DISCRETE", 0, 21],
"character_1": ["DISCRETE", 0, 21],
"character_2": ["DISCRETE", 0, 21],
"health_1": ["BOX", 0, 144],
"health_2": ["BOX", 0, 144],
"active_character": ["BINARY", 0, 1],
"super_bar": ["BOX", 0, 144],
"super_count": ["BOX", 0, 3],
"partner": ["DISCRETE", 0, 21],
"partner_attacks": ["BOX", 0, 9]
}
},
"cfg": {"WP": "But1", "MP": "But2", "SP": "But3", "WK": "But4", "MK": "But5", "SK": "But6"}
},
"xmvsf":
{
"name": "X-Men VS Street Fighter",
"id": "xmvsf",
"original_rom_name": "xmvsf.zip",
"search_keywords": ["x-men vs street fighter", "x-men-vs.-street-fighter-usa-961004", "8769", "wowroms"],
"notes": "Requires the QSound_HLE sound driver to be placed in the roms folder. Search keywords: \"qsound_hle.zip\", \"dl-1425.bin\"",
"nvram_save": "",
"sha256": "833aa46af63a3ad87f69ce2bacd85a4445f35a50e3aff4f793f069b205b51c60",
"char_list": ["Akuma", "Magneto", "Juggernaut", "Dhalsim", "Mr. Bison",
"Sabretooth", "Storm", "Chun-Li", "Zangief", "Gambit",
"Rogue", "Cammy", "Charlie", "Wolverine", "Cyclops", "Ryu",
"Ken", "Apocalypse", "Alpha Chun-Li"],
"char_forbidden_list": ["Apocalypse", "Alpha Chun-Li"],
"char_homonymy_map": {},
"outfits": [1, 2],
"difficulty": [1, 8, 2],
"difficulty_to_cluster_map": {
"1": "Easy",
"2": "Easy",
"3": "Easy",
"4": "Easy",
"5": "Medium",
"6": "Medium",
"7": "Hard",
"8": "Hard"
},
"cluster_to_difficulty_map": {
"Easy": 4,
"Medium": 6,
"Hard": 8
},
"rounds_per_stage": 1,
"stages_per_game": 8,
"number_of_chars_per_round": 2,
"number_of_chars_to_select": 2,
"n_actions": [9, 18, 7],
"health": [0, 144],
"frame_shape": [224, 384, 3],
"ram_states": {
"common": {
"stage": ["BOX", 1, 8],
"timer": ["BOX", 0, 99]
},
"Px": {
"side": ["BINARY", 0, 1],
"wins": ["BOX", 0, 1],
"character": ["DISCRETE", 0, 18],
"character_1": ["DISCRETE", 0, 18],
"character_2": ["DISCRETE", 0, 18],
"health_1": ["BOX", 0, 144],
"health_2": ["BOX", 0, 144],
"active_character": ["BINARY", 0, 1],
"super_bar": ["BOX", 0, 144],
"super_count": ["BOX", 0, 3]
}
},
"cfg": {"WP": "But1", "MP": "But2", "SP": "But3", "WK": "But4", "MK": "But5", "SK": "But6"}
},
"soulclbr":
{
"name": "Soul Calibur",
"id": "soulclbr",
"original_rom_name": "soulclbr.zip",
"search_keywords": ["soul calibur", "soul-calibur", "106959", "wowroms"],
"notes": "",
"nvram_save": "at28c16",
"sha256": "a07a1a19995d582b56f2865783c5d7adb7acb9a6ad995a26fc7c4cfecd821817",
"char_list": ["Xianghua", "Yoshimitsu", "Lizard Man", "Siegfried",
"Rock", "Seung Mina", "Edge Master", "Voldo",
"Ivy", "Sophitia", "Arthur", "Kilik", "Hwang",
"Maxi", "Nightmare", "Taki", "Astaroth", "Inferno"],
"char_forbidden_list": ["Inferno"],
"char_homonymy_map": {},
"outfits": [1, 2],
"difficulty": [1, 5, 3],
"difficulty_to_cluster_map": {
"1": "Easy",
"2": "Easy",
"3": "Easy",
"4": "Medium",
"5": "Hard"
},
"cluster_to_difficulty_map": {
"Easy": 3,
"Medium": 4,
"Hard": 5
},
"rounds_per_stage": 2,
"stages_per_game": 8,
"number_of_chars_per_round": 1,
"number_of_chars_to_select": 1,
"n_actions": [9, 13, 5],
"health": [0, 240],
"frame_shape": [240, 512, 3],
"ram_states": {
"common": {
"stage": ["BOX", 1, 8],
"timer": ["BOX", 0, 40]
},
"Px": {
"side": ["BINARY", 0, 1],
"wins": ["BOX", 0, 2],
"character": ["DISCRETE", 0, 17],
"health": ["BOX", 0, 240]
}
},
"cfg": {"HA": "But1", "VA": "But2", "K": "But3", "G": "But4"}
}
}
Loading
Loading