-
Notifications
You must be signed in to change notification settings - Fork 0
/
MAIN.py
executable file
·277 lines (223 loc) · 8.81 KB
/
MAIN.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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import generals
import heapq
# 1v1
#g = generals.Generals('ry0FVyx_g', 'frank', '1v1')
# ffa
# g = generals.Generals('your userid', 'your username', 'ffa')
# private game
#roomID = raw_input("Please enter the room id: ")
#print(roomID)
#g = generals.Generals('ry0FVyx_g', 'frank', 'private', roomID)
# 2v2 game
# g = generals.Generals('your userid', 'your username', 'team')
RIGHT = (0, 1)
LEFT = (0, -1)
UP = (-1, 0)
DOWN = (1, 0)
dirs = {(0, 1): "RIGHT", (0, -1): "LEFT", (-1, 0): "UP", (1, 0): "DOWN"}
class Tile:
def __init__(self):
self.state = generals.FOG # what is on the tile
self.visited = False # while traversing, marks if visited
self.coords = [] # coordinates in grid
self.up = None # Node above it
self.down = None # Node below it
self.left = None # Node to left of it
self.right = None # Node to right of it
self.army = 0 # Number of troops on the tile (- means good)
self.searchDist = 0 #
self.searchPrev = None
class Bot:
def __init__(self):
self.mapGrid = [] # a representation of the map as a 2x2 matrix
self.tiles = [] # a list of all tiles
self.roomID = "" # the id of current game
self.nCols = 0 # number of columns in the map
self.nRows = 0 # number of rows in the map
self.game = None
self.color = ""
def getSize(self):
return len(self.mapGrid)
def startGame(self,game="private"):
if game == "1v1":
self.game = generals.Generals('ry0FVyx_g', 'frank', '1v1')
elif game == "ffa":
self.game = generals.Generals('ry0FVyx_g', 'frank', 'ffa')
elif game == "private":
self.roomID = raw_input("Please enter the room id: ")
self.game = generals.Generals('ry0FVyx_g', 'frank', 'private', self.roomID)
elif game == "2v2":
self.game = generals.Generals('ry0FVyx_g', 'frank', 'team')
else:
print("Please input one of the following game types: ")
print("1v1, ffa, private, 2v2")
def initializeMap(self,update):
'''Creates a map with nodes and connects the nodes
to create a graph that the bot can traverse'''
self.createMap(update)
for i in range(self.nRows):
for j in range(self.nCols):
#print("updated tile: "+str(i)+" "+str(j))
currTile = self.mapGrid[i][j]
currTile.coords = [i,j]
if i+1 < self.nRows: # check down
if update['tile_grid'][i+1][j] in [generals.FOG,1,-1]:
currTile.down = self.mapGrid[i+1][j]
if i-1 >= 0: # check up
if update['tile_grid'][i-1][j] in [generals.FOG,1,-1]:
currTile.up = self.mapGrid[i-1][j]
if j+1 < self.nCols: # check right
if update['tile_grid'][i][j+1] in [generals.FOG,1,-1]:
currTile.right = self.mapGrid[i][j+1]
if j-1 >= 0: # check left
if update['tile_grid'][i][j-1] in [generals.FOG,1,-1]:
currTile.left = self.mapGrid[i][j-1]
def updateMap(self,update):
for i in range(self.nRows):
for j in range(self.nCols):
botTile = self.mapGrid[i][j]
tile = update['tile_grid'][i][j]
troops = update['army_grid'][i][j]
if tile == generals.MOUNTAIN:
botTile.state = generals.MOUNTAIN
elif tile == generals.FOG:
botTile.state = generals.FOG
elif tile == generals.OBSTACLE:
botTile.state = generals.OBSTACLE
elif tile == generals.ENEMY:
botTile.state = generals.ENEMY
botTile.army = troops
if self.color == "blue":
botTile.army *= -1
elif tile == generals.BOT:
botTile.state = generals.BOT
botTile.army = troops
if self.color == "red":
botTile.army *= -1
elif tile == generals.EMPTY:
botTile.state = generals.EMPTY
else:
print("unknown state")
def dijkstras(self,root,target):
heap = []
for t in self.tiles:
t.searchDist = 1000000
t.searchPrev = None
root.searchDist = 0
heapp.heappush(heap,t)
while heap != []:
u = heapq.heappop(heap)
for v in [u.up,u.down,u.left,u.right]:
if v:
alt = u.searchDist + v.army
if alt < v.searchDist:
v.searchDist = alt
v.searchPrev = u
return target
def createMap(self, update):
'''Craetes the initial Map - a 2D array with a
Tile object in each index'''
self.nCols = update['cols']
self.nRows = update['rows']
self.mapGrid = [ [Tile() for i in range(self.nCols)] for j in range(self.nRows) ]
def printMap(self):
print("")
for i in range(self.nRows):
rowStr = ""
for j in range(self.nCols):
tile = self.mapGrid[i][j]
if tile.state == generals.MOUNTAIN:
rowStr += "[ M ]"
elif tile.state == generals.FOG:
rowStr += "[|||]"
elif tile.state == generals.OBSTACLE:
rowStr += "[ M ]"
elif tile.state == generals.ENEMY:
rowStr += "[ "+str(tile.army)+" ]"
elif tile.state == generals.BOT:
rowStr += "[ "+str(tile.army)+" ]"
elif tile.state == generals.EMPTY:
rowStr += "[ ]"
else:
rowStr += "[ "+str(tile)+" ]"
print(rowStr)
print("")
print("")
def checkInRange(size, x, y):
return x < size and y < size and y > -1 and x > -1
frank = Bot()
frank.startGame()
madeMap = False
stackX = 0
stackY = 0
curDir = None
for update in frank.game.get_updates():
frank.printMap()
if madeMap == False: # only happens once at the start
frank.initializeMap(update)
pi = update['player_index']
crownY, crownX = update['generals'][pi]
if frank.mapGrid[crownY][crownX].army > 0:
frank.color = "red"
else:
frank.color = "blue"
stackX = crownX
stackY = crownY
madeMap = True
frank.updateMap(update)
if frank.mapGrid[stackY][stackX].army > -1: # If the current spot has one or fewer troops,
stackX = crownX # make the current stack the crown stack
stackY = crownY
# print("Stack: [" + str(stackX) + "," + str(stackY) + "]")
moved = False
for dy, dx in [(0, 1), (0, -1), (1, 0), (-1, 0)]: # all directions
if checkInRange(frank.getSize(), stackY+dy, stackX+dx): # if the dir is valid
print(frank.getSize())
print(stackY+dy)
print(stackX+dx)
if frank.mapGrid[stackY+dy][stackX + dx].army >= 1: # if there is an enemy troop next to stack
frank.game.move(stackY, stackX, stackY + dy, stackX + dx)
stackX += dx
stackY += dy
moved = True
break
if moved == False: # if we did not find an enemy troop
if curDir != None: # if we have a current direction
dy, dx = curDir # store that dir
if checkInRange(frank.getSize(), stackY+dy, stackX+dx): # if the dir is valid
if frank.mapGrid[stackY+dy][stackX+dx].army <= -1:
frank.game.move(stackY, stackX, stackY + dy, stackX + dx)
stackX += dx
stackY += dy
else:
if curDir == UP or curDir == DOWN:
dy, dx = LEFT
if checkInRange(frank.getSize(), stackY+dy, stackX+dx): # if the dir is valid
if frank.mapGrid[stackY+dy][stackX+dx].army <= -1:
print("HEADING LEFT")
curDir = LEFT
else:
print("HEADING RIGHT")
curDir = RIGHT
else:
dy, dx = UP
if checkInRange(frank.getSize(), stackY+dy, stackX+dx): # if the dir is valid
if frank.mapGrid[stackY+dy][stackX+dx].army <= -1:
print("HEADING UP")
curDir = UP
else:
print("HEADING DOWN")
curDir = DOWN
dy, dx = curDir
frank.game.move(stackY, stackX, stackY + dy, stackX + dx)
stackX += dx
stackY += dy
else:
for dy, dx in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
if checkInRange(frank.getSize(), stackY+dy, stackX+dx):
if frank.mapGrid[stackY+dy][stackX+dx].army <= -1: # if we have an existing path off the castle
frank.game.move(stackY, stackX, stackY + dy, stackX + dx)
stackX += dx
stackY += dy
curDir = (dy, dx)
break