示例#1
0
 def find_valid_spaces(self) -> list:
     tiles = {(position.x, position.y)
              for _, position, visible in join_drop_key(
                  self.engine.tiles, self.engine.positions,
                  self.engine.visibilities)
              if visible.level < 2 and not position.blocks}
     units = {(position.x, position.y)
              for _, position in join_drop_key(self.engine.inputs,
                                               self.engine.positions)}
     return tiles - units
示例#2
0
def go_up(engine, entity):
    """Check if entity position is on stairs. If true go up"""
    went_up = False
    position = engine.positions.find(entity)
    tilemap = engine.tilemaps.find(position.map_id)
    g = join_drop_key(engine.tiles, engine.positions, engine.renders)
    for _, tile_position, render in g:
        if (tile_position.map_id == engine.world.id
                and tile_position == position and render.char == '<'):
            break
        else:
            tile_position = None

    if not tile_position:
        engine.logger.add('Could not go up since not on stairs')
        return went_up

    old_id = engine.world.id
    up = engine.world.go_up()
    if old_id != engine.world.id:
        engine.map_system.regenerate_map(old_id)
    else:
        engine.logger.add('no parent node.')

    for _, (_, tile_position, render) in join(engine.tiles, engine.positions,
                                              engine.renders):
        if (tile_position.map_id == engine.world.id and render.char == '>'):
            break

    position = tile_position.copy(movement_type=position.movement_type,
                                  blocks=position.blocks)
    engine.positions.remove(engine.player)
    engine.positions.add(engine.player, position)
    return True
示例#3
0
def check_tile_info(engine, position):
    describeables = list()
    for p, i in join_drop_key(engine.positions, engine.infos):
        if (position.x == p.x and position.y == p.y and i.name is not 'floor'):
            describeables.append(i.name)
    if describeables:
        engine.logger.add(', '.join(describeables))
示例#4
0
def move(engine, entity, movement) -> bool:
    # if entity has no position component return early
    position = engine.positions.find(entity)
    if not position or not movement:
        return False

    # save temp positions for collision checking
    x, y = position.x + movement.x, position.y + movement.y

    # check map out-of-bounds collisions
    tilemap = engine.tilemaps.find(eid=position.map_id)
    if not (0 <= x < tilemap.width and 0 <= y < tilemap.height):
        return collide(engine, entity, -1)

    # check unit collisions for specific movment types
    if position.movement_type == Position.MovementType.GROUND:
        # check unit collisions
        for entity_id, entity_position in engine.positions:
            if (entity_position.x == x and entity_position.y == y
                    and entity_position.map_id == engine.world.id
                    and entity_id != entity
                    and entity_position.blocks is True):
                # if door is an unlocked door, open door and move positions
                entity_openable = engine.openables.find(entity_id)
                if entity_openable:
                    # replace info
                    engine.infos.add(entity_id,
                                     engine.infos.shared['opened door'])
                    engine.renders.add(
                        entity_id,
                        random.choice(engine.renders.shared['opened door']))
                    entity_openable = True
                    entity_position.blocks = False
                    position.x += movement.x
                    position.y += movement.y
                    engine.logger.add(
                        "You open the door and enter the doorway")
                    return True
                return collide(engine, entity, entity_id)

    if position.movement_type == Position.MovementType.VISIBLE:
        g = join_drop_key(engine.positions, engine.visibilities)
        for entity_position, visible in g:
            if (entity_position.x == x and entity_position.y == y
                    and entity_position.map_id == engine.world.id
                    and visible.level < 2):
                return False

    # no collisions. move to the new position
    position.x += movement.x
    position.y += movement.y

    # check
    if entity == engine.player:
        check_for_floor_items(engine, position)
    elif entity == engine.cursor:
        check_tile_info(engine, position)
        return False
    return True
示例#5
0
 def find_unlit_spaces(self) -> set:
     return {
         (position.x, position.y)
         for (_, position,
              visible) in join_drop_key(self.engine.tiles, self.engine.
                                        positions, self.engine.visibilities)
         if visible.level > 1 and not position.blocks
     }
示例#6
0
def pathfind(engine, start, end, pathfinder=astar):
    """Wrapper for ecs engine to use astar"""
    tiles = {
        (position.x, position.y)
            for _, position in join_drop_key(engine.tiles, engine.positions)
                if not position.blocks
    }
    path = pathfinder(tiles, start, end)
    return path
