def attack_them(us, minions, minions_attacked, parser): """Attack the list of minions provided. The minions are guaranteed to be attacked. Returns: A list of friendly minions that have not yet attacked. """ logger.info("Focus firing on minions: {}".format(minions)) us_remain = us[:] them = minions[:] them.sort(cmp=botalgs.highest_attack_cmp) for enemy in them: logger.info("Focus firing on {}".format(enemy)) # If we can kill this minion, do it attackers = botalgs.can_kill_minion(us_remain, enemy) if attackers: # Since we are attacking with these, remove them from future calculations for m in attackers: us_remain.remove(m) # Perform the attack attack_minion(m, enemy) minions_attacked.append(m) parser.process_log() # Remove the enemy from our temporary calculation them.remove(enemy) # If we haven't attacked all enemies, and we still have minions able, attack them anyway if them and us_remain: # Pick the weakest one them.sort(cmp=lambda x, y: int(x.remaining_health()) < int( y.remaining_health())) for enemy in them: for m in us_remain: # If we've killed this enemy, stop attacking it if enemy.remaining_health() <= 0: break us_remain.remove(m) attack_minion(m, enemy) minions_attacked.append(m) parser.process_log() assert (not [enemy for enemy in them if enemy.remaining_health() > 0]) or \ (not us_remain), \ "Enemies remain that have not been killed despite us having minions available to attack" return us_remain
def attack_them(us, minions, minions_attacked, parser): """Attack the list of minions provided. The minions are guaranteed to be attacked. Returns: A list of friendly minions that have not yet attacked. """ logger.info("Focus firing on minions: {}".format(minions)) us_remain = us[:] them = minions[:] them.sort(cmp=botalgs.highest_attack_cmp) for enemy in them: logger.info("Focus firing on {}".format(enemy)) # If we can kill this minion, do it attackers = botalgs.can_kill_minion(us_remain, enemy) if attackers: # Since we are attacking with these, remove them from future calculations for m in attackers: us_remain.remove(m) # Perform the attack attack_minion(m, enemy) minions_attacked.append(m) parser.process_log() # Remove the enemy from our temporary calculation them.remove(enemy) # If we haven't attacked all enemies, and we still have minions able, attack them anyway if them and us_remain: # Pick the weakest one them.sort(cmp=lambda x,y: int(x.remaining_health()) < int(y.remaining_health())) for enemy in them: for m in us_remain: # If we've killed this enemy, stop attacking it if enemy.remaining_health() <= 0: break us_remain.remove(m) attack_minion(m, enemy) minions_attacked.append(m) parser.process_log() assert (not [enemy for enemy in them if enemy.remaining_health() > 0]) or \ (not us_remain), \ "Enemies remain that have not been killed despite us having minions available to attack" return us_remain
def attack_phase(parser): logger.debug("Attack phase") # Make shallow copies so we can get updated locations of minions when others die us = gstate.tingle.minions[:] them = gstate.opponent.minions[:] minions_attacked = [] # Can't attack if we have none if not us: return # These are the potential attackers (they must be active to attack) us_remain = [m for m in us if m.active] # They must have attack value to attack us_remain = [m for m in us_remain if int(m.attack) > 0] logger.debug("Minions available to attack:\n{}".\ format(pformat(us_remain))) # Attack any minions with taunt first taunters = [m for m in them if 'Taunt' in m.mechanics] us_remain = attack_them(us_remain, taunters, minions_attacked, parser) logger.debug("Minions remaining after taking out taunters:\n{}".\ format(pformat(us_remain))) # If we don't have any remaining, continue with attack if not us_remain: return # Recalculate minions after attacking taunters them = gstate.opponent.minions[:] logger.debug("Enemy minions remaining to take out:\n{}".\ format(pformat(them))) # Order them by highest attacks them.sort(cmp=botalgs.highest_attack_cmp) for enemy in them: # If we can kill this minion, do it attackers = botalgs.can_kill_minion(us_remain, enemy) if attackers: # Since we are attacking with these, remove them from future calculations for m in attackers: # If the minion got killed, stop trying if enemy.remaining_health() <= 0: break us_remain.remove(m) # Perform the attack attack_minion(m, enemy) minions_attacked.append(m) parser.process_log() # If we have any minions left over, attack the hero for m in us_remain: attack_hero(m) minions_attacked.append(m) parser.process_log() # Here lies a bug: we may think we are attacking with a minion, but we click # on the wrong one time.sleep(1) parser.process_log() active_minions = [m for m in gstate.tingle.minions[:] if m.active and int(m.attack) > 0] assert not active_minions , \ "Attack phase complete, but some minions did not attack: {}\nThought I attacked with {}".format(active_minions, minions_attacked)
def attack_phase(parser): logger.debug("Attack phase") # Make shallow copies so we can get updated locations of minions when others die us = gstate.tingle.minions[:] them = gstate.opponent.minions[:] minions_attacked = [] # Can't attack if we have none if not us: return # These are the potential attackers (they must be active to attack) us_remain = [m for m in us if m.active] # They must have attack value to attack us_remain = [m for m in us_remain if int(m.attack) > 0] logger.debug("Minions available to attack:\n{}".\ format(pformat(us_remain))) # Attack any minions with taunt first taunters = [m for m in them if 'Taunt' in m.mechanics] us_remain = attack_them(us_remain, taunters, minions_attacked, parser) logger.debug("Minions remaining after taking out taunters:\n{}".\ format(pformat(us_remain))) # If we don't have any remaining, continue with attack if not us_remain: return # Recalculate minions after attacking taunters them = gstate.opponent.minions[:] logger.debug("Enemy minions remaining to take out:\n{}".\ format(pformat(them))) # Order them by highest attacks them.sort(cmp=botalgs.highest_attack_cmp) for enemy in them: # If we can kill this minion, do it attackers = botalgs.can_kill_minion(us_remain, enemy) if attackers: # Since we are attacking with these, remove them from future calculations for m in attackers: # If the minion got killed, stop trying if enemy.remaining_health() <= 0: break us_remain.remove(m) # Perform the attack attack_minion(m, enemy) minions_attacked.append(m) parser.process_log() # If we have any minions left over, attack the hero for m in us_remain: attack_hero(m) minions_attacked.append(m) parser.process_log() # Here lies a bug: we may think we are attacking with a minion, but we click # on the wrong one time.sleep(1) parser.process_log() active_minions = [ m for m in gstate.tingle.minions[:] if m.active and int(m.attack) > 0 ] assert not active_minions , \ "Attack phase complete, but some minions did not attack: {}\nThought I attacked with {}".format(active_minions, minions_attacked)