-
Notifications
You must be signed in to change notification settings - Fork 0
/
monte_carlo.py
74 lines (63 loc) · 3.55 KB
/
monte_carlo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from generate_hands import HandGenerator
import util
import random
def monte_carlo_utilities(game_state, player, max_simulations=2000, simulations_per_hand=1):
legal_cards = util.get_legal_cards(player.cards, game_state.trick.suit_led)
utilities = {card: 0.0 for card in legal_cards}
simulations_per_card = max_simulations / len(legal_cards)
hands_needed = simulations_per_card / simulations_per_hand
hand_generator = HandGenerator(max_hands=hands_needed)
hand_assignments = hand_generator.generate_hands(game_state, player)
for card in legal_cards:
for i in xrange(len(hand_assignments)):
for _ in xrange(simulations_per_hand):
hands = {player_name : list(hand_assignments[i][player_name]) for player_name in hand_assignments[i]}
utilities[card] += monte_carlo_simulate(game_state, player, card, hands)
# Normalize to probabilities and return
for card in legal_cards:
utilities[card] = float(utilities[card]) / simulations_per_card
return utilities
def monte_carlo_simulate(game_state, player, chosen_card, hands):
utility = 0
player_names = [p.name for p in game_state.players]
played = dict({card: game_state.trick.played[card].name for card in game_state.trick.played})
played[chosen_card] = player.name
if not hands[player.name]:
print 'Got empty hand for chosen card %s' % chosen_card
# print 'Player hand: %s; trying to remove %s' % (hands[player.name], chosen_card)
hands[player.name].remove(chosen_card)
suit_led = game_state.trick.suit_led or chosen_card.suit
for player_name in game_state.trick.left_to_play:
if player_name != player.name:
# card_to_play = random.choice(util.get_legal_cards(hands[player_name], suit_led))
card_to_play = util.strongest_legal_play(util.get_legal_cards(hands[player_name], suit_led), suit_led, game_state.trump)
played[card_to_play] = player_name
hands[player_name].remove(card_to_play)
winning_card = util.strongest_card([card for card in played], suit_led, game_state.trump)
winning_player = played[winning_card]
if game_state.are_partners(player.name, winning_player):
utility += 1
else:
utility -= 1
first_to_play = util.index_of_player_with_name(game_state, winning_player)
while hands[game_state.players[first_to_play].name]:
first_player_name = game_state.players[first_to_play].name
# lead_card = random.choice(hands[first_player_name])
lead_card = util.strongest_legal_play(util.get_legal_cards(hands[first_player_name], None), None, game_state.trump)
played = {lead_card: first_player_name}
hands[first_player_name].remove(lead_card)
suit_led = lead_card.suit
for player_name in player_names:
if player_name != first_player_name:
# card_to_play = random.choice(util.get_legal_cards(hands[player_name], suit_led))
card_to_play = util.strongest_legal_play(util.get_legal_cards(hands[player_name], suit_led), suit_led, game_state.trump)
played[card_to_play] = player_name
hands[player_name].remove(card_to_play)
winning_card = util.strongest_card([card for card in played], suit_led, game_state.trump)
winning_player = played[winning_card]
if game_state.are_partners(player.name, winning_player):
utility += 1
else:
utility -= 1
first_to_play = util.index_of_player_with_name(game_state, winning_player)
return utility