-
Notifications
You must be signed in to change notification settings - Fork 0
/
myPlayerBrain.py
executable file
·238 lines (196 loc) · 8.48 KB
/
myPlayerBrain.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
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# Team Guest
# UVic 2016
# Michael Reiter, Kurt Dorflinger, Juan Carlos Gallegos, Nicholas Kobald
import random as rand
import api.units as lib
from api.units import SpecialPowers
import logic
NAME = "Team Guest"
SCHOOL = "University of Victoria"
def random_element(list):
if len(list) < 1:
print "random element from empty list? returning None..."
return None
return list[rand.randint(0, len(list) - 1)]
class MyPlayerBrain(object):
"""The Python AI class."""
def __init__(self):
self.name = NAME
self.school = SCHOOL
if NAME is "Anders Hejlsberg" or SCHOOL is "Windward U.":
print "Please enter your name and university at the top of MyPlayerBrain.py"
#The player's avatar (looks in the same directory that this module is in).
#Must be a 32 x 32 PNG file.
try:
avatar = open("avatar.jpg", "rb")
avatar_str = b''
for line in avatar:
avatar_str += line
avatar = avatar_str
except IOError:
avatar = None # avatar is optional
self.avatar = avatar
def Setup(self, map, me, hotelChains, players):
self.turn_count = 0
self.drawUsed = False
def QuerySpecialPowersBeforeTurn(self, map, me, hotelChains, players):
if (self.turn_count == 0 or self.turn_count == 1) and not self.drawUsed:
self.drawUsed = True
return SpecialPowers.DRAW_5_TILES
return SpecialPowers.NONE
def QueryTileOnly(self, map, me, hotelChains, players):
tile = random_element(me.tiles)
createdHotel = next((hotel for hotel in hotelChains if not hotel.is_active), None)
mergeSurvivor = next((hotel for hotel in hotelChains if hotel.is_active), None)
return PlayerPlayTile(tile, createdHotel, mergeSurvivor)
def QueryTileAndPurchase(self, map, me, hotelChains, players):
self.turn_count += 1
# Determine what move to do on your turn
choice = self.chooseTileMove(map, me, hotelChains)
turn = PlayerTurn(tile=choice[0],
created_hotel=choice[1], merge_survivor=choice[2])
# Buy stocks, if on turn 6 buy 5
if self.turn_count == 6:
turn.Card = SpecialPowers.BUY_5_STOCK
turn.Buy.extend(self.chooseStockPurchases(me, hotelChains, 5))
else:
# Determine what stocks to buy
turn.Buy.extend(self.chooseStockPurchases(me, hotelChains, 3))
# Use our super powers
if self.turn_count == 5:
turn.Card = SpecialPowers.FREE_3_STOCK
return turn
def QueryMergeStock(self, map, me, hotelChains, players, survivor, defunct):
myStock = next((stock for stock in me.stock if stock.chain == defunct.name), None)
trade = myStock.num_shares / 3
if trade % 2 != 0:
trade += 1
sell = myStock.num_shares - trade
return PlayerMerge(sell, 0, trade)
def checkAdjacentTile(self, map, me, i, j):
# Possible outcomes: all empty, one+ single, one+ hotel
# These are the number of empty, single or hotels adjacent to the input tile (i, j)
empty = 0
single = 0
hotel = 0
merging = []
creating = []
# For every adjacent tile, check if it is either empty, single or hotel
# Check to the left of the current tile
if i > 0:
curr = map.tiles[i - 1][j]
if curr.Type == curr.SINGLE:
single += 1
creating.append(map.tiles[i - 1][j])
elif curr.Type == curr.HOTEL:
hotel += 1
merging.append((curr, curr.hotel))
elif curr.Type == curr.UNDEVELOPED:
empty += 1
# Check to the right of the current tile
if i < map.width - 1:
curr = map.tiles[i + 1][j]
if curr.Type == curr.SINGLE:
single += 1
creating.append(map.tiles[i + 1][j])
elif curr.Type == curr.HOTEL:
hotel += 1
merging.append((curr, curr.hotel))
elif curr.Type == curr.UNDEVELOPED:
empty += 1
# Check above the current tile
if j > 0:
curr = map.tiles[i][j - 1]
if curr.Type == curr.SINGLE:
single += 1
creating.append(map.tiles[i][j - 1])
elif curr.Type == curr.HOTEL:
hotel += 1
merging.append((curr, curr.hotel))
elif curr.Type == curr.UNDEVELOPED:
empty += 1
# Check below the current tile
if j < map.height - 1:
curr = map.tiles[i][j + 1]
if curr.Type == curr.SINGLE:
single += 1
creating.append(map.tiles[i][j + 1])
elif curr.Type == curr.HOTEL:
hotel += 1
merging.append((curr, curr.hotel))
elif curr.Type == curr.UNDEVELOPED:
empty += 1
# If there are hotels adjacent
if hotel > 0:
return [hotel + single, "hotel", merging]
# If there are single hotel tiles adjacent
elif single > 0:
return [single, "single", creating]
# Otherwise there are no tiles adjacent
else:
return [0, "empty"]
def chooseTileMove(self, map, me, hotelChains):
create = []
expand = []
mergers = []
# This populates lists for which moves will create a company,
# which moves will expand a company, and which moves will cause a merger.
for i in xrange(map.width):
for j in xrange(map.height):
for tile in me.tiles:
if i == tile.x and j == tile.y:
# Check adjacent tiles to see what it would result in
result = self.checkAdjacentTile(map, me, i, j)
if result[1] == "hotel":
mergers.append([result, map.tiles[i][j], i, j])
elif result[1] == "single":
create.append([result, map.tiles[i][j], i, j])
else:
expand.append([map.tiles[i][j], i, j])
# Determine which move you want to use here
inactive = next((hotel for hotel in hotelChains if not hotel.is_active), None)
chosen = logic.chooseTileMove(create, expand, mergers, me, inactive)
if chosen is None:
return [random_element(me.tiles), inactive, inactive]
else:
return chosen
def chooseStockPurchases(self, me, hotelChains, stockCount):
options = []
# Create a list of hotel stocks that can be bought (are active) and the
# currently owned shares. options = [[hotel, shares owned], ...]
for hotel in hotelChains:
if hotel.is_active:
added = False
for stock in me.stock:
if stock.chain == hotel:
added = True
options.append([hotel, stock.num_shares])
break
if not added:
options.append([hotel, 0])
# Expects a list in the form of [lib.HotelStock(hotel, purchase amount), ...]
buyList = logic.chooseStockPurchases(options, hotelChains, stockCount)
if buyList is None:
return [lib.HotelStock(random_element(hotelChains), rand.randint(1, 4))]
else:
return buyList
class PlayerMerge(object):
def __init__(self, sell, keep, trade):
self.Sell = sell
self.Keep = keep
self.Trade = trade
class PlayerPlayTile(object):
def __init__(self, tile, created_hotel, merge_survivor):
self.Tile = tile
self.CreatedHotel = created_hotel
self.MergeSurvivor = merge_survivor
class PlayerTurn(PlayerPlayTile):
def __init__(self, tile, created_hotel, merge_survivor):
super(PlayerTurn, self).__init__(tile, created_hotel, merge_survivor)
self.Card = lib.SpecialPowers.NONE
self.Buy = [] # hotel stock list
self.Trade = [] # trade stock list
class TradeStock(object):
def __init__(self, trade_in, get):
self.Trade = trade_in
self.Get = get