def test_manager():
    m = ComponentManager(Render)
    n = ComponentManager(Position)
    
    render = Render()
    position = Position()

    m.add(0, render)
    n.add(0, position)

    for r, p in join_drop_key(m, n):
        assert r == render
        assert p == position
示例#8
0
    def on_move(self, event):
        """
            if out-of-bounds, environment or unit blocked:
                returns Collision result
            else:
                moves entity
        """
        self.logger.add(f"Move {self.engine.turns}")
        # if entity has no position component return early
        position = self.engine.positions.find(entity)
        if not position or not movement:
            return False

        # save temp positions for collision checking
        x, y = position.x + movement.x, position.y + movement.y

        # check map out-of-bounds collisions
        tilemap = self.engine.tilemaps.find(eid=position.map_id)
        if not (0 <= x < tilemap.width and 0 <= y < tilemap.height):
            return self.collide(entity, Collision(-1))

        # check unit collisions for specific movment types
        if position.movement_type == Position.MovementType.GROUND:
            # check unit collisions
            for entity_id, entity_position in self.engine.positions:
                if (entity_position.x == x and entity_position.y == y
                        and entity_position.map_id == self.engine.world.id
                        and entity_id != entity
                        and entity_position.blocks is True):
                    return self.collide(entity, Collision(entity_id))

        if position.movement_type == Position.MovementType.VISIBLE:
            g = join_drop_key(self.engine.positions, self.engine.visibilities)
            for entity_position, visible in g:
                if (entity_position.x == x and entity_position.y == y
                        and entity_position.map_id == self.engine.world.id
                        and visible.level < 2):
                    return False

        # no collisions. move to the new position
        position.x += movement.x
        position.y += movement.y

        # check
        if entity == self.engine.player:
            self.check_for_floor_items(position)
        elif entity == self.engine.cursor:
            self.check_tile_info(position)
            return False
        return True
示例#9
0
def go_down(engine, entity):
    """Check if entity position is on stairs. If true go down"""
    went_down = False
    position = engine.positions.find(entity)
    tilemap = engine.tilemaps.find(eid=position.map_id)

    # should only return 1 tile/render pair
    g = join_drop_key(engine.tiles, engine.positions, engine.renders)
    for _, tile_position, render in g:
        # tile from current map / same map position as entity / is down stairs
        if (tile_position.map_id == engine.world.id
                and tile_position == position and render.char == '>'):
            break
        else:
            tile_position = None

    if not tile_position:
        engine.logger.add('Could not go down since not on stairs')
        return went_down

    old_id = engine.world.id
    engine.world.go_down()
    if old_id == engine.world.id:
        # TODO: generate child map to go down. For now return False
        # engine.logger.add('Could not go down since no child map')
        # return went_down
        engine.map_system.generate_map(MapType.CAVE)
        engine.world.go_down()
    else:
        engine.map_system.regenerate_map(old_id)

    for _, (_, tile_position, render) in join(engine.tiles, engine.positions,
                                              engine.renders):
        # tile from current map / is up stairs
        if (tile_position.map_id == engine.world.id and render.char == '<'):
            break

    if not tile_position:
        engine.logger.add('Could not go down since child map has no up stairs')
        return went_down

    # send entity to the position of stairs on child map
    position = tile_position.copy(movement_type=position.movement_type,
                                  blocks=position.blocks)
    engine.positions.remove(engine.player)
    engine.positions.add(engine.player, position)
    return True
示例#10
0
def cast_light2(engine, x0, x1, y0, y1, raycaster=raycast2):
    """Wrapper for raycast so that engine is not a parameter to raycast"""
    player = engine.positions.find(engine.player)
    tilemap = engine.tilemaps.find(engine.world.id)

    if not tilemap:
        no_tilemap_error(engine.world.id, engine.tilemaps.components.keys())
        exit(0)

    tiles = dict()
    blocked = set()

    for v, p in join_drop_key(engine.visibilities, engine.positions):
        if (p.map_id == engine.world.id and x0 <= p.x < x1 and y0 <= p.y < y1):
            v.level = max(0, min(v.level, 1))
            tiles[(p.x, p.y)] = v
            if p.blocks:
                blocked.add((p.x, p.y))
    raycaster(tiles, blocked, tilemap.width, tilemap.height, player)
示例#11
0
 def find_empty_spaces(self) -> list:
     return {(position.x, position.y)
             for _, position in join_drop_key(self.engine.tiles,
                                              self.engine.positions)
             if not position.blocks}
