def test_returns_only_options_from_one_item_dictionary(self): score_lookup = {("a", "b"): 100} safest = pick_safest(score_lookup) expected_result = (("a", "b"), 100) self.assertEqual(expected_result, safest)
def pick_move_in_equilibrium_from_multiple_score_lookups(score_lookups): # This is the WRONG way to find a Nash Equilibrium from different potential games # ... but it is a simple way that works (with crappy results) # # The games should be modelled properly based on incomplete information (see Harsanyi Transform), # however that would require the bot to keep track of what it has revealed to the opponent try: weighted_choices = get_weighted_choices_from_multiple_score_lookups( score_lookups) except CouldNotFindEquilibriumError as e: logger.warning("Problem finding equilibria: {}".format(e)) return random.choice([ pick_safest(sl, remove_guaranteed=True)[0][0] for sl in score_lookups ]) s = sum([wc[1] for wc in weighted_choices]) bot_choices = [wc[0] for wc in weighted_choices] bot_percentages = [wc[1] / s for wc in weighted_choices] choice = random.choices(bot_choices, weights=bot_percentages)[0] logger.debug("Choices: {}".format([w for w in weighted_choices if w[1]])) logger.debug("Choice: {}".format(choice)) return choice
def test_returns_better_option_for_two_different_moves(self): score_lookup = {("a", "b"): 100, ("c", "b"): 200} safest = pick_safest(score_lookup) expected_result = (("c", "b"), 200) self.assertEqual(expected_result, safest)
def pick_safest_move_using_dynamic_search_depth(battles): """ Dynamically decides how far to look into the game. This requires a strong computer to be able to search 3/4 turns ahead. Using a pypy interpreter will also result in better performance. """ all_scores = dict() num_battles = len(battles) if num_battles > 1: search_depth = 2 for i, b in enumerate(battles): state = b.create_state() mutator = StateMutator(state) user_options, opponent_options = b.get_all_options() logger.debug("Searching through the state: {}".format(mutator.state)) scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=search_depth, prune=True) prefixed_scores = prefix_opponent_move(scores, str(i)) all_scores = {**all_scores, **prefixed_scores} elif num_battles == 1: search_depth = 3 b = battles[0] state = b.create_state() mutator = StateMutator(state) user_options, opponent_options = b.get_all_options() num_user_options = len(user_options) num_opponent_options = len(opponent_options) options_product = num_user_options * num_opponent_options if options_product < 20 and num_user_options > 1 and num_opponent_options > 1: logger.debug("Low options product, looking an additional depth") search_depth += 1 logger.debug("Searching through the state: {}".format(mutator.state)) logger.debug("Options Product: {}".format(options_product)) logger.debug("My Options: {}".format(user_options)) logger.debug("Opponent Options: {}".format(opponent_options)) logger.debug("Search depth: {}".format(search_depth)) all_scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=search_depth, prune=True) else: raise ValueError("less than 1 battle?: {}".format(battles)) decision, payoff = pick_safest(all_scores, remove_guaranteed=True) bot_choice = decision[0] logger.debug("Safest: {}, {}".format(bot_choice, payoff)) logger.debug("Depth: {}".format(search_depth)) return bot_choice
def test_returns_option_with_the_lowest_minimum_in_2_by_2(self): score_lookup = { ("a", "x"): 100, ("a", "y"): -100, ("c", "x"): 200, ("c", "y"): -200, } safest = pick_safest(score_lookup) expected_result = (("a", "y"), -100) self.assertEqual(expected_result, safest)
def pick_safest_move_from_battles(battles): all_scores = dict() for i, b in enumerate(battles): state = b.create_state() mutator = StateMutator(state) user_options, opponent_options = b.get_all_options() logger.debug("Searching through the state: {}".format(mutator.state)) scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=config.search_depth, prune=True) prefixed_scores = prefix_opponent_move(scores, str(i)) all_scores = {**all_scores, **prefixed_scores} decision, payoff = pick_safest(all_scores, remove_guaranteed=True) bot_choice = decision[0] logger.debug("Safest: {}, {}".format(bot_choice, payoff)) return bot_choice
def pick_safest_move_from_battles(battles): all_scores = dict() for i, b in enumerate(battles): state = b.create_state() mutator = StateMutator(state) user_options, opponent_options = b.get_all_options() logger.debug("Attempting to find best move from: {}".format( mutator.state)) scores = get_payoff_matrix(mutator, user_options, opponent_options, prune=True) prefixed_scores = prefix_opponent_move(scores, str(i)) all_scores = {**all_scores, **prefixed_scores} decision, payoff = pick_safest(all_scores) bot_choice = decision[0] logger.debug("Safest: {}, {}".format(bot_choice, payoff)) return bot_choice