/*
 * level.h — структуры уровня PoP под наш движок.
 *
 * Формат — POP-DAT-FormatSpecifications.pdf §3.4 (DAT 1.0): комната =
 * 30 тайлов (10 колонок x 3 ряда), foretable даёт тип тайла,
 * backtable — модификатор/состояние (семантика зависит от типа).
 * Адресация тайла: tile = (room-1)*30 + tileOffset, tileOffset 0-9 =
 * верхний ряд, 10-19 = средний, 20-29 = нижний, слева направо.
 *
 * Фаза 1 (applications/PoP/docs/PORT_PLAN.md §5, сузили объём):
 * только геометрия (пол/стены/провалы) для коллизий — двери, факелы,
 * ловушки, гарды НЕ используются (структуры под них здесь тоже
 * упрощены/оставлены как заготовка на потом, см. §7 плана Фаза 2).
 */
#ifndef LEVEL_H
#define LEVEL_H

#include <stdint.h>

/* 1 (не 24) — PoC грузит и рисует только комнату 1; расширить, когда
 * появится настоящий level_load() на несколько комнат. */
#define LEVEL_ROOMS   1          /* комнаты нумеруются 1..24 в файле,
                                  * здесь индекс 0..23 = комната N+1 */
#define ROOM_COLS     10
#define ROOM_ROWS     3
#define ROOM_TILES    (ROOM_COLS * ROOM_ROWS)   /* 30 */

/* --- Типы тайлов (Table 7 спецификации) --- */
#define TILE_TYPE(byte)      ((uint8_t)((byte) & 0x1F))
#define TILE_MODIFIER(byte)  ((uint8_t)(((byte) >> 5) & 1))

enum {
    TILE_EMPTY          = 0x00,
    TILE_FLOOR          = 0x01,
    TILE_SPIKES         = 0x02,
    TILE_PILLAR         = 0x03,
    TILE_GATE           = 0x04,
    TILE_STUCK_BUTTON   = 0x05,
    TILE_DROP_BUTTON    = 0x06,
    TILE_TAPESTRY       = 0x07,
    TILE_PILLAR_BOTTOM  = 0x08,
    TILE_PILLAR_TOP     = 0x09,
    TILE_POTION         = 0x0A,
    TILE_LOOSE          = 0x0B,
    TILE_TAPESTRY_TOP   = 0x0C,
    TILE_MIRROR         = 0x0D,
    TILE_DEBRIS         = 0x0E,
    TILE_RAISE_BUTTON   = 0x0F,
    TILE_EXIT_LEFT      = 0x10,
    TILE_EXIT_RIGHT     = 0x11,
    TILE_CHOPPER        = 0x12,
    TILE_TORCH          = 0x13,
    TILE_WALL           = 0x14,
    TILE_SKELETON       = 0x15,
    TILE_SWORD          = 0x16,
    TILE_BALCONY_LEFT   = 0x17,
    TILE_BALCONY_RIGHT  = 0x18,
    TILE_LATTICE_PILLAR = 0x19,
    TILE_LATTICE_SUPPORT= 0x1A,
    TILE_LATTICE_SMALL  = 0x1B,
    TILE_LATTICE_LEFT   = 0x1C,
    TILE_LATTICE_RIGHT  = 0x1D,
    TILE_TORCH_DEBRIS   = 0x1E,
    TILE_NULL           = 0x1F
};

/* Твёрдые тайлы — Фаза 1 (только геометрия); классификация наша, для
 * коллизий движка, не часть исходного формата.  Двери/шипы/дробилки и
 * т.п. сознательно исключены из объёма Фазы 1 (см. §5 плана) — при
 * встрече в реальных данных трактовать как проходимые до Фазы 2.
 *
 * tile_is_solid() — "есть опора сверху" (вертикальный смысл: можно
 * стоять НА этом тайле) — Floor ТОЖЕ solid в этом смысле!  Для
 * горизонтальной коллизии (можно ли ВОЙТИ в эту клетку сбоку) нужен
 * ОТДЕЛЬНЫЙ предикат — см. tile_blocks_side ниже.  Баг 2026-07-16:
 * col_blocked() в poc.c ошибочно звал tile_is_solid() для бокового
 * упора — Floor блокировал сам себя, Кид не мог сдвинуться с места
 * стоя на полу. */
static inline uint8_t tile_is_solid(uint8_t byte)
{
    switch (TILE_TYPE(byte)) {
        case TILE_FLOOR:
        case TILE_PILLAR:
        case TILE_PILLAR_BOTTOM:
        case TILE_PILLAR_TOP:
        case TILE_WALL:
        case TILE_BALCONY_LEFT:
        case TILE_BALCONY_RIGHT:
            return 1;
        default:
            return 0;
    }
}

/* tile_blocks_side() — настоящая преграда СБОКУ (нельзя войти в
 * клетку по горизонтали): Wall/Pillar-семейство.  Floor/Balcony НЕ
 * блокируют — по ним идёшь (тайл под ногами, не впереди).  Lattice-
 * колонны (0x19-0x1D) — узкие, Кид физически проходит мимо (см.
 * gen_tile_placeholders.py draw_lattice_like) — тоже НЕ блокируют. */
static inline uint8_t tile_blocks_side(uint8_t byte)
{
    switch (TILE_TYPE(byte)) {
        case TILE_PILLAR:
        case TILE_PILLAR_BOTTOM:
        case TILE_PILLAR_TOP:
        case TILE_WALL:
            return 1;
        default:
            return 0;
    }
}

/* --- Тайл и комната --- */
typedef struct {
    uint8_t type;     /* foretable byte (rrmccccc — см. TILE_TYPE/MODIFIER) */
    uint8_t state;    /* backtable byte — модификатор/состояние */
} tile_t;

typedef struct {
    tile_t  tiles[ROOM_TILES];         /* индекс = tileOffset 0..29 */
    uint8_t link_left, link_right;     /* links-блок: 0 = нет соседа */
    uint8_t link_up, link_down;
    uint8_t guard_location;            /* 0..29; 30 (и выше) = нет гарда */
    int8_t  guard_direction;           /* 0 = вправо, -1 = влево */
    uint8_t guard_skill;               /* 0..9 */
    uint8_t guard_colour;              /* индекс палитры, Table 11 */
    /* door I/II (событийные цепочки) — Фаза 2, не здесь */
} room_t;

typedef struct {
    room_t  rooms[LEVEL_ROOMS];        /* индекс 0 = комната 1 (файл 1-based) */
    uint8_t start_room;                /* 1..24 */
    uint8_t start_location;            /* 0..29 */
    int8_t  start_direction;           /* 0 = вправо, -1 = влево */
} level_t;

/* Тайл по (room 1-based, col 0-9, row 0-2). */
static inline tile_t *level_tile(level_t *lv, uint8_t room, uint8_t col, uint8_t row)
{
    return &lv->rooms[room - 1].tiles[row * ROOM_COLS + col];
}

/* Загружает ОДНУ комнату + стартовую позицию уровня из файла в формате
 * tools/extract_room.py (63 Б: foretable[30]+backtable[30] той комнаты
 * + start_room+start_pos+start_dir, вырезанные из res20NN.bin — layout
 * подтверждён декодом байт 2026-07-15/16: файл начинается СРАЗУ с
 * foretable[720], потом backtable[720], без заголовка; start_position
 * — смещение 2112, сверено со структурой level_type в SDLPoP/src/
 * types.h).  Заполняет lv->start_room/start_location/start_direction.
 * 0 — OK, -1 — файл не найден/короче 63 Б. */
int level_load_room(level_t *lv, uint8_t room, const char *path);

#endif
