Skip to content

Instantly share code, notes, and snippets.

@mueslo
Last active December 28, 2015 18:39
Show Gist options
  • Save mueslo/7544271 to your computer and use it in GitHub Desktop.
Save mueslo/7544271 to your computer and use it in GitHub Desktop.
erere
import rg
import numpy as np
class Robot:
#desirability of certain number of neighbours:
# num 0 1 2 3 4
des_en = [0, 1, -2, -3, -4] #Enemy
des_tn = [0, 1, 2, 1, 0] #Team
direction = {
(1,0) : "right",
(0,1) : "down",
(-1,0) : "left",
(0,-1) : "up"
}
def note(self,s):
self.to_print += '\033[93m'+s+'\033[0m'
def warn(self,s):
self.to_print += '\033[91m'+s+'\033[0m'
def echo(self,s):
self.to_print += s
def same_team_as(self,bot):
return bot.player_id == self.player_id
def suicide_outcome(self):
#outcome is damage difference between steps and teams
outcome = -self.hp
for n in self.neighbours:
if n["enemy"]==True:
outcome += 15 if n["health"]>15 else n["health"]
return outcome
def move_outcome(self,loc):
outcome = 0
#new_neighbours = self.neighbours_around(loc)
#new state variables:
#new_n_en = len(filter((lambda x: x["enemy"]==True),new_neighbours))
#new_n_tn = len(filter((lambda x: x["enemy"]==False),new_neighbours))
#new_dist_to_tcom = rg.dist(loc,self.tcom)
new_dist_to_ecom = rg.dist(loc,self.ecom)
#delta_dist_tcom = new_dist_to_tcom - self.dist_to_tcom
delta_dist_ecom = new_dist_to_ecom - self.dist_to_ecom
#change in desirability due to enemies
#outcome += self.des_en[new_n_en]-self.des_en[self.n_en]
#change in desirability due to friendlies
#outcome += self.des_tn[new_n_tn]-self.des_tn[self.n_tn]
#change in desirability due to moving towards center of mass
outcome += 2*(delta_dist_ecom<0)
#todo change in desirability due to self, team or enemy health
return outcome
def neighbours_around(self, loc):
neighbours = []
for other_loc,other_bot in self.gamestate:
# nearest neighbour but not the one we just came from
if rg.wdist(other_loc,loc) <= 1 and other_loc!=self.location:
neighbours.append(
{"loc":other_loc,
"health":other_bot.hp,
"enemy":(not self.same_team_as(other_bot))
})
return neighbours
def team_center_of_mass(self):
#NOTE: would center of health be a good indicator of sth?
locs = []
for loc,bot in self.gamestate:
if self.same_team_as(bot):
locs.append(loc)
if len(locs)>0:
return tuple(np.average(locs, axis=0))
else:
return rg.CENTER_POINT
def enemy_center_of_mass(self):
locs = []
for loc,bot in self.gamestate:
if not self.same_team_as(bot):
locs.append(loc)
if len(locs)>0:
return tuple(np.average(locs, axis=0))
else:
return rg.CENTER_POINT
def expected_team_config(self):
self.echo("nothing!")
#return moved ally units
#returns index of chosen element
def choose_outcome(self,outcome_list):
#return np.argmax(outcome_list)
p = np.exp(outcome_list)
p = p/sum(p) #normalize
return np.random.choice(len(outcome_list),p=p)
def update_state_variables(self):
self.to_print = ""
self.note("Team {1}'s Robot at {0} is acting...\t".format(self.location,self.player_id))
self.neighbours = self.neighbours_around(self.location)
self.en = filter((lambda x: x["enemy"]==True),self.neighbours)
self.tn = filter((lambda x: x["enemy"]==False),self.neighbours)
self.n_en = len(self.en)
self.n_tn = len(self.tn)
self.empty_neighbour_cells=rg.locs_around(self.location, filter_out=('invalid', 'obstacle'))
self.tcom = self.team_center_of_mass()
self.ecom = self.enemy_center_of_mass()
self.dist_to_tcom = rg.dist(self.tcom,self.location)
self.dist_to_ecom = rg.dist(self.ecom,self.location)
def choose_action(self):
#suicide does more damage to enemy team than attacking
if self.suicide_outcome()>8:
self.warn(" -> SUICIDE! Expected effective damage: {0}".format(self.suicide_outcome()))
return ["suicide"]
if self.n_en>0:
#health_vals = [nb["health"] for nb in self.en]
outcomes = []
for enemy in self.en:
#number of teammates around enemy
n_surr = len(filter((lambda x: x["enemy"]==False),self.neighbours_around(enemy["loc"])))
outcomes.append(abs(enemy["health"]-8*n_surr))
attack_loc = self.en[np.argmin(outcomes)]["loc"]
delta_loc = tuple(np.array(attack_loc)-np.array(self.location))
self.echo(" -> Attacking "+self.direction[delta_loc])
return ['attack', attack_loc]
# if there are enemies around, attack them
#for loc, bot in self.gamestate:
# if not self.same_team_as(bot):
# if rg.wdist(loc, self.location) <= 1:
# return ['attack', loc]
#todo: anticipate team moves
outcomes = map(self.move_outcome, self.empty_neighbour_cells)
i = self.choose_outcome(outcomes)
delta_locs = [tuple(np.array(loc)-np.array(self.location)) for loc in self.empty_neighbour_cells]
self.echo(" -> Moving "+self.direction[delta_locs[i]]+str(zip(outcomes,[self.direction[loc] for loc in delta_locs])))
return ["move", self.empty_neighbour_cells[i]]
# move toward the enemy's center of mass
#return ['move', loc]
def act(self, game):
self.gamestate = game.get("robots").items()
self.update_state_variables()
action = self.choose_action()
#print self.to_print
return action
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment