Last active
December 28, 2015 18:39
-
-
Save mueslo/7544271 to your computer and use it in GitHub Desktop.
erere
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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