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

Shuffle actions to fix away team advantage #260

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 5 additions & 1 deletion botbowl/core/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,11 @@ def set_available_actions(self) -> None:
Calls the current procedure's available_actions() method and sets the game's available actions to the returned
list.
"""
self.state.available_actions = self.state.stack.peek().available_actions()
forbidden_actions_types = {ActionType.BLOCK}
actions = self.state.stack.peek().available_actions()
if actions is not None:
actions = [action for action in actions if action.action_type not in forbidden_actions_types ]
self.state.available_actions = actions

def report(self, outcome) -> None:
"""
Expand Down
28 changes: 23 additions & 5 deletions botbowl/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,11 @@ def to_json(self):
'bomb': self.bomb.to_json() if self.bomb else None
}

def permute_list(l: Optional[list], permutation: np.ndarray):
if l is None or len(l) == 0:
return []
assert len(l) == len(permutation), f"Length of list {l} does not match length of permutation {permutation}"
return [l[i] for i in permutation]

@immutable_after_init
class ActionChoice:
Expand All @@ -629,15 +634,28 @@ class ActionChoice:

def __init__(self, action_type, team, positions=None, players=None, rolls=None, block_dice=None, skill=None,
paths=None, disabled=False):

self.action_type = action_type
self.positions = [] if positions is None else positions
self.players = [] if players is None else players
self.team = team
self.rolls = [] if rolls is None else rolls
self.block_dice = [] if block_dice is None else block_dice
self.disabled = disabled
self.skill = skill
self.paths = [] if paths is None else paths
if positions is not None:
permutation_indices = np.random.permutation(len(positions))
try:
self.positions = permute_list(positions, permutation_indices)
self.rolls = permute_list(rolls, permutation_indices)
self.block_dice = permute_list(block_dice, permutation_indices)
self.paths = permute_list(paths, permutation_indices)
except AssertionError as e:
new_message = str(e) + f" with action type {action_type}"
raise type(e)(new_message)
else:
self.positions = [] if positions is None else positions
self.rolls = [] if rolls is None else rolls
self.block_dice = [] if block_dice is None else block_dice
self.paths = [] if paths is None else paths
self.players = [] if players is None else players


def __repr__(self):
return f"ActionChoice({self.action_type}, len(positions)={len(self.positions)}, " \
Expand Down
56 changes: 56 additions & 0 deletions examples/scripted_bot_brawl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import botbowl
import time
import scripted_bot_example


def main():
# Load configurations, rules, arena and teams
config = botbowl.load_config("bot-bowl")
config.competition_mode = False
config.pathfinding_enabled = True
# config = get_config("gym-7.json")
# config = get_config("gym-5.json")
# config = get_config("gym-3.json")
ruleset = botbowl.load_rule_set(
config.ruleset, all_rules=False
) # We don't need all the rules
arena = botbowl.load_arena(config.arena)
home = botbowl.load_team_by_filename("human", ruleset)
away = botbowl.load_team_by_filename("human", ruleset)

num_games = 1000
home_tds = 0
away_tds = 0
home_wins = 0
away_wins = 0
draws = 0
# Play 10 games
for i in range(num_games):
home_agent = botbowl.make_bot("scripted")
home_agent.name = "Scripted Bot (home)"
away_agent = botbowl.make_bot("scripted")
away_agent.name = "Scripted (away)"
config.debug_mode = False
game = botbowl.Game(
i, home, away, home_agent, away_agent, config, arena=arena, ruleset=ruleset
)
game.config.fast_mode = True

print("Starting game", (i + 1))
start = time.time()
game.init()
end = time.time()
print(end - start)

home_wins += 1 if game.get_winning_team() is game.state.home_team else 0
away_wins += 1 if game.get_winning_team() is game.state.away_team else 0
home_tds += game.state.home_team.state.score
away_tds += game.state.away_team.state.score

print(
f"(home, away): Wins: ({home_wins}, {away_wins}), TDs: ({home_tds}, {away_tds})"
)


if __name__ == "__main__":
main()
12 changes: 1 addition & 11 deletions examples/scripted_bot_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,16 +682,6 @@ def end_game(self, game):
"""
Called when a game ends.
"""
winner = game.get_winning_team()
print("Casualties: ", game.num_casualties())
if winner is None:
print("It's a draw")
elif winner == self.my_team:
print("I ({}) won".format(self.name))
print(self.my_team.state.score, "-", self.opp_team.state.score)
else:
print("I ({}) lost".format(self.name))
print(self.my_team.state.score, "-", self.opp_team.state.score)


def path_to_move_actions(game: botbowl.Game, player: botbowl.Player, path: Path, do_assertions=True) -> List[Action]:
Expand Down Expand Up @@ -791,4 +781,4 @@ def main():


if __name__ == "__main__":
main()
main()