Example #1
0
    def TakeAction(self,t):
        if not self.IsPlayer() and len(self.action_list) == 0:
            path,cost,enemy = self.FindNearestEnemy()
            if not enemy:
                return False
            offset = enemy.pos-self.pos

            #Check first if we can blast anyone
            for index,action in utils.r_enumerate(self.blast_action_creator.actions):
                if action.cost <= self.stats.mana:
                    self.blast_action_creator.SetAction(index)
                    if self.blast_action_creator.Valid(offset):
                        self.action_list.extend( self.blast_action_creator.Create(offset,t,self) )
                        return self.action_list.pop(0)

        #If we get here there's nothing to return
        return super(BlastingMonster,self).TakeAction(t)
Example #2
0
    def TakeAction(self,t):

     # +-----------------------------------------------------------------------------------+
     # |                   ..-#.--                         .  -.                           |
     # |                   -.%--+                         . .+..+..                        |
     # |                   .m##-m.                           ###+m                         |
     # |                   -m-*%%+.                         -m+%+--                        |
     # |                    +%m% .                          .++++                          |
     # |                     +-.-.       ..++-   ..            -.                          |
     # |                     .  .   . . .m--+.-. -- . .      .                             |
     # |                            .. +-. .mm-%.-. -..-                                   |
     # |                          ..  m.#**###-*#%##+.m +                                  |
     # |                         -%%.#*#m. -m-+.. +.*#+* -.                                |
     # |                         -.+#-m-+.  -..- +.+-+##-                                  |
     # |                        +-##m.  .-.... . . .-.+*%+.                                |
     # |                      - +-#%.               --m.%m-.                               |
     # |                     ...m+m+..              . ..#+-.                               |
     # |                      .m#%-..                ..-#...                               |
     # |                     +.-+m--.                .-.-                                  |
     # |                       -..                    - .                                  |
     # |                                                ..                                 |
     # |                                                                                   |
     # |                            ____                                                   |
     # |                           |  _ \ ___   ___                                        |
     # |                           | |_) / _ \ / _ \                                       |
     # |                           |  __/ (_) | (_) |                                      |
     # |                           |_|   \___/ \___/                                       |
     # |                                                                                   |
     # |                                                                                   |
     # |FIXME: This code is hacked-together rubbish. Implement something sensible          |
     # +-----------------------------------------------------------------------------------+

        if len(self.action_list) == 0 and self.IsPlayer():
            return None

        if not self.IsPlayer() and len(self.action_list) == 0:
            #For a computer player, decide what to do
            #regular players populate this list themselves
            self.InvalidatePathCache()

            #Find the nearest enemy
            
            enemies = []
            danger_score = 0.
            away_vector  = Point(0,0)
            for player in self.tiles.wizards:
                for enemy in player.controlled:
                    if enemy.player is self.player:
                        continue
                    #offset = utils.WrapDistance(enemy.pos,self.pos,self.tiles.width)
                    #distance = offset.length()
                    #path = self.tiles.PathTo(self.pos,enemy.pos)
                    #if path == None:
                    #    cost = (enemy.pos-self.pos).length()
                    #else:
                    #    cost = path.cost
                    cost = (enemy.pos - self.pos).length()
                    if cost < 6:
                        danger_score += (enemy.stats.attack + enemy.stats.health + enemy.stats.mana)/cost
                        away_vector -= (enemy.pos - self.pos)
                    enemies.append((cost,enemy))
            enemies.sort(lambda x,y : cmp(x[0],y[0]))
            if len(enemies) == 0:
                #wtf? There are no other wizards? the game should have ended
                return False
            cost,enemy = enemies[0]
            path = self.PathTo(enemy.pos)
            if path:
                cost = path.cost
            danger_score /= float(self.player.personality.confidence + self.stats.health + self.stats.mana)
            #print self.name,danger_score,away_vector,Point(0 if away_vector.x == 0 else 5.0/away_vector.x,0 if away_vector.y == 0 else 5.0/away_vector.y)
            target = self.pos + away_vector
            away_path = None
            if away_vector != Point(0,0):
                for adjust in utils.Spiral(15):
                    final_target = target + adjust
                    away_path = self.PathTo(final_target)
                    if away_path:
                        break

            if danger_score < 1 or self.player.personality.confidence > 5:
                #We're either not in danger or we're brash, so try wizard blasting the nearest enemy
                offset = enemy.pos-self.pos
                for index,action in utils.r_enumerate(self.blast_action_creator.actions):
                    if action.cost < self.stats.mana:
                        self.blast_action_creator.SetAction(index)
                        if self.blast_action_creator.Valid(offset):
                            self.action_list.extend( self.blast_action_creator.Create(offset,t,self) )
                            return self.action_list.pop(0)

            if danger_score > 1:
                #Stop saving, this is serious
                self.saving_for = None
                #we want to leave
                target = self.pos + away_vector
                if away_path:
                    if self.stats.move > 0:
                        #walk that way
                        if self.move_action_creator.Valid(away_path.steps[0]):
                            self.action_list.extend( self.move_action_creator.Create(away_path.steps[0],t,self) )
                    elif self.stats.mana > 0:
                        if danger_score > 2 and self.player.personality.confidence < 4:
                            #try a teleport to get away fast
                            if self.stats.mana > self.teleport_action_creator.actions[1].cost*2:
                                target_action = 1
                            elif self.stats.mana > self.teleport_action_creator.actions[0].cost:
                                target_action = 0
                            else:
                                #we can't do a teleport
                                target_action = None
                            if target_action != None:
                                self.teleport_action_creator.SetAction(target_action)
                                offset = final_target - self.pos
                                if not self.teleport_action_creator.Valid(offset):
                                    #shit, we can't teleport there for some reason, let's try others in the same direction
                                    candidates = utils.Brensenham(final_target,self.pos,self.tiles.width)
                                    for point in candidates:
                                        if self.teleport_action_creator.Valid(point - self.pos):
                                            final_target = point
                                            offset = final_target - self.pos
                                            break
                                    else:
                                        offset = None
                                if offset != None:
                                    #Woop can teleport
                                    self.action_list.extend( self.teleport_action_creator.Create(offset,t,self) )
            elif self.ReadyToAttack():
                #Not too dangerous, so attack!
                #Teleports are cool for getting in striking distance quickly If we've got enough mana left over to
                #strike, and we can get in there, lets give it a go
                offset = enemy.pos - self.pos

                if not self.saving_for and offset.length() < 10:
                    if self.stats.mana > self.teleport_action_creator.actions[1].cost*2:
                        target_action = 1
                    elif self.stats.mana > self.teleport_action_creator.actions[0].cost*2:
                        target_action = 0
                    else:
                        #we we don't want to do a teleport
                        target_action = None
                    if target_action != None:
                        self.teleport_action_creator.SetAction(target_action)
                        #We can't teleport right onto him, try a spiral
                        for adjust in utils.Spiral(16):
                            if self.teleport_action_creator.Valid(offset + adjust):
                                self.action_list.extend( self.teleport_action_creator.Create(offset + adjust,t,self) )
                                return self.action_list.pop(0)
                            break

                if len(self.action_list) == 0:
                    #Not teleporting, maybe we want to move
                    if self.stats.move > 0 and path:
                        if self.move_action_creator.Valid(path.steps[0]):
                            self.action_list.extend( self.move_action_creator.Create(path.steps[0],t,self) )
                            return self.action_list.pop(0)
            elif self.stats.move > 0:
                #move away to give us time to build up forces and look busy
                if away_path:
                    path = away_path
                else:
                    opposite_point = enemy.pos + Point(self.tiles.width/2,0)
                    if enemy.pos.y < self.tiles.height/2:
                        opposite_point.y = self.tiles.height-1
                    opposite_point.x %= self.tiles.width
                    path = self.PathTo(opposite_point)
                if path:
                    if self.move_action_creator.Valid(path.steps[0]):
                        self.action_list.extend( self.move_action_creator.Create(path.steps[0],t,self) )

        if len(self.action_list) == 0:
            if self.saving_for and self.saving_for.cost + self.player.personality.emergency_mana <= self.stats.mana:
                self.saving_for.creator.SetAction(self.saving_for.index)
                self.SummonMonster(self.saving_for.creator,t)
                self.saving_for = None

        if len(self.action_list) == 0:
            #We've dealt with the logic of getting away from or towards the enemy, but maybe we've 
            #got mana to burn and we should summon some monsters
            
            #Which monster? Ideally we want the number of monsters we have to match our preference ratio
            #so cast the one which is furthest out
            if len(self.player.controlled) < self.player.personality.necessary_monsters and danger_score > self.player.personality.confidence/4:
                #just cast the first one we can afford
                for monster in self.monsters.monsters:
                    if monster.cost + self.player.personality.emergency_mana <= self.stats.mana:
                        monster.creator.SetAction(monster.index)
                        self.SummonMonster(monster.creator,t)
                        break
                        
            elif len(self.player.controlled) < self.player.personality.desired_monsters:
                #We've already got a few (probably shitty) ones, so lets save up for a better one
                actual_counts = []
                for monster in self.monsters.monsters:
                    count = len([m for m in self.player.controlled if type(m) == monster.monster])
                    actual_counts.append(count)
                #print self.name,[(monster.monster.name,c) for (monster,c) in zip(self.monsters.monsters,actual_counts)]
                total = sum(actual_counts)
                actual_ratios = [0 if total == 0 else float(c)/total for c in actual_counts]
                required = sorted([(monster,monster.desirability - actual_ratio) for actual_ratio,monster in itertools.izip(actual_ratios,self.monsters.monsters)],lambda x,y:cmp(y[1],x[1]))
                
                #print self.name,[(monster.monster.name,needed) for (monster,needed) in required]
                monster,needed = required[0]
                if monster.cost + self.player.personality.emergency_mana <= self.stats.mana:
                    monster.creator.SetAction(monster.index)
                    self.SummonMonster(monster.creator,t)
                else:
                    self.saving_for = monster
                
            #Stand-in AI logic until the game rules are fixed. There are two types,
            # tentative wizards do:
            #  - Move away from the enemy if possible
            #  - Shoot any enemy in range
            #  - Otherwise try to summon a monster if you can, but stay above 6 mana
            #
            # gungho wizards do:
            #  - Shoot any enemy in range
            #  - Summon a Goblin if they can (but stay above 2 mana for shooting)
            #  - 
            # if self.player_type == players.PlayerTypes.TENTATIVE:
            #     if self.stats.move > 0:
            #         #Go away from the nearest enemy
            #         opposite_point = enemy.pos + Point(self.tiles.width/2,0)
            #         if enemy.pos.y < self.tiles.height/2:
            #             opposite_point.y = self.tiles.height-1
            #         opposite_point.x %= self.tiles.width
            #         path = self.tiles.PathTo(self.pos,opposite_point)
            #         if path:
            #             if self.move_action_creator.Valid(path.steps[0]):
            #                 self.action_list.extend( self.move_action_creator.Create(path.steps[0],t,self) )
            #     #We've had a chance, at moving, but maybe we decided not to?
            #     if len(self.action_list) == 0:
            #         offset = enemy.pos-self.pos
            #         if self.blast_action_creator.Valid(offset):
            #             self.action_list.extend( self.blast_action_creator.Create(offset,t,self) )
            #         elif self.stats.mana - self.summon_goblin_creator.cost >= 6:
            #             #Want to summon a goblin, find the first spot that works
            #             choices = sorted([p for p in self.summon_goblin_creator.valid_vectors],lambda x,y:cmp(x.length(),y.length()))
            #             for point in choices:
            #                 if self.summon_goblin_creator.Valid(point):
            #                     self.action_list.extend( self.summon_goblin_creator.Create(point,t,self) )
            #                     break
            #             else:
            #                 #coun't find a place to put it. pants
            #                 pass
            # elif self.player_type == players.PlayerTypes.GUNGHO:
            #     if self.stats.move > 0 and path:
            #         if self.move_action_creator.Valid(path.steps[0]):
            #             self.action_list.extend( self.move_action_creator.Create(path.steps[0],t,self) )
            #     #We've had a chance, at moving, but maybe we decided not to?
            #     if len(self.action_list) == 0:
            #         offset = enemy.pos-self.pos
            #         if self.blast_action_creator.Valid(offset):
            #             self.action_list.extend( self.blast_action_creator.Create(offset,t,self) )
            #         elif self.stats.mana - self.summon_goblin_creator.cost >= 2:
            #             #Want to summon a goblin, find the first spot that works
            #             choices = sorted([p for p in self.summon_goblin_creator.valid_vectors],lambda x,y:cmp(x.length(),y.length()))
            #             for point in choices:
            #                 if self.summon_goblin_creator.Valid(point):
            #                     self.action_list.extend( self.summon_goblin_creator.Create(point,t,self) )
            #                     break
            #             else:
            #                 #coun't find a place to put it. pants
            #                 pass
                
        if len(self.action_list) == 0:
            #we failed to think of anything to do, so this guy is done
            return False
        return self.action_list.pop(0)