Example #1
0
def create_unit(engine, name):
    unit_data = dict()

    entity = engine.entities.create()
    engine.ais.add(entity, AI())
    engine.inputs.add(entity, Input(is_player=False))
    engine.infos.add(entity, Information(name))
    space = find_empty_space(engine)
    if not space:
        raise Exception("No empty space to place unit")
    engine.positions.add(entity, Position(*space))

    # unit specific attributes
    if name == 'rat':
        render = Render(char='r')
        health = Health(2, 2)
    elif name == 'goblin':
        render = Render(char='g', color="brown")
        health = Health(5, 5)
    elif name == 'bat':
        render = Render(char='b')
        health = Health(3, 3)

    engine.renders.add(entity, render)
    engine.healths.add(entity, health)
Example #2
0
def main():
    d = {0: Position(1, 2)}
    with open('data.pickle', 'wb') as f:
        pickle.dump(d, f, pickle.HIGHEST_PROTOCOL)

    with open('data.pickle', 'rb') as f:
        data = pickle.load(f)
    print(data)
Example #3
0
 def convert_dungeon_to_ecs(self, map_id, map_type, dungeon):
     # add tiles and tile specific attribute components
     maptype = self.engine.tilemaptypes.shared[map_type]
     environment = ".#+/'"
     blocked = environment[1:3]
     doors = environment[2:4]
     for y, row in enumerate(dungeon):
         for x, char in enumerate(row):
             if char == ' ':
                 continue
             # shared components
             tile_id = self.engine.entities.create()
             # tile
             self.engine.tiles.add(tile_id, Tile())
             # visibility
             self.engine.visibilities.add(tile_id, Visibility())
             # position
             self.engine.positions.add(tile_id, Position(
                 x, y,
                 map_id=map_id,
                 movement_type=Position.MovementType.NONE,
                 blocks=char in blocked
             ))
             # info
             info = self.engine.infos.shared[env_char_to_name[char]]
             self.engine.infos.add(tile_id, info)
             # render
             if char in ".'":
                 colors = maptype.floors
             elif char == '#':
                 colors = maptype.walls
             elif char in doors:
                 colors = maptype.doors
             else:
                 colors = maptype.stairs
             render = Render(char, random.choice(colors))
             self.engine.renders.add(tile_id, render)
             # openable
             if char in doors:
                 # This is a unique case (possibly more in the future) in
                 # that this tile creates a map entity with Openable.
                 openable = Openable(opened=char=='/')
                 self.engine.openables.add(tile_id, openable)
Example #4
0
        if entity_id in self.components[component_type]:
            del self.components[entity_id]
            return True
        return False

    def find(self, entity_id: int, component_type: object) -> object:
        if component_type.manager not in self.components:
            raise ValueError(
                f"Cannot find {component_type} in component dictionary")
        return self.components[component_type.manager].get(entity_id)


if __name__ == "__main__":
    from source.ecs.components import components, Position
    c = ComponentsManager(components)
    c.add(1, Position(1, 1))
    print(c.find(1, Position))
    print(c)

    # print memory footprint
    # Total allocated size: 2.4 KiB
    import tracemalloc
    tracemalloc.start()
    c = ComponentsManager(components)
    snapshot = tracemalloc.take_snapshot()
    top_stats = snapshot.statistics('traceback')
    for stat in top_stats:
        print(stat)
    total = sum(stat.size for stat in top_stats)
    print("Total allocated size: %.1f KiB" % (total / 1024))
Example #5
0
 def initialize_cursor(self):
     # initialize a cursor
     self.cursor = self.engine.entities.create()
     self.engine.positions.add(self.cursor, Position())
