예제 #1
0
def pick_final_rooms(level: Level) -> List[int]:
    rooms = []
    for i, room in enumerate(level.rooms):
        n = count_neighbours(level.matrix, i)

        if n > 1:
            continue

        x, y = index_to_pos(i, M_SIZE)
        w, h = room[0]

        if x < M_SIZE - 1 and w >= MAX_ROOM_SIZE:
            continue

        if y < M_SIZE - 1 and h >= MAX_ROOM_SIZE:
            continue

        left = pos_to_index(x - 1, y, M_SIZE)
        top = pos_to_index(x, y - 1, M_SIZE)
        left_size = level.rooms[left][0] if x > 0 else None
        top_size = level.rooms[top][0] if y > 0 else None

        if left_size and left_size[0] >= MAX_ROOM_SIZE:
            continue

        if top_size and top_size[1] >= MAX_ROOM_SIZE:
            continue

        if w > 5 and h > 5:
            rooms.append(i)

    return rooms
예제 #2
0
def draw_debug(state: State, *extras):
    pyxel.cls(0)
    for i in range(len(state.board)):
        x, y = index_to_pos(i, state.board.side)

        v = state.board[i]
        if is_wall(v):
            col = 0
        elif is_door(v):
            if is_locked(v):
                col = 8
            else:
                col = 13
        elif 40 <= v < 45:
            col = 1
        elif state.board.entrance == i:
            col = 12
        else:
            col = 7
        pyxel.rect(x * U + OFF, y * U + OFF, U, U, col)
        # if i in extras[0]:
        #     pyxel.pix(x * U + 1 + OFF, y * U + 1 + OFF, 9)

    for i in state.level.items:
        x, y = i.square
        pyxel.rect(x * U + OFF, y * U + 1 + OFF, U, U, 9)

    outline_room(state, state.level.start_room, 12)
    outline_room(state, state.level.final_rooms[0], 14)
    for fr in state.level.final_rooms[1:]:
        outline_room(state, fr, 3)
예제 #3
0
def matrix_neighbours(index: int) -> List[int]:
    col, row = index_to_pos(index, M_SIZE)

    return [
        r * M_SIZE + c for r, c in [
            (row, col + 1),
            (row + 1, col),
            (row, col - 1),
            (row - 1, col),
        ] if r < M_SIZE and c < M_SIZE and r >= 0 and c >= 0
    ]
예제 #4
0
def encode_wall(board: Board, index: int) -> int:
    val = 0b10000

    x, y = index_to_pos(index, board.side)
    neighs = [(x - 1, y), (x, y + 1), (x + 1, y), (x, y - 1)]

    for i, (x_, y_) in enumerate(neighs):
        if board.outside(x_, y_) or is_wall(board.get(x_, y_)):
            val = val | (1 << i)

    return int("{0:b}".format(val))
예제 #5
0
def outline_room(state, room_index, color):
    x, y = index_to_pos(room_index, M_SIZE)
    size = state.level.rooms[room_index][0]
    pyxel.rectb(
        x * U * MAX_ROOM_SIZE + OFF,
        y * U * MAX_ROOM_SIZE + OFF,
        size[0] * U,
        size[1] * U,
        color,
    )
    pass
예제 #6
0
 def ray_dirs(i):
     px, py = state.player.pos
     c, r = index_to_pos(i, state.board.side)
     return [
         (x - px, y - py)
         for x, y in [
             (c + 0.5, r),
             (c + 1, r + 0.5),
             (c + 0.5, r + 1),
             (c, r + 0.5),
         ]
         if x - px and y - py
     ]
예제 #7
0
def encode_door(board: Board, index: int) -> int:
    x, y = index_to_pos(index, board.side)
    top = x, y - 1

    top_val = board.get(*top)

    if board.outside(*top):
        return 22

    elif is_wall(top_val):
        bin_str = str(top_val)
        if bin_str[4] == "0" and bin_str[2] == "1":
            return 21
        elif bin_str[4] == "1" and bin_str[2] == "1":
            return 22
        elif bin_str[2] == "0":
            return 23

    return 20
