//! 盤面表現と状態管理
//!
//! このモジュールは将棋の盤面を表現し、指し手の適用・取り消し、
//! 合法手生成などの機能を提供します。
//!
//! # 主要な型
//!
//! - [`Position`] - 盤面状態を管理する中心的な構造体
//! - [`MoveList`] - 指し手のリスト
//! - [`StateInfo`] - 局面の状態情報（ハッシュ、王手駒など）
//!
//! # 初期化
//!
//! このモジュールを使用する前に [`init()`] を呼び出して、
//! 利きテーブルなどの事前計算を行う必要があります。
//!
//! ```
//! use rshogi::board;
//!
//! // プログラム起動時に1回呼び出す
//! board::init();
//! ```
//!
//! # 局面の構築
//!
//! ```
//! use rshogi::board::{self, Position};
//!
//! board::init();
//!
//! // 平手初期局面
//! let pos = board::hirate_position();
//!
//! // SFEN から構築
//! let pos = board::position_from_sfen(
//!     "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"
//! ).unwrap();
//! ```
//!
//! # 指し手の適用と取り消し
//!
//! ```
//! use rshogi::board::{self, Position};
//! use rshogi::types::Move;
//!
//! board::init();
//! let mut pos = board::hirate_position();
//!
//! // 指し手を適用
//! let mv16 = Move::from_usi("7g7f").unwrap();
//! let m = pos.move32_from_move(mv16);
//! pos.apply_move32(m);
//!
//! // 指し手を取り消し
//! pos.undo_move32(m);
//! ```
//!
//! # 合法手生成
//!
//! 合法手生成は [`movegen`] サブモジュールで提供されます。
//!
//! ```
//! use rshogi::board::{self, MoveList};
//! use rshogi::movegen::{Legal, generate_moves};
//!
//! board::init();
//! let pos = board::hirate_position();
//!
//! let mut moves = MoveList::new();
//! generate_moves::<Legal>(&pos, &mut moves);
//!
//! println!("合法手数: {}", moves.len());
//! ```
//!
//! `Move32`（駒情報付き 32bit 指し手）のリストを直接生成するには
//! [`generate_legal_all_move32`] を使用します。
//!
//! ```
//! use rshogi::board::{self, Move32List};
//! use rshogi::movegen::generate_legal_all_move32;
//!
//! board::init();
//! let pos = board::hirate_position();
//!
//! let mut moves = Move32List::new();
//! generate_legal_all_move32(&pos, &mut moves);
//!
//! println!("合法手数: {}", moves.len());
//! ```
//!
//! # サブモジュール
//!
//! - [`movegen`] - 合法手生成
//! - [`attack_tables`] - 利きテーブル
//! - [`perft`] - Perft テスト
//! - [`zobrist`] - Zobrist ハッシュ

pub mod attack_tables;
pub mod bitboard256;
pub mod bitboard_set;

pub mod move_list;
pub mod movegen;
pub mod perft;
pub mod initial_positions;
mod parser;
pub use parser::{
    generate_position_state, generate_sfen, generate_sfen_from_position_state,
    generate_sfen_with_ply, parse_sfen, PositionState, SfenError,
};
mod lookup;
pub mod zobrist;
pub mod position;
pub mod state_info;
pub mod mate_constant;
#[cfg(test)]
pub(crate) mod test_support;

pub use crate::mate;
pub use crate::types::Bitboard;
pub use attack_tables::{
    check_candidate_bb, GOLD_ATTACKS, KING_ATTACKS, KNIGHT_ATTACKS, PAWN_ATTACKS, SILVER_ATTACKS,
};
pub use bitboard256::Bitboard256;
pub use bitboard_set::BitboardSet;
pub use initial_positions::InitialPosition;
pub use mate::solve_mate_in_one;
pub use move_list::{Move32List, MoveList};
pub use movegen::{
    generate_legal_all_move32, generate_moves, generate_moves_move32, generate_quiet_checks,
    generate_recaptures, generate_recaptures_all, CapturePlusPro, CapturePlusProAll, Captures,
    CapturesAll, Checks, ChecksAll, Evasions, EvasionsAll, Legal, LegalAll, MoveGenType,
    NonEvasions, NonEvasionsAll, QuietChecks, QuietChecksAll, Quiets, QuietsAll, QuietsProMinus,
    QuietsProMinusAll, Recaptures, RecapturesAll,
};
pub use position::{
    BoardArray, DeclarationDetail, DeclarationEvaluation, HuffmanCodedPos, HuffmanCodedPosError,
    PackedPiece, PackedSfen, PackedSfenError, Ply, Position, ValidationIssue, ValidationReport,
};
pub use state_info::{StateIndex, StateInfo, StateStack};
#[cfg(test)]
mod tests;

/// 盤面関連の事前計算を行う
pub fn init() {
    Bitboard::init_tables();
}

/// SFEN文字列から局面を構築する（ヘルパー）。
pub fn position_from_sfen(sfen: &str) -> Result<Position, parser::SfenError> {
    let mut pos = Position::empty();
    pos.set_sfen(sfen)?;
    Ok(pos)
}

/// [`PositionState`] から局面を構築する（ヘルパー）。
///
/// エディタ等で構築した `PositionState` から `Position` を生成する。
/// SFEN 文字列を経由しない raw-state import に使用できる。
///
/// この関数は盤面キャッシュやハッシュを再構築するが、
/// 局面のルール妥当性までは検証しない unchecked import である。
/// checked workflow が必要な場合は import 後に
/// [`Position::validate()`] または [`Position::validate_all()`] を呼ぶ。
///
/// # Examples
///
/// ```
/// use rshogi::board::{self, BoardArray, PositionState};
/// use rshogi::types::{Color, Hand, Piece};
///
/// board::init();
///
/// let mut board_array = BoardArray::empty();
/// board_array.set(rshogi::types::SQ_59, Piece::B_KING);
/// board_array.set(rshogi::types::SQ_51, Piece::W_KING);
///
/// let state = PositionState {
///     board: board_array,
///     hands: [Hand::ZERO; Color::COUNT],
///     side_to_move: Color::BLACK,
///     ply: 1,
/// };
///
/// let pos = board::position_from_position_state(&state);
/// assert_eq!(board::generate_position_state(&pos), state);
/// assert!(pos.validate().is_ok());
/// ```
#[must_use]
pub fn position_from_position_state(state: &PositionState) -> Position {
    let mut pos = Position::empty();
    pos.set_position_state(state);
    pos
}

/// 平手初期局面を構築する（ヘルパー）。
#[must_use]
pub fn hirate_position() -> Position {
    let mut pos = Position::empty();
    pos.set_hirate();
    pos
}
