def choice_17(g, p): if g.info_tokens < 8: for c in p.deck: if c.value_info != 5: discard(g, p, c) return True return False
def random_choice(g, p): # choice 0 : discard # choice 1 : play a card # choice 2 : give info possible_choices = [0, 1, 2] # can not discard if there are already 8 info tokens if g.info_tokens == 8: possible_choices.remove(0) # can not give info if there are not any info token left elif g.info_tokens == 0: possible_choices.remove(2) action_choice = choice(possible_choices) if action_choice == 0: # choose randomly the card to discard discarded_card = randrange(len(p.deck)) discard(g, p, p.deck[discarded_card]) elif action_choice == 1: # choose randomly the card to play played_card = randrange(len(p.deck)) play_card(g, p, p.deck[played_card]) else: # choose randomly the player to give information p_index = g.players.index(p) other_players_index = list(range(len(g.players))) other_players_index.remove(p_index) player_info = g.players[choice(other_players_index)] # choose randomly the card to give information on card_info = randrange(len(player_info.deck)) # choose randomly the type of information : 0 for color, 1 for value info_type = choice(['color', 'value']) if info_type == 'color': info = choice(['blue', 'red', 'green', 'yellow', 'white']) else: info = randrange(1, 6) give_info(g, player_info, card_info, info_type, info)
def choice_1(g, p): for c in p.deck: if (c.color_info != "") and (c.value_info != 10): if c.value_info <= g.fireworks[c.color_info]: discard(g, p, c) return True else: play_card(g, p, c) return True elif c.color_info != "": if (g.fireworks[c.color_info] == 5) or (color_lost(g, c.color)): discard(g, p, c) return True else: play_card(g, p, c) return True elif c.value_info != 10: if (c.value_info < 5) and (c.value_info <= min( g.fireworks.values())): discard(g, p, c) return True elif c.value_info < 5: play_card(g, p, c) return True return False
def simple_rules(g, p): # play a card if the information on it is known and can be played # discard it if the card is useless for c in p.deck: if (c.color_info != "") and (c.value_info != 10): if c.value == g.fireworks[c.color_info] + 1: play_card(g, p, c) return for c in p.deck: if (c.color_info != "") and (c.value_info != 10): if c.value_info <= g.fireworks[c.color_info]: discard(g, p, c) return elif c.value_info == g.fireworks[c.color_info] + 1: play_card(g, p, c) return elif c.color_info != "": if (g.fireworks[c.color_info] == 5) or (color_lost(g, c.color)): discard(g, p, c) return else: play_card(g, p, c) return elif c.value_info != 10: if (c.value_info < 5) and (c.value_info <= min( g.fireworks.values())): discard(g, p, c) return elif (c.value_info < 5) and (c.value_info <= max(g.fireworks.values()) + 1): play_card(g, p, c) return # give the information if a player among the 2 nexts has 2 playable cards if g.info_tokens >= 1: for next_turn in [1, 2]: next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): recurrent_value = several_playable_cards(g, next_player_deck) if recurrent_value != 0: good_info = True for c in next_player_deck: if (c.value == recurrent_value) and ( c.color_info == "") and (c.value_info == 10): if (not (unseen_information( g, next_player, c, 'value')) ) or (not (unseen_information( g, next_player, c, 'color'))) or ( c.value < g.fireworks[c.color] + 1): good_info = False if good_info: give_info(g, next_player, 'value', recurrent_value) return # complete the information about a "5" of the 2 next players if it is playable if g.info_tokens >= 1: for next_turn in range(1, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck for c in next_player_deck: if (c.value_info == 5) and (c.color_info == "") and (g.fireworks[c.color] == 4): same_color_cards = 0 for cards in next_player_deck: if cards.color == c.color: same_color_cards += 1 if same_color_cards <= 1: give_info(g, next_player, 'color', c.color) return # give an information if the 2 next players have nice cards with not any info on it # and if there is at least an info token left if g.info_tokens >= 1: for next_turn in [1, 2]: next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (c.value == g.fireworks[c.color] + 1) and ( c.color_info == "") and (c.value_info == 10): info = info_to_give(next_player_deck, c) if info == "color": if unseen_information(g, next_player, c, 'color'): give_info(g, next_player, 'color', c.color) return elif info == "value": if unseen_information(g, next_player, c, 'value'): give_info(g, next_player, 'value', c.value) return # give an information to a player if the previous player has an information so the second one # will be able to play a card just after (second and third next players) if g.info_tokens >= 1: for next_turn in [2, 3]: player_before_next = g.players[(g.players.index(p) + next_turn - 1) % len(g.players)] next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (c.value == g.fireworks[c.color] + 2) and (c.color_info == "") and ( c.value_info == 10) and info_given_to_player( player_before_next, c.color, g.fireworks[c.color] + 1) and not (info_on_the_left( player_before_next.deck, c)): info = info_to_give(next_player_deck, c) if info == "color": if unseen_information(g, next_player, c, 'color'): give_info(g, next_player, 'color', c.color) return elif info == "value": if unseen_information(g, next_player, c, 'value'): give_info(g, next_player, 'value', c.value) return # give an information about a "5" or a useless card in the 2 next players' deck if g.info_tokens >= 1: for next_turn in [1, 2]: next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (c.value == 5) and (c.color_info == "") and (c.value_info == 10): give_info(g, next_player, 'value', 5) return elif (min(g.fireworks.values()) >= c.value) and (c.value_info == 10): give_info(g, next_player, 'value', c.value) return elif (g.fireworks[c.color] == 5) and (c.color_info == ""): give_info(g, next_player, 'color', c.color) return # give an information if the next players have nice cards with not any info on it # and if there is at least an info token left (from the third next player) if g.info_tokens >= 1: for next_turn in range(3, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (c.value == g.fireworks[c.color] + 1) and ( c.color_info == "") and (c.value_info == 10): info = info_to_give(next_player_deck, c) if info == "color": if unseen_information(g, next_player, c, 'color'): give_info(g, next_player, 'color', c.color) return elif info == "value": if unseen_information(g, next_player, c, 'value'): give_info(g, next_player, 'value', c.value) return # give an information about a "5" or a useless card in the next players' deck (from the third next player) if g.info_tokens >= 1: for next_turn in range(3, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (c.value == 5) and (c.color_info == "") and (c.value_info == 10): give_info(g, next_player, 'value', 5) return elif (min(g.fireworks.values()) >= c.value) and (c.value_info == 10): give_info(g, next_player, 'value', c.value) return elif (g.fireworks[c.color] == 5) and (c.color_info == ""): give_info(g, next_player, 'color', c.color) return # complete the information about a "5" of the next players if g.info_tokens >= 1: for next_turn in [1, 2]: next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck for c in next_player_deck: if (c.value_info == 5) and (c.color_info == "") and ( g.fireworks[c.color] == 4) and not (same_value_or_color_cards( next_player_deck, c)): give_info(g, next_player, 'color', c.color) return # complete the information about an unplayable informed card if g.info_tokens >= 1: for next_turn in [1, 2]: next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck for c in next_player_deck: if (c.value_info == 10) and (c.color_info != ""): if c.value != g.fireworks[c.color] + 1: info = info_to_give(next_player_deck, c) if info == "value": give_info(g, next_player, 'value', c.color) return if (c.value_info != 10) and (c.color_info == ""): if c.value != g.fireworks[c.color] + 1: info = info_to_give(next_player_deck, c) if info == "color": give_info(g, next_player, 'color', c.color) return # throw a card (not a "5") if it is not useful in a near future if g.info_tokens < 8: for c in p.deck: if (c.value_info != 10) and (c.value != 5): if c.value_info > max(g.fireworks.values()) + 1: discard(g, p, c) return # throw a random card (not a useful "5") if no information about the deck if g.info_tokens < 6: for c in p.deck: if c.value_info != 5: discard(g, p, c) return # complete the information about a "5" with no cards with the same color in the deck to not discard randomly if g.info_tokens >= 1: for next_turn in range(1, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck for c in next_player_deck: if (c.value_info == 5) and (c.color_info == ""): if not (same_value_or_color_cards(next_player_deck, c)): give_info(g, next_player, 'color', c.color) return # complete the color information about cards that are the same and with the value only as information if g.info_tokens >= 1: for next_turn in range(1, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck for c in next_player_deck: if (duplicated_card(g, next_player_deck, c) ) and (c.value <= g.fireworks[c.color]) and ( c.value_info != 10) and (c.color_info == "") and not ( same_value_or_color_cards(next_player_deck, c)): give_info(g, next_player, 'color', c.color) return # give an information about a playable card which appears twice in the deck of one of the next players if g.info_tokens >= 1: for next_turn in range(1, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (duplicated_card( g, next_player_deck, c)) and (c.value == g.fireworks[c.color] + 1) and ( c.value_info == 10) and (c.color_info == ""): give_info(g, next_player, 'value', c.value) return # give an information about a playable card but with cards with same color and same value in the deck # can not be given to the player just after if g.info_tokens >= 1: for next_turn in range(2, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck if not (too_much_information(next_player_deck)): for c in next_player_deck: if (c.value_info == 10) and (c.color_info == "") and ( c.value == g.fireworks[c.color] + 1): give_info(g, next_player, 'value', c.value) return # give a random information if there are a lot of info tokens instead of playing a random card # priority for the "4" when the game is near of its start if g.info_tokens >= 6: for next_turn in range(3, len(g.players)): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck for c in next_player_deck: if (c.value_info != 10) and (c.color_info == "") and ( c.value == 4) and (max(g.fireworks.values()) < 3): give_info(g, next_player, 'value', 4) return for c in next_player_deck: info = info_to_give(next_player_deck, c) if (c.value_info != 10) and (c.color_info == "") and (info == 'color'): give_info(g, next_player, 'color', c.color) return if (c.value_info == 10) and (c.color_info != "") and (info == 'value'): give_info(g, next_player, 'value', c.value) return # try to put a random card if the game is almost done and there are still error tokens if (len(g.draw_pile) < 4) and g.error_tokens >= 2: for c in p.deck: if (c.color_info == "") and (c.value_info == 10): play_card(g, p, c) return # throw a random card (not a known useful "5") if no information about the deck if g.info_tokens < 8: for c in p.deck: if c.value_info != 5: discard(g, p, c) return # play a random card (rarely happens) for c in p.deck: if (c.color_info == "") and (c.value_info == 10): play_card(g, p, c) return for c in p.deck: if (c.color_info == "") and (c.value_info != 5): play_card(g, p, c) return for c in p.deck: if (c.color_info == "") or (c.value_info != 10): play_card(g, p, c) return
def neural_network_predictions(g, p, players_number, game_state, model): colors_list = ['blue', 'red', 'green', 'yellow', 'white'] values_list = [1, 2, 3, 4, 5] ## encode the game state game_state.loc[0, 'info_tokens'] = g.info_tokens game_state.loc[0, 'error_tokens'] = g.error_tokens for color in ['blue', 'red', 'green', 'yellow', 'white']: game_state.loc[0, color + '_firework'] = g.fireworks[color] # deck information for c in p.deck: if c.color_info != "": game_state.loc[0, 'info : card ' + str(p.deck.index(c)) + ' is ' + str(c.color_info)] = 1 if c.value_info != 10: game_state.loc[0, 'info : card ' + str(p.deck.index(c)) + ' is ' + str(c.value_info)] = 1 # next players' deck for next_turn in range(1, players_number): next_player = g.players[(g.players.index(p) + next_turn) % len(g.players)] next_player_deck = next_player.deck card_index = 0 for c in next_player_deck: game_state.loc[0, 'player ' + str(next_turn) + ' turn(s) after : card ' + str(card_index) + ' is ' + str(c.color)] = 1 game_state.loc[0, 'player ' + str(next_turn) + ' turn(s) after : card ' + str(card_index) + ' is ' + str(c.value)] = 1 card_index += 1 # next players' deck information for next_player in range(1, players_number): next_player_deck = g.players[((g.players.index(p)) + next_player) % players_number].deck for c in next_player_deck: if c.color_info != "": game_state.loc[0, 'player ' + str(next_player) + ' turn(s) after : info : card ' + str(next_player_deck.index(c)) + ' is ' + str(c.color_info)] = 1 if c.value_info != 10: game_state.loc[0, 'player ' + str(next_player) + ' turn(s) after : info : card ' + str(next_player_deck.index(c)) + ' is ' + str(c.value_info)] = 1 ## make a score prediction for each possible action and choose the best one if len(p.deck) == 4: possible_actions = list(game_state.columns[[392, 394, 396, 398]]) else: possible_actions = list(game_state.columns[[392, 394, 396]]) if g.info_tokens != 8: if len(p.deck) == 4: possible_actions += list(game_state.columns[[393, 395, 397, 399]]) else: possible_actions += list(game_state.columns[[393, 395, 397]]) if g.info_tokens > 0: for next_player in range(1, players_number): next_player_deck = g.players[((g.players.index(p)) + next_player) % players_number].deck for color in colors_list: for c in next_player_deck: if c.color == color: possible_actions.append('say to player ' + str(next_player) + ' the ' + color) break for value in values_list: for c in next_player_deck: if c.value == value: possible_actions.append('say to player ' + str(next_player) + ' the ' + str(value)) break action_to_do = "" highest_action_score = -100 for action in possible_actions: game_state.loc[0, 392:440] = 0 game_state.loc[0, action] = 1 action_score = model.predict(game_state).item() if action_score > highest_action_score: action_to_do = action highest_action_score = action_score ## execute the chosen action if 'play card' in action_to_do: play_card(g, p, p.deck[int(action_to_do[10])]) return if 'discard card' in action_to_do: discard(g, p, p.deck[int(action_to_do[13])]) return if 'say' in action_to_do: if ('blue' in action_to_do) or ('red' in action_to_do) or ( 'green' in action_to_do) or ('yellow' in action_to_do) or ( 'white' in action_to_do): give_info( g, g.players[(g.players.index(p) + int(action_to_do[14])) % players_number], 'color', action_to_do[20:len(action_to_do)]) return else: give_info( g, g.players[(g.players.index(p) + int(action_to_do[14])) % players_number], 'value', int(action_to_do[20])) return