131 lines
4.1 KiB
Rust
131 lines
4.1 KiB
Rust
use crate::{
|
|
//consts::*,
|
|
board::Board,
|
|
history::Play,
|
|
piece::Piece, util::Hex,
|
|
};
|
|
|
|
pub type Pool = [u8; 7];
|
|
|
|
pub struct Game {
|
|
pub complete:bool,
|
|
pub turn:u16,
|
|
pub board:Board,
|
|
pub pool:[Pool; 2],
|
|
|
|
pub history:Vec<Play>,
|
|
}
|
|
impl Game {
|
|
pub fn new() -> Self
|
|
{
|
|
Self {
|
|
complete:false,
|
|
|
|
turn:0,
|
|
|
|
board:Board::new(),
|
|
pool:[Pool::default(); 2],
|
|
|
|
history:Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn init(&mut self)
|
|
{
|
|
self.board.init();
|
|
}
|
|
|
|
pub fn apply_history(&mut self, history:&Vec<Play>) -> Result<(),()>
|
|
{
|
|
self.init();
|
|
for play in history {
|
|
self.process(play)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn process(&mut self, play:&Play) -> Result<(),()>
|
|
{
|
|
let player = (self.turn & 1) as u8;
|
|
|
|
|
|
//
|
|
// TODO:
|
|
// - Check for piece promotion.
|
|
// - Validate plays against move sets and specific rules.
|
|
// - Determine game state (check, checkmate).
|
|
//
|
|
|
|
|
|
// Move piece on board.
|
|
if if play.source == 0 {
|
|
if let Some(pid) = self.board.tiles[play.from as usize].piece {
|
|
if let Some(mut piece) = self.board.pieces[pid as usize] {
|
|
let mut swap = false;
|
|
|
|
if let Some(tid) = self.board.tiles[play.to as usize].piece {
|
|
if let Some(target) = &mut self.board.pieces[tid as usize] {
|
|
|
|
// Check for piece swap.
|
|
if piece.player == target.player {
|
|
swap = true;
|
|
target.tile = play.from;
|
|
|
|
// Check for target promotion.
|
|
let hex = Hex::from_tile(play.to);
|
|
if !target.promoted && Hex::is_back(hex.x, hex.y, target.player) {
|
|
println!("promotion {} {} ({}, {})", target.class, play.to, hex.x, hex.y);
|
|
target.promoted = true;
|
|
}
|
|
}
|
|
|
|
// Add captured piece to pool.
|
|
else {
|
|
self.pool[piece.player as usize][target.class as usize] += 1;
|
|
}
|
|
}
|
|
|
|
// Destroy piece if captured.
|
|
if !swap { self.board.pieces[tid as usize] = None; }
|
|
}
|
|
|
|
// Set tile/piece associations.
|
|
if swap {
|
|
self.board.tiles[play.from as usize].piece = self.board.tiles[play.to as usize].piece;
|
|
} else {
|
|
self.board.tiles[play.from as usize].piece = None;
|
|
}
|
|
self.board.tiles[play.to as usize].piece = Some(pid);
|
|
piece.tile = play.to;
|
|
|
|
self.board.pieces[pid as usize] = Some(piece);
|
|
|
|
// Check for piece promotion.
|
|
let hex = Hex::from_tile(play.from);
|
|
if !piece.promoted && Hex::is_back(hex.x, hex.y, piece.player) {
|
|
println!("promotion {} {} ({}, {})", piece.class, play.to, hex.x, hex.y);
|
|
if let Some(piece) = &mut self.board.pieces[pid as usize] {
|
|
piece.promoted = true;
|
|
}
|
|
}
|
|
true
|
|
} else { false }
|
|
} else { false }
|
|
}
|
|
|
|
// Place piece from pool.
|
|
else {
|
|
if self.pool[player as usize][play.from as usize] > 0 && self.board.tiles[play.to as usize].piece.is_none() {
|
|
self.pool[player as usize][play.from as usize] -= 1;
|
|
let piece = Piece::new(play.from, player);
|
|
self.board.set_piece(piece, play.to);
|
|
true
|
|
} else { false }
|
|
} {
|
|
self.turn += 1;
|
|
self.history.push(*play);
|
|
Ok(())
|
|
} else { Err(()) }
|
|
}
|
|
}
|