"""an attempt to study what happens when being (requires energy)."""

import random

env_energy = 10
turn = 0

STARVELIMIT = 0.2

def get_energy(requester, request=1.0): #can modules have properties?
    global env_energy
    if not request > env_energy:
        env_energy -= request
        return request
    else:
        rest = env_energy
        env_energy = 0
        return rest
    

class Being: #to be able to have many
    def __init__(self, name="being x"):
        self.name = name
        self.energy = 1.0
        self.health = 1.0

    def request_energy(self, other):
        if self.health < 0:
            print self.name, "is dead, being requested for energy .. is there some in the body, that could not use self - should that go to the requester", other.name, "now?"
            return 0
        if self.energy > STARVELIMIT: #not starving
            marginal = 0 #0.1
            extra = self.energy - (STARVELIMIT + marginal)
            if extra > 0:
                self.energy -= extra
                print self.name, "is giving", extra, "to", other.name
                return extra
            else:
                return 0
        else:
            print self.name, "is starving and not giving anything to", other.name
            return 0
    
    def be(self):
        """ does something motivate having energy consumption here?

        perhaps this is what the body uses .. so this is an embodied being?
        atm. not positioned tho, and without inputs / outputs.

        kinda makes sense that the world appears as a global variable,
        wrapped in a getter tho
        """
        if self.health == 1.0: #no worries or problems,
            self.energy -= 0.01 #can act fully
        else:
            self.energy -= self.health / 100 #can not live fully

        if self.energy < STARVELIMIT: #getting weak
            self.health -= STARVELIMIT - self.energy
            self.energy += get_energy(STARVELIMIT) #needs some to recover

        elif self.energy < 0.35: #healthy hunger
            self.energy += get_energy(0.7)

        elif self.energy > 0.5:
            if self.health < 1:
                self.health += 0.05

        if self.energy < 0 or self.health < 0:
            #asks from others as a last resort
            others = set(beings) - set([self])
            for o in others:
                self.energy += o.request_energy(self)
                if self.energy > 0:
                    self.health += self.energy #err
                    self.energy = 0
                    if self.health > 0:
                        return True #was saved, for a moment at least

            print self.name, "died on turn %d." % turn
            self.die()

    def die(self):
        #def no():
        #    return False
        #self.be = no #lambda _: False
        self.be = None


beings = [Being(str(i)) for i in range(200)]
hope = True
            
while hope:
    hope = False #please bare with how procedural programming is
    #-this is not a declaration, just a way to make a dependency
    #between the following code, that goes thru the beings, and
    # ..
    turn += 1
    env_energy += random.random() / 60 #what if this was a sine wave, or something?
    for b in beings:
        if b.be: #is a function/method (instance callable), and not None (dead)
            b.be()
            print "[%d] %s %f, %f, env: %f" % (turn, b.name, b.energy, b.health, env_energy)#, beings
            hope = True
        else:
            print b.name, "is no more."
        #if b.health < 0:

print "stopped at turn", turn