示例#12
0
def get_tiles(engine, x0, x1, y0, y1) -> list:
    tiles = []
    for v, p in join_drop_key(engine.visibilities, engine.positions):
        if (p.map_id == engine.world.id and x0 <= p.x < x1 and y0 <= p.y < y1):
            tiles.append((v, p))
    return tiles
示例#13
0
        t = time.time()
        caster(
            engine, 
            off_x, 
            57 + off_x, 
            off_y, 
            17 + off_y, 
            raycaster=raycaster
        )
        s = time.time()

        # save the timing result
        recorder.append(s - t)

    # edit the map buffer with seen positions and player position
    for p, v in join_drop_key(engine.positions, engine.visibilities):
        m[p.y][p.x] = ' ' if v.level == 0 else n[p.y][p.x]
    p = engine.positions.find(engine.player)
    m[p.y][p.x] = '@'

    # render
    print(string(m))

    try:
        c = input().strip()
    except KeyboardInterrupt:
        break

    p = engine.positions.find(engine.player)
    if c == 'w' and n[p.y-1][p.x] == '.':
        m[p.y][p.x] = '.'
示例#14
0
    def render(self):
        player = self.engine.positions.find(self.engine.player)
        tilemap = self.engine.tilemaps.find(player.map_id)
        # calculate camera bounds on scrolling map
        if tilemap.width < self.width:
            self.cam_x = 0
        else:
            self.cam_x = scroll(player.x, self.width, tilemap.width)
        x0, x1 = self.cam_x, self.width + self.cam_x
        if tilemap.height < self.height:
            self.cam_y = 0
        else:
            self.cam_y = scroll(player.y, self.height, tilemap.height)
        y0, y1 = self.cam_y, self.height + self.cam_y

        # do line of sight calculations
        cast_light(self.engine, x0, x1, y0, y1)

        start = time.time()
        # draw map first, then items, then units
        for visibility, position, render in join_drop_key(
                self.engine.visibilities, self.engine.positions,
                self.engine.renders):
            if (visibility.level > 0 and player.map_id == position.map_id
                    and x0 <= position.x < x1 and y0 <= position.y < y1):
                c = render.color if visibility.level > 1 else "darkest grey"
                self.add_string(position.x - self.cam_x,
                                position.y - self.cam_y, render.char, c)

        self.engine.entities_in_view.clear()
        for eid, (health, position, render,
                  info) in join(self.engine.healths, self.engine.positions,
                                self.engine.renders, self.engine.infos):
            if (position.map_id == self.engine.world.id
                    and (position.x, position.y) in self.engine.tiles_in_view
                    and x0 <= position.x < x1 and y0 <= position.y < y1):
                if self.engine.player != eid:
                    self.engine.entities_in_view.add(eid)
                self.add_string(position.x - self.cam_x,
                                position.y - self.cam_y, render.char,
                                render.color)

        # # draw items
        # self.render_items(visible_tiles, player.map_id, cam_x, cam_y, x0, x1, y0, y1)
        # while True:
        #     # draw units
        #     self.render_units(visible_tiles, player.map_id, cam_x, cam_y, x0, x1, y0, y1)
        #     if not self.engine.effects.components:
        #         break
        #     if time.time() - start > (1 / 23):
        #         self.engine.effects.components.clear()
        #         break
        #     # draw effects
        #     self.render_effects(tiles, player.map_id, cam_x, cam_y, x0, x1, y0, y1)
        #     self.update_effects()

        if self.engine.mode is not GameMode.NORMAL:
            # self.render_cursor(visible_tiles, player.map_id, cam_x, cam_y, x0, x1, y0, y1)
            position = self.engine.positions.find(self.engine.cursor)
            if self.engine.mode in (GameMode.LOOKING, GameMode.DEBUG):
                self.add_string(position.x - self.cam_x,
                                position.y - self.cam_y, 'X')
            elif self.engine.mode == GameMode.MAGIC:
                cursor = self.engine.cursors.find(self.engine.cursor)
                spellname = Spell.identify[cursor.using]
                render = self.engine.renders.shared[spellname][0]
                if spellname == 'fireball':
                    for xx, yy in diamond():
                        x = position.x + xx
                        y = position.y + yy
                        if (x, y) not in self.engine.tiles_in_view:
                            continue
                        self.add_string(x - cam_x, y - cam_y, render.char,
                                        render.color)