// Tablero de Buscaminas. Es un tipo opaco: quien lo usa solo tiene punteros y solo llama a estas
// funciones. Las filas y las columnas se cuentan desde 0.
#ifndef BOARD_H
#define BOARD_H

typedef struct board Board;

typedef enum {
    GAME_PLAYING,
    GAME_WON,
    GAME_LOST
} GameState;

// Crea un tablero sin minas, con todas sus celdas tapadas. Devuelve NULL si rows o cols son menores
// que 1, si rows * cols no cabe en un int o si no hay memoria.
// Owner: quien llama, que debe liberarlo con board_free.
Board *board_new(int rows, int cols);

// Libera el tablero. Acepta NULL.
void board_free(Board *board);

// Crea un tablero fijo desde n cadenas de igual largo: '*' es una mina y '.' es una celda sin mina.
// Devuelve NULL si los datos están mal o si no hay memoria. Owner: quien llama.
Board *board_from_rows(const char *rows[], int n);

// Crea un tablero con mines minas en lugares elegidos a partir de seed: con la misma semilla salen
// siempre los mismos lugares. Devuelve NULL si mines no cabe o si no hay memoria. Owner: quien llama.
Board *board_random(int rows, int cols, int mines, unsigned int seed);

// Abre la celda. Una celda sin minas vecinas abre también a sus ocho vecinas, y así sucesivamente.
// No hace nada si la celda está fuera, abierta o con bandera, o si el juego ya terminó.
void board_reveal(Board *board, int row, int col);

// Pone o quita la bandera de una celda tapada. En otro caso no hace nada.
void board_toggle_flag(Board *board, int row, int col);

// Dice cómo va el juego: GAME_LOST si se abrió una mina, GAME_WON si se abrieron todas las celdas sin
// mina, y GAME_PLAYING en otro caso.
GameState board_state(const Board *board);

int board_rows(const Board *board);
int board_cols(const Board *board);
int board_mines(const Board *board);

// Devuelve cuántas celdas sin mina están abiertas.
int board_opened(const Board *board);

// Devuelve cuántas minas tiene alrededor la celda, sin contarse a sí misma.
// Exige: (row, col) dentro del tablero.
int board_mines_around(const Board *board, int row, int col);

// Devuelve el carácter que el jugador ve en la celda: '#' tapada, 'F' con bandera, '.' abierta sin
// minas vecinas, de '1' a '8' abierta con minas vecinas, '*' mina abierta. Si ya se perdió, muestra
// '*' en todas las minas. Exige: (row, col) dentro del tablero.
char board_cell_char(const Board *board, int row, int col);

// Escribe el tablero en la terminal, con los números de fila y de columna.
void board_print(const Board *board);

#endif
