-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvonbots.py
More file actions
207 lines (170 loc) · 7.7 KB
/
vonbots.py
File metadata and controls
207 lines (170 loc) · 7.7 KB
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from random import randint
from Player import Player
from math import log
DECK_SIZE = 24
# 20% chance of taking the card
class PlayerV(Player):
def wants_card(self, card, schmibbets, game_state):
return True if randint(0, 5) == 0 else False
# Will take card if it's adjacent to a currently owned card and has more than 4 schmibbets
# Will take card if it's within 2 numbers of a currently owned card, and has more schmibbets than the player does
# Won't take card if it's 2 away, and the directly adjacent card has already been taken
# Will take card if it is more likely to draw another card with a higher number than the current value
# Will only take a card in this way if the card has more schmibbets than the player does
class PlayerW(Player):
def wants_card(self, card, schmibbets, game_state):
if schmibbets > self.schmibbets:
under = 0
over = 0
card_val = card - schmibbets
for i in game_state.get_cards_taken():
if i < card - card_val:
under += 1
if i > card - card_val:
over += 1
if under < over:
return True
for i in self.cards:
if card in [i - 1, i + 1] and schmibbets > 4:
return True
if schmibbets > self.schmibbets:
if card == i - 2 and i - 1 in game_state.get_cards_taken():
return True
if card == i + 2 and i + 1 in game_state.get_cards_taken():
return True
return False
# Will take card if it has none and one of the following are true:
# a) Card is less than 11
# b) Card is less than 21 and has 5 Schmibbets
# c) Card is less than 31 and has 10 Schmibbets
# d) Card has 15 Schmibbets
# Will take card if value is less than 9
# Will take card if it's directly preceding an existing card
# Will take card if it's directly succeeding an existing card and has 5 Schmibbets
class PlayerX(Player):
def wants_card(self, card, schmibbets, game_state):
if not self.cards:
if card <= 10:
return True
if card <= 20 and schmibbets >= 5:
return True
if card <= 30 and schmibbets >= 10:
return True
if schmibbets >= 15:
return True
if card - schmibbets <= 8:
return True
for i in self.cards:
if card == i - 1:
return True
if schmibbets >= 5 and card == i + 1:
return True
return False
# Will take card if it has none and one of the following are true:
# a) Card is in lower third and has 5 schmibbets
# b) Card is in middle third and has 10 schmibbets
# c) Card has 15 schmibbets
# Will take card if value is less than 5
# Will take card if it's directly preceding an existing card
# Will take card if it's directly succeeding an existing card and has 5 schmibbets
class PlayerY(Player):
def wants_card(self, card, schmibbets, game_state):
if not self.cards:
if card <= 14 and schmibbets >= 5:
return True
if card <= 25 and schmibbets >= 10:
return True
if schmibbets >= 15:
return True
if card - schmibbets <= 4:
return True
for i in self.cards:
if card == i - 1:
return True
if card == i + 1 and schmibbets >= 5:
return True
return False
class PlayerZ(Player):
def wants_card(self, card, schmibbets, game_state):
if not self.cards and card / 3 - schmibbets <= 0:
return True
if card - schmibbets < 6 or (self.schmibbets < self.starting_schmibbets and card - schmibbets < 9):
return True
for i in self.cards:
if card == i - 1 and (schmibbets > 0 or i - 2 not in game_state.get_cards_taken()):
return True
if card == i + 1 and (schmibbets > 4 or i + 2 not in game_state.get_cards_taken()):
return True
if schmibbets > 4 and card == i - 2 and i - 1 in game_state.get_cards_taken():
return True
if schmibbets > 9 and card == i + 2 and i + 1 in game_state.get_cards_taken():
return True
return False
class GoodPlayer(Player):
ADJACENT_CARD_PARAM = 3.5
SEMI_ADJACENT_MULTIPLE_PARAM = .25
MYSTERY_VALUE_PARAM = 1.2
SCHMIBBET_VALUE_PARAM = 4
def wants_card(self, card, schmibbets, game_state):
if self.is_card_adjacent(card):
return True
card_value = 0
cards_available = game_state.get_cards_available()
if (card + 1) in cards_available:
card_value += self.ADJACENT_CARD_PARAM
if (card + 2) in cards_available:
card_value += self.ADJACENT_CARD_PARAM * self.SEMI_ADJACENT_MULTIPLE_PARAM
if (card - 1) in cards_available:
card_value += self.ADJACENT_CARD_PARAM
if (card - 2) in cards_available:
card_value += self.ADJACENT_CARD_PARAM * self.SEMI_ADJACENT_MULTIPLE_PARAM
turn_factor = (1 - 1 / (1 + len(game_state.deck) / 25)) * self.MYSTERY_VALUE_PARAM
decision = (card_value + schmibbets * self.SCHMIBBET_VALUE_PARAM) * turn_factor - card>= 0
return decision
def is_card_adjacent(self, card):
for c in self.cards:
if abs(c - card) == 1:
return True
return False
class FuturePlayer(Player):
# SCHMIBBETS_PER_VALUE_EST = .138
# TURNS_PER_GAME = 22.5
def wants_card(self, card, schmibbets, game_state):
return false
# if self.is_card_adjacent(card):
# # print(f"taking card {card} with schmibbets {schmibbets}. {self.cards}")
# return True
# # est_turns_remaining = self.est_turns_remaining(card, schmibbets, game_state)
# # if est_turns_remaining > self.schmibbets: # take it we need schmibbets period
# # print(f"taking card {card} with schmibbets {schmibbets}. {self.cards} because turns")
# # return True
# card_value = 0
# cards_available = game_state.get_cards_available()
# init_card_value = 3.5
# second_card_ratio = .25
# if (card + 1) in cards_available:
# card_value += init_card_value
# if (card + 2) in cards_available:
# card_value += init_card_value * second_card_ratio
# if (card - 1) in cards_available:
# card_value += init_card_value
# if (card - 2) in cards_available:
# card_value += init_card_value * second_card_ratio
# # turn_factor = (est_turns_remaining / self.TURNS_PER_GAME)
# turn_factor = (1 - 1 / (1 + len(game_state.deck) / 25)) * 1.2
# decision = (card_value + schmibbets * 4) * turn_factor - card>= 0
# # print(f"card: {card}, value: {card_value}, schmibbets: {schmibbets}, turn_factor: {turn_factor}")
# # decision = schmibbets / card > .138 # take it if it's more than average
# # if decision:
# # print(f"taking card {card} with schmibbets {schmibbets}. {self.cards} because value")
# return decision
# def is_card_adjacent(self, card):
# for c in self.cards:
# if abs(c - card) == 1:
# return True
# return False
# # def est_turns_remaining(self, current_card, current_schmibbets, game_state):
# # turns = max(current_card * self.SCHMIBBETS_PER_VALUE_EST - current_schmibbets, 0)
# # for card in game_state.deck: # cheating
# # turns += card * self.SCHMIBBETS_PER_VALUE_EST
# # return turns / len(game_state.players)