예제 #1
0
    def __init__(self,parent):
        self.class_lookup = Lookup()
        self.lookup = { }
        self.positions = { }
        self.parents = { }
        self.schedules = { }
        self.parent = parent
        self.scheduler = parent.scheduler

        self.cur_id = 0
        self.garbage_id = self.add_entity("ethereal")
        self.set_pos(self.garbage_id,(0, 0))
예제 #2
0
class EntityManager(object):
    """Manager class for Entities.

    Contains class_lookup for string <-> class associations/instance type checking.
    lookup contains the ID <-> object referencing.
    positions contains the position of the entity, or None.
    parents contains the ID of the containing entity, or None.
    schedules contains the IDs of the scheduling tasks assigned to each entity.
    cur_id is the current free ID to be assigned.
    Entity ID #0 is 'garbage collection' of entities. Parent to this to remove next tick.
    """

    def __init__(self,parent):
        self.class_lookup = Lookup()
        self.lookup = { }
        self.positions = { }
        self.parents = { }
        self.schedules = { }
        self.parent = parent
        self.scheduler = parent.scheduler

        self.cur_id = 0
        self.garbage_id = self.add_entity("ethereal")
        self.set_pos(self.garbage_id,(0, 0))

    def __len__(self):
        return len(self.lookup)

    def __getitem__(self, item):
        if isinstance(item, int):
            return self.lookup[item]
        elif isinstance(item, tuple) and len(item) == 2:
            return self.get_at(*item)
        else:
            return NotImplemented

    def __iter__(self):
        return self.lookup.iterkeys()

    def __contains__(self, item):
        return item in self.lookup

    def is_instance(self, id, lookup):
        return isinstance(self[id], self.class_lookup.get_class(lookup))

    def post_message(self, msg):
        """Convenience method for entities to call to post messages to the message window."""
        self.parent.add_messages((msg,))

    def add_entity(self, type, delay=10):
        """Adds a new entity of type to entity_list, and returns its ID."""
        self.adjust_cur_id()
        id = self.cur_id
        cls = self.class_lookup.get_class(type)
        self.lookup[id] = cls(self,id)
        self.lookup[id].init()
        self.lookup[id].type = type
        self.lookup[id].delay = delay
        if delay is not None:
            self.schedule(self.scheduler, id)
        return id

    def load_entity(self, id, type, pos, parent, atts, name, char, delay, fgcol):
        cls = self.class_lookup.get_class(type)
        self.lookup[id] = cls(self,id)
        self.lookup[id].init()
        self.lookup[id].type = type
        self.lookup[id].delay = delay
        self.lookup[id].fgcol = fgcol
        self.lookup[id].set_attributes(atts)
        self.lookup[id].char = char
        self.lookup[id].name = name
        if pos is not None:
            self.set_pos(id,pos)
        else:
            self.set_parent(id,parent)
        if delay is not None:
            self.schedule(self.scheduler, id)

    def get_at(self,x,y):
        """Returns list of ids of entities at a position or an empty tuple."""
        if (x,y) in self.positions.itervalues():
            ret = [ ]
            for id in self.positions:
                if self.positions[id] == (x,y):
                    ret.append(id)
            return ret
        return ()

    def get_in(self,ent):
        """Returns list of ids of entities contained directly by ent or an empty tuple."""
        if ent in self.parents.itervalues():
            ret = [ ]
            for id in self.parents:
                if self.parents[id] == ent:
                    ret.append(id)
            return ret
        return ()

    def get_pos(self,id):
        """Returns (x,y) of entity if not contained, or None."""
        if id not in self:
            raise IDNotFound
        return self.positions[id]

    def get_abs_pos(self,id):
        """Returns (x,y) of entity; Recurses up container entities to return real position."""
        if id not in self:
            raise IDNotFound
        cur_id = id
        pos = None
        while not pos and cur_id is not None:
            pos = self.positions[cur_id]
            cur_id = self.parents[cur_id]
        return pos

    def get_parent(self,id):
        """Returns ID of directly containing entity or None."""
        if id not in self:
            raise IDNotFound
        return self.parents[id]

    def get_ancestor(self,id):
        """Returns ID of top containing entity or None."""
        if id not in self:
            raise IDNotFound
        if self.parents[id] is None:
            return id
        return self.get_ancestor(self.parents[id])

    def set_attribute(self, id, att, val):
        """Sets the entity's attribute to the given value."""
        if id not in self:
            raise IDNotFound
        self[id].set_attribute(att, val)

    def get_attribute(self, id, att):
        """Returns the entity's attribute or None."""
        if id not in self:
            raise IDNotFound
        return self[id].get_attribute(att)

    def get_name(self, id):
        """Returns the entity's name."""
        if id not in self:
            raise IDNotFound
        return self[id].get_name()

    def set_sched(self, ent, sched):
        """Cancels the current schedule for an entity and sets a new id as its main."""
        if ent in self.schedules:
            if self.schedules[ent] is not None:
                sched.cancel_schedule(self.schedules[ent])
        self.schedules[ent] = sched

    def get_sched(self, ent):
        """Returns the scheduler id for entity or None."""
        if ent in self.schedules:
            return self.schedules[ent]
        return None

    def schedule(self, sched, id):
        """Schedules the entity in the scheduler according to its current delay."""
        if id in self.schedules:
            if self.schedules[id] is not None:
                sched.cancel_schedule(self.schedules[id])
        if id not in self:
            raise IDNotFound
        delay = self[id].delay
        if delay is not None:
            self.schedules[id] = sched.add_schedule((self[id].update, (), delay))


    def ent_lift(self, ent1, ent2):
        """Lifter ent1 attempts to lift liftee ent2."""
        ent = self[ent1]
        victim = self[ent2]
        ent.lift(ent2)
        success = victim.was_lifted(ent1)
        ent.finished_lifting(ent2,success)
        return success

    def ent_equip(self, ent1, ent2):
        """Equipper ent1 attempts to equip equipment to ent2."""
        ent = self[ent1]
        victim = self[ent2]
        ent.equip(ent2)
        success = victim.was_equipped(ent1)
        ent.finished_equipping(ent2, success)
        return success

    def ent_collide(self, ent1, ent2):
        """Collider ent1 attempts to move onto tile of ent2."""
        ent = self[ent1]
        victim = self[ent2]
        ent.collide(ent2)
        success = victim.was_collided(ent1)
        ent.finished_colliding(ent2, success)
        return success

    def ent_activate(self, id):
        return self[id].activated()

    def ent_drop(self, ent_id):
        ent = self[ent_id]
        ancestor = self.get_ancestor(ent_id)
        self[ancestor].drop(ent_id)
        success = ent.was_dropped(ancestor)
        self[ancestor].finished_dropping(ent_id, success)

    def ent_use(self, ent1, ent2):
        """Used ent1 attempts to use target ent2."""
        ent = self[ent1]
        victim = self[ent2]
        if ent != victim:
            ok = self.ent_equip(ent1, ent2)
            if not ok:
                self.ent_lift(ent1, ent2)
        else:
            self.ent_activate(ent1)

    def move_ent(self,id,x,y):
        """Tries to move an entity in a relative direction, with collision checking and interaction."""
        pos = self.get_pos(id) or (0,0)
        pos = (pos[0] + x, pos[1] + y)
        can_move = True
        #check for interactions to raise
        for victim_id in self[(pos[0],pos[1])]:
            if id is not victim_id:
                can_move = self.ent_collide(id, victim_id)
        #check for collisions
        if self.parent.collision_check(id,x,y) and can_move:
            self.set_pos(id,pos)

    def move_ent_to_ent(self,id,id2):
        """Passes call to try to move an entity to another into relative coords."""
        x, y = self.get_pos(id2) or (0,0)
        ex, ey = self.get_pos(id) or (0,0)
        self.move_ent(id, x-ex, y-ey)

    def set_pos(self, id, pos):
        """Sets the entity's position to the given tuple, unsetting parent."""
        #if id not in self:
        #    raise IDNotFound
        self.positions[id] = pos
        self.parents[id] = None

    def set_parent(self, id, parent_id):
        """Sets the entity's containing entity to the given ID, unsetting its position."""
        #if id not in self and parent_id not in self:
        #    raise IDNotFound
        self.positions[id] = None
        self.parents[id] = parent_id

    def adjust_cur_id(self):
        self.cur_id = 0
        while self.cur_id in self.lookup:
            self.cur_id += 1

    def save(self):
        """Returns a list of strings representing save-format data."""
        ret = ["{"]
        ret += ['"player" : '+str(self.parent.player)+',']
        ret += ['"camera" : '+str(self.parent.camera)+',']
        for id in self.positions:
            obj = self.lookup[id]
            pos = self.get_pos(id)
            parent = self.get_parent(id)
            print pos, parent
            ret += ['"'+str(id)+'" : {']
            ret += ['"type" : "'+obj.type+'",']
            if pos is not None:
                ret += ['"pos" : ['+str(pos[0])+','+str(pos[1])+'],']
            else:
                ret += ['"pos" : null,']
            if parent is not None:
                ret += ['"parent" : '+str(parent)+',']
            else:
                ret += ['"parent" : null,']
            ret += ['"atts" : "'+obj.get_attributes()+'",']
            ret += ['"name" : "'+obj.name+'",']
            ret += ['"char" : "'+obj.char+'",']
            if obj.delay:
                ret += ['"delay" : '+str(obj.delay)+',']
            else:
                ret += ['"delay" : null,']
            ret += ['"fgcol" : '+str(list(obj.fgcol))]
            ret += ["},"]
        ret[-1] = ret[-1][:-1]
        ret += ["}"]
        return ret