Improvements on states, last turns strategy, and money management

This commit is contained in:
Vylion 2018-12-17 03:05:13 +01:00
parent cc28851e03
commit 1811f38482

119
mybot2.py
View file

@ -24,15 +24,19 @@ class Pilot(object):
class Harvester(Pilot): class Harvester(Pilot):
Role = "HARVESTER" Role = "HARVESTER"
StateHarvest = "HARVEST" StatusSearch = "SEARCH"
StateDeposit = "DEPOSIT" StatusHarvest = "HARVEST"
StatusDeposit = "DEPOSIT"
StatusRunback = "RUNBACK"
StatusLeave = "LEAVING"
def __init__(self, ai, ship): def __init__(self, ai, ship):
super(Harvester, self).__init__(ai, ship) super(Harvester, self).__init__(ai, ship)
self.status = "INACTIVE" self.status = "INACTIVE"
self.log("{} Pilot assigned to ship".format(Harvester.Role)) self.log("{} Pilot assigned to ship".format(Harvester.Role))
self.status = Harvester.StateHarvest self.status = Harvester.StatusSearch
self.role = Harvester.Role self.role = Harvester.Role
self.target = self.ai.shipyard().position
def log(self, s): def log(self, s):
super(Harvester, self).log("[{}] {}".format(self.status, s)) super(Harvester, self).log("[{}] {}".format(self.status, s))
@ -40,7 +44,9 @@ class Harvester(Pilot):
def getHalitestNeighbor(self, ship): def getHalitestNeighbor(self, ship):
halitest = ship.position halitest = ship.position
map = self.ai.map() map = self.ai.map()
for neighbor in ship.position.get_surrounding_cardinals(): neighbors = ship.position.get_surrounding_cardinals()
random.shuffle(neighbors)
for neighbor in neighbors:
if map[neighbor].halite_amount > map[halitest].halite_amount: if map[neighbor].halite_amount > map[halitest].halite_amount:
halitest = neighbor halitest = neighbor
return halitest return halitest
@ -51,16 +57,28 @@ class Harvester(Pilot):
closest = (None, 0) closest = (None, 0)
for dropoff in self.ai.dropoffs: for dropoff in self.ai.dropoffs:
dist = map.calculate_distance(source, dropoff) dist = map.calculate_distance(source, dropoff)
if closest[0] == None or closest[1] > dist: if closest[0] is None or closest[1] > dist:
closest = (dropoff, dist) closest = (dropoff, dist)
return closest[0] return closest[0]
def shouldBuild(self, ship): def shouldBuild(self, ship):
return (self.status == Harvester.StateDeposit and self.static > 5 and should = (self.status == Harvester.StatusDeposit and self.static > 5)
self.ai.me().halite_amount >= constants.DROPOFF_COST) can = self.ai.current_halite >= constants.DROPOFF_COST
def harvest(self, ship): closest = self.getClosestDropoff(ship)
self.log("Harvesting; collected halite: {}".format(ship.halite_amount)) map = self.ai.map()
dist = map.calculate_distance(ship.position, closest)
worth = dist > self.static
return can and should and worth and not self.ai.noMoreCosts
def amOnTime(self, ship):
map = self.ai.map()
closest = self.getClosestDropoff(ship)
distance = map.calculate_distance(ship.position, closest)
return distance*2 <= constants.MAX_TURNS - self.ai.turn()
def search(self, ship):
self.log("Searching; collected halite: {}".format(ship.halite_amount))
map = self.ai.map() map = self.ai.map()
shipyard = self.ai.shipyard() shipyard = self.ai.shipyard()
@ -72,6 +90,13 @@ class Harvester(Pilot):
return ship.move(order) return ship.move(order)
def step(self, ship): def step(self, ship):
if (not self.amOnTime(ship) and self.status != Harvester.StatusRunback
and self.status != Harvester.StatusLeave):
self.ai.noMoreCosts = True
self.status = Harvester.StatusRunback
self.target = self.getClosestDropoff(ship)
self.log("Initiating runback")
if ship.position == self.lastPos: if ship.position == self.lastPos:
self.static += 1 self.static += 1
else: else:
@ -79,35 +104,66 @@ class Harvester(Pilot):
self.lastPos = ship.position self.lastPos = ship.position
if self.shouldBuild(ship): if self.shouldBuild(ship):
self.log("Bulding Dropoff point")
self.ai.addDropoff(ship.position) self.ai.addDropoff(ship.position)
self.ai.current_halite -= constants.DROPOFF_COST
return ship.make_dropoff() return ship.make_dropoff()
map = self.ai.map() map = self.ai.map()
shipyard = self.ai.shipyard() shipyard = self.ai.shipyard()
# Status is returning to deposit halite on a dropoff point # Status is runback, last deposit run
if self.status == Harvester.StateDeposit: if self.status == Harvester.StatusRunback:
# Deposited successfully # Deposited successfully
if ship.position == self.ai.shipyard().position: if ship.position == self.target:
self.log("Halite has been deposited") self.log("Halite has been deposited one last time")
self.status = Harvester.StateHarvest self.status = Harvester.StatusLeave
self.target = random.choice(self.ai.enemyShipyards()).position
self.target = map.normalize(self.target)
# Still travelling to dropoff point # Still travelling to dropoff point
else: else:
if self.ai.newDropoffs: if self.ai.newDropoffs:
self.dropoff = self.getClosestDropoff(ship) self.target = self.getClosestDropoff(ship)
order = map.naive_navigate(ship, self.dropoff) order = map.naive_navigate(ship, self.target)
return ship.move(order) return ship.move(order)
# Status is harvesting halite; halite exceeds criteria for dropoff # Make way for other Runbacks
elif ship.halite_amount >= constants.MAX_HALITE / 2: if self.status == self.StatusLeave:
if map[ship.position].halite_amount > 0 and ship.halite_amount < constants.MAX_HALITE: order = map.get_unsafe_moves(ship.position, self.target)[0]
self.log("Finishing halite harvest") return ship.move(order)
# Status is returning to deposit halite on a dropoff point
if self.status == Harvester.StatusDeposit:
# Deposited successfully
if ship.position == self.target:
self.log("Halite has been deposited")
self.status = Harvester.StatusSearch
# Still travelling to dropoff point
else:
if self.ai.newDropoffs:
self.target = self.getClosestDropoff(ship)
order = map.naive_navigate(ship, self.target)
return ship.move(order)
# Status is searching for halite
elif self.status == Harvester.StatusSearch:
order = self.search(ship)
if (order == Direction.Still or
ship.halite_amount + map[ship.position].halite_amount > constants.MAX_HALITE * 3/4):
self.log("Stopping to harvest halite")
self.status = Harvester.StatusHarvest
return ship.stay_still() return ship.stay_still()
else:
return order
# Status is harvesting halite in current tile
elif self.status == Harvester.StatusHarvest:
# Enough to go to deposit halite
if ship.halite_amount >= constants.MAX_HALITE*2 / 3:
self.log("Returning to deposit collected halite: {}" self.log("Returning to deposit collected halite: {}"
.format(ship.halite_amount)) .format(ship.halite_amount))
self.status = Harvester.StateDeposit self.status = Harvester.StatusDeposit
self.dropoff = self.getClosestDropoff(ship) self.target = self.getClosestDropoff(ship)
# Status is harvesting halite return ship.stay_still()
else: # Not enough to go deposit halite
return self.harvest(ship) elif map[ship.position].halite_amount <= 0:
self.status = Harvester.StatusSearch
return self.setp(ship)
return ship.stay_still() return ship.stay_still()
class Brain(object): class Brain(object):
@ -120,6 +176,8 @@ class Brain(object):
self.noEnemiesCheck = (game.turn_number, False) self.noEnemiesCheck = (game.turn_number, False)
self.dropoffs = [game.me.shipyard.position] self.dropoffs = [game.me.shipyard.position]
self.newDropoffs = False self.newDropoffs = False
self.noMoreCosts = False
self.current_halite = game.me.halite_amount
self.enemies = {} self.enemies = {}
for key, player in game.players.items(): for key, player in game.players.items():
@ -142,6 +200,9 @@ class Brain(object):
def shipyard(self): def shipyard(self):
return self.game.me.shipyard return self.game.me.shipyard
def enemyShipyards(self):
return [self.enemies[pid].shipyard for pid in self.enemies]
def addDropoff(self, pos): def addDropoff(self, pos):
self.newDropoffs = True self.newDropoffs = True
self.dropoffs.append(pos) self.dropoffs.append(pos)
@ -149,11 +210,11 @@ class Brain(object):
def canSpawn(self): def canSpawn(self):
me = self.me() me = self.me()
map = self.map() map = self.map()
return me.halite_amount >= constants.SHIP_COST and not map[me.shipyard].is_occupied return self.current_halite >= constants.SHIP_COST and not map[me.shipyard].is_occupied
def shouldSpawn(self): def shouldSpawn(self):
rate = random.expovariate(self.game.turn_number / 15) rate = random.expovariate(self.game.turn_number / 20)
return self.turn() <= 1 or random.random() <= rate return not self.noMoreCosts and (self.turn() <= 1 or random.random() <= rate)
def tailingSpawn(self): def tailingSpawn(self):
bestPlayer = None bestPlayer = None
@ -169,6 +230,7 @@ class Brain(object):
me = self.me() me = self.me()
map = self.map() map = self.map()
shipyard = self.shipyard() shipyard = self.shipyard()
self.current_halite = me.halite_amount
# A command queue holds all the commands you will run this turn. # A command queue holds all the commands you will run this turn.
commands = [] commands = []
@ -184,6 +246,7 @@ class Brain(object):
# If you're on the first turn and have enough halite, spawn a ship. # If you're on the first turn and have enough halite, spawn a ship.
# Don't spawn a ship if you currently have a ship at port, though. # Don't spawn a ship if you currently have a ship at port, though.
if self.canSpawn() and self.shouldSpawn(): if self.canSpawn() and self.shouldSpawn():
self.current_halite -= constants.SHIP_COST
commands.append(shipyard.spawn()) commands.append(shipyard.spawn())
# Send your moves back to the game environment, ending this turn. # Send your moves back to the game environment, ending this turn.