#!/usr/bin/env python

'''Simulation for killing strategies in Real Time Strategy games.'''

import random
import copy

class Shooter(object):
    '''A simple shooting object with hitpoints and firepower'''

    def __init__(self, hp, firepower):
        self.hp = hp
        self.firepower = firepower
    
    def fireAt(self, other):
        other.hp -= self.firepower

    def __eq__(self, other):
        return (self.hp == other.hp and self.firepower ==
                other.firepower)

def findLeastHP(enemies):
    '''Returns the enemy with the least hitpoints'''
    return min(enemies, key=lambda x: x.hp)

def findMostHP(enemies):
    '''Returns the enemy with the most hitpoints'''
    return max(enemies, key=lambda x: x.hp)

def findLeastFP(enemies):
    '''Returns the enemy with the least firepower'''
    return min(enemies, key=lambda x: x.firepower)

def findMostFP(enemies):
    '''Returns the enemy with the most firepower'''
    return max(enemies, key=lambda x: x.firepower)

def findLeastFPperHP(enemies):
    '''Returns the enemy with the least firepower per hitpoint'''
    return min(enemies, key=lambda x: float(x.firepower) / x.hp)

def findMostFPperHP(enemies):
    '''Returns the enemy with the most firepower per hitpoint'''
    return max(enemies, key=lambda x: float(x.firepower) / x.hp)

def findRandom(enemies):
    return random.choice(enemies)

# Create a list of strategies
strategies = [findLeastHP, findMostHP, findLeastFP, findMostFP,
        findLeastFPperHP, findMostFPperHP, findRandom]

def createEnemies():
    enemies = []
    for num in range(30):
        hp = random.randint(100, 2000)
        firepower = random.randint(10, 1000)
        enemy = Shooter(hp, firepower)
        enemies.append(enemy)

    return enemies

enemyList = createEnemies()

def runSimulation(findEnemy):
    enemies = copy.deepcopy(enemyList)
    me = Shooter(0, 50)

    rounds = 0
    while enemies:
        # First, all enemies shoot at me
        for enemy in enemies:
            enemy.fireAt(me)

        # Now I fire at some enemy
        enemy = findEnemy(enemies)
        me.fireAt(enemy)

        # Remove all dead enemies
        enemies = [enemy for enemy in enemies if enemy.hp > 0]
        rounds += 1

    print "Strategy: %s" % findEnemy.func_name
    print "\tAll enemies dead after %i rounds" % rounds
    print "\tTotal damage received: %i" % -me.hp

    return -me.hp

print 70 * '-'

results = []
for strategy in strategies:
    score = runSimulation(strategy)
    
    results.append((strategy, score))

print 70 * '-'
results = sorted(results, cmp=lambda x, y: cmp(x[1], y[1]))
for strategy, score in results:
    print "%20s: %i" % (strategy.func_name, score)

# vim:foldnestmax=1