예제 #8
0
def populate_enemies(level: Level, stock, empty):
    board = level.board
    enemies = []
    for i in range(len(board)):
        if not is_empty(board[i]):
            continue

        if any(index_in_room(level, r, i) for r in level.final_rooms):
            continue

        if any(board.to_index(*k.square) == i for k in level.items):
            continue

        if is_active_tile(board[i]):
            continue

        r = random.randint(0, 100)
        if r >= empty:
            enemy_cls = random.choice(stock)
            e = enemy_cls(index_to_pos(i, board.side))
            e.sprite.play()
            enemies.append(e)

    return enemies
예제 #9
0
def encode_floor(board: Board, index: int) -> int:
    x, y = index_to_pos(index, board.side)
    top = x, y - 1

    top_val = board.get(*top)

    if board.outside(*top):
        return 32

    elif is_wall(top_val):
        bin_str = str(top_val)
        if bin_str[4] == "0" and bin_str[2] == "1":
            return 31
        elif bin_str[4] == "1" and bin_str[2] == "1":
            return 32
        elif bin_str[4] == "1" and bin_str[2] == "0":
            return 33
        elif bin_str[4] == "0" and bin_str[2] == "0":
            return 34

    elif top_val == 20:  # front door
        return 35

    return 30
예제 #10
0
def update(state: State) -> State:
    x, y = state.player.pos

    deads_enemies = []
    for e in state.enemies:
        e.update(state)
        if e.pv < 1:
            deads_enemies.append(e)
    for d in deads_enemies:
        state.enemies.remove(d)

    if state.text_box is not None:
        state.text_box.update(state)
        return
    elif state.player_turn:
        player_action(state)
    else:
        game_turn(state)

    state.player.update(state)

    # if state.player.pv < 1:
    #     state.text_box = misc.TextBox("skull", "You are dead...")

    # Move camera if needed
    px, py = state.player.pos
    cx, cy = state.camera
    lthreshold = 6
    rthreshold = 9
    cx = px - lthreshold if px - cx < lthreshold else cx
    cx = px - rthreshold if px - cx > rthreshold else cx
    cy = py - lthreshold if py - cy < lthreshold else cy
    cy = py - rthreshold if py - cy > rthreshold else cy
    state.camera = cx, cy

    deads_particles = []
    for p in state.particles:
        p.update(state)
        if not p.living():
            deads_particles.append(p)
    for dp in deads_particles:
        state.particles.remove(dp)

    # store in-range block indices
    max_range = state.max_range
    state.in_range = set()
    for i in range(len(state.board)):
        x, y = index_to_pos(i, state.board.side)
        center = x + 0.5, y + 0.5
        if dist(center, state.player.pos) < max_range * 2:
            state.in_range.add(i)

    # for i in range(3):
    #     state.particles.append(Glitter(state.player.pos))

    def ray_dirs(i):
        px, py = state.player.pos
        c, r = index_to_pos(i, state.board.side)
        return [
            (x - px, y - py)
            for x, y in [
                (c + 0.5, r),
                (c + 1, r + 0.5),
                (c + 0.5, r + 1),
                (c, r + 0.5),
            ]
            if x - px and y - py
        ]

    def hit_wall(x, y):
        return (
            state.board.outside(x, y)
            or is_wall(state.board.get(x, y))
            or dist(state.player.pos, (x, y)) > state.max_range
            or is_door(state.board.get(x, y))
        )

    rays: List[VecF] = sum([ray_dirs(i) for i in state.in_range], [])
    state.visible = set()
    for r in rays:
        trav, hit, _ = cast_ray((px + 0.5, py + 0.5), r, hit_wall)
        state.visible.update(trav)
        if not state.board.outside(*hit):
            state.visible.add(hit)
    state.visited |= state.visible

    return state