Example #6
0
def main(screen, mapstring):
    # setup colors
    curses.init_pair(1, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
    curses.init_pair(3, curses.COLOR_GREEN, curses.COLOR_BLACK)
    curses.init_pair(4, curses.COLOR_BLUE, curses.COLOR_BLACK)

    dungeon = [[c for c in row] for row in mapstring.split('\n')]
    w, height = len(dungeon[0]), len(dungeon)
    cursor = Position(w // 2, height // 2)
    tiles = {(i, j): cell
             for j, row in enumerate(dungeon) for i, cell in enumerate(row)}
    a = None
    b = None
    changed = False
    path = None
    x_ruler = ''.join(str(i % 10) for i in range(w))

    while True:
        screen.erase()
        screen.addstr(0, 0, mapstring)
        # add width ruler
        for x in (0, w + 1):
            screen.addstr(0, x, x_ruler)
        # add height ruler
        for j in range(len(dungeon)):
            screen.addch(j, 0, str(j % 10))
        if a:
            screen.addstr(a.y, a.x, 'a')
            screen.addstr(height + 1, 0, f"a: {a.x:02}, {a.y:02}")
        if b:
            screen.addstr(b.y, b.x, 'b')
            screen.addstr(height + 2, 0, f"b: {b.x:02}, {b.y:02}")

        if a and b and changed:
            start = time.time()
            path = astar(tiles, a, b)
            screen.addstr(height + 6, 0, f"{time.time()-start}")
            changed = False
        if path:
            nheight = 0
            for x, y in path:
                screen.addch(y, x, 'o', curses.color_pair(3))
        screen.addstr(height, 0, f"c: {cursor.x:02}, {cursor.y:02}")
        screen.move(cursor.y, cursor.x)
        screen.refresh()
        char = screen.getch()
        keypress = keyboard[char]
        if keypress == 'q' or keypress == 'escape':
            break
        if keypress == 'up':
            cursor.y -= 1 if cursor.y > 1 else 0
        elif keypress == 'down':
            cursor.y += 1 if cursor.y < len(dungeon) - 2 else 0
        elif keypress == 'left':
            cursor.x -= 1 if cursor.x > 1 else 0
        elif keypress == 'right':
            cursor.x += 1 if cursor.x < len(dungeon[0]) - 2 else 0
        elif keypress == 'a':
            if not a or (a and a != cursor):
                a = Position(cursor.x, cursor.y)
                changed = True
            elif a and a == cursor:
                a = None
        elif keypress == 'b':
            if not b or (b and b != cursor):
                b = Position(cursor.x, cursor.y)
                changed = True
            elif b and b == cursor:
                b = None
        elif keypress == 'c':
            a = None
            b = None
            changed = False
            path = None
Example #7
0
def create_player():
    player = engine.entities.create()
    engine.player = player
    engine.inputs.add(player, Input())
    if not spaces:
        raise Exception("No empty spaces to place player")
    space = spaces.pop()

    engine.positions.add(
        player,
        Position(*space,
                 map_id=engine.world.id,
                 movement_type=Position.MovementType.GROUND))
    engine.renders.add(player, Render('@'))
    engine.healths.add(player, Health(10, 20))
    engine.manas.add(player, Mana(10, 20))
    engine.infos.add(player, Information("Hero"))
    engine.inputs.add(player, Input(needs_input=True))

    # create armor for player
    # head
    helmet = engine.entities.create()
    engine.items.add(helmet, Item('armor', ('head', )))
    engine.renders.add(helmet, Render('['))
    engine.infos.add(helmet,
                     Information('iron helmet', 'Helps protect your head.'))
    engine.armors.add(helmet, Armor(2))
    # body
    platemail = engine.entities.create()
    engine.items.add(platemail, Item('armor', ('body', )))
    engine.renders.add(platemail, Render('['))
    engine.infos.add(
        platemail,
        Information('platemail',
                    'Armor made from sheets of metal. Heavy but durable.'))
    engine.armors.add(platemail, Armor(5))
    # feet
    ironboots = engine.entities.create()
    engine.items.add(ironboots, Item('armor', ('feet', )))
    engine.renders.add(ironboots, Render('['))
    engine.infos.add(ironboots,
                     Information('iron boots', 'Reinforced footwear.'))
    engine.armors.add(ironboots, Armor(3))

    # create a weapon for player
    spear = engine.entities.create()
    engine.items.add(spear, Item('weapon', ('hand', 'missiles')))
    engine.renders.add(spear, random.choice(engine.renders.shared['spear']))
    engine.infos.add(spear, engine.infos.shared['spear'])
    engine.weapons.add(spear, Weapon(4, 3))

    # create some missiles for player
    stone = engine.entities.create()
    engine.items.add(stone, Item('weapon', ('hand', 'missiles')))
    engine.renders.add(stone, Render('*'))
    engine.infos.add(
        stone, Information('stone', 'A common item useful for throwing.'))
    engine.weapons.add(stone, Weapon(1))

    # add created items to an equipment component
    e = Equipment(head=helmet,
                  body=platemail,
                  hand=spear,
                  feet=ironboots,
                  missiles=stone)
    engine.equipments.add(player, e)

    # add an inventory
    i = Inventory()
    engine.inventories.add(player, Inventory())
Example #8
0
def test_position_add():
    p = Position(2, 3)
    q = Position(5, 1)

    assert p + q == Position(7, 4)
Example #9
0
    def missile(self, cursor):
        end = self.engine.positions.find(cursor)
        cursor_component = self.engine.cursors.find(cursor)
        start = self.engine.positions.find(cursor_component.entity)
        equipment = self.engine.equipments.find(cursor_component.entity)
        if equipment.missile_weapon and equipment.missiles:
            ...
        elif equipment.missiles:
            # save missiles item id
            missiles = equipment.missiles

            # remove stone from inventory
            unequipped = self.engine.router.route('equipment', 'unequip_item',
                                                  cursor_component.entity,
                                                  missiles)
            # processed correctly
            if unequipped:
                render = self.engine.renders.find(missiles)
                self.engine.logger.add(render.char)
                path = pathfind(self.engine, start, end, pathfinder=bresenhams)
                # add a position component to thrown item
                self.engine.positions.add(
                    missiles,
                    Position(*path[-1],
                             self.engine.world.id,
                             movement_type=Position.MovementType.NONE,
                             blocks=None))
                # check if there is a unit in the path of the throw item
                # if there is one then calculate damage.
                # Do this by:
                #     1. Getting all units in the missile path[1:]
                #        Note: this works since only one unit will be on a
                #              tile at any given time
                #     2 Check each position in the path against the unit
                #       positions.
                #     3. If a unit exists then calculate chance to hit.
                #     4. If hit then calculate damage applied.
                units = {(position.x, position.y): (uid, health)
                         for uid, (health, position) in join(
                             self.engine.healths, self.engine.positions)
                         if (position.x, position.y) in path[1:]}
                # skip altogether if no units found in the unit query
                log = []
                is_player = cursor_component.entity == self.engine.player
                weapon = self.engine.infos.find(missiles)
                if units:
                    for p in path[1:]:
                        uid, health = units.get(p, (None, None))
                        if not uid:
                            continue
                        attacker = self.engine.infos.find(
                            cursor_component.entity)
                        attack = self.engine.weapons.find(
                            missiles).damage_throw
                        defender = self.engine.infos.find(uid)
                        if is_player:
                            log.append(
                                f"You throw the {weapon.name} at {defender.name}"
                            )
                        else:
                            log.append(
                                f"The {attacker.name} throws a {weapon.name} at {defender.name}"
                            )
                        # calculate chance to hit
                        # NOTE: calculate with a skill based chance later
                        # currently 50% chance to hit
                        if True:
                            armor = self.engine.router.route(
                                'armor', 'get_total_armor_value', uid)
                            damage = max(0, attack - armor)
                            health.cur_hp -= damage

                            if damage < 1:
                                log.append(f", but the missile did no damage!")
                            else:
                                log.append(f". It hits for {damage} damage.")
                            if health.cur_hp < 1:
                                log.append(f" The {defender.name} dies!")
                                self.engine.destroyed.add(uid, Destroyed())
                        else:
                            if is_player:
                                log.append(f", but miss!")
                            else:
                                log.append(f", but misses.")
                else:
                    if is_player:
                        log.append(
                            f"You throw the {weapon.name} at nothing in particular."
                        )
                self.engine.logger.add(''.join(log))
                # add ranged hit effect to effect list
                effect = RangeHitEffect(cursor, render.char, '0', path)
                self.engine.effects.add(cursor_component.entity, effect)
        return True
Example #10
0
# define world
w = engine.entities.create()
engine.world = WorldGraph({w: DungeonNode(w)}, w)

# define map properties
t = TileMap(x, y)
engine.tilemaps.add(w, t)

# define map objects
for y, row in enumerate(m):
    for x, cell in enumerate(row):

        e = engine.entities.create()
        engine.positions.add(e, Position(
            x, y, 
            map_id=w,
            blocks=cell is '#'
        ))
        engine.visibilities.add(e, Visibility())

# define player
e = engine.entities.create()
engine.player = e

# define random unblocked position
walkable = [
    (p.x, p.y)
        for p in engine.positions.components.values()
            if not p.blocks
]
random.shuffle(walkable)