harden engine rules, position invariants, and undo history
- make Position represent only valid board squares and use checked offsets - make move endpoints fallible and remove unchecked coordinate arithmetic - validate moves against generated legal moves, including mandatory capture - track pending multi-captures and restrict continuation to the same piece - derive pending state after undo/redo and preserve redo on invalid moves - fix circular buffer wraparound, mixed iteration, and element drops - adapt GTK and WASM to fallible endpoints and apply errors - add rule, promotion, chain, history, and coordinate regression tests
This commit is contained in:
@@ -252,7 +252,7 @@ impl App {
|
||||
let available_moves: Vec<Position> = self
|
||||
.available_moves
|
||||
.iter()
|
||||
.map(Move::get_end_position)
|
||||
.filter_map(Move::get_end_position)
|
||||
.collect();
|
||||
for i in 0..DraughtsBoard::rows() {
|
||||
for j in 0..DraughtsBoard::columns() {
|
||||
@@ -274,7 +274,8 @@ impl App {
|
||||
ctx.fill_rect(cell.tl().x(), cell.tl().y(), cell.width(), cell.height());
|
||||
if (i + j) % 2 != 0 {
|
||||
let current_player = Player::White;
|
||||
let position = Position::from_index((map_row(current_player, j), i));
|
||||
let position = Position::new(map_row(current_player, j) as u8, i as u8)
|
||||
.expect("board loop only visits valid squares");
|
||||
let piece = self.game.piece_at(position);
|
||||
if piece.is_present() {
|
||||
piece_drawer.draw_piece(ctx, &self.xform, cell.clone(), piece)?;
|
||||
@@ -412,13 +413,14 @@ fn main() -> Result<(), JsValue> {
|
||||
let selected_move = app
|
||||
.available_moves
|
||||
.iter()
|
||||
.find(|mv| mv.get_end_position() == position)
|
||||
.find(|mv| mv.get_end_position() == Some(position))
|
||||
.map(Move::clone);
|
||||
if app.selected_piece.is_some() && selected_move.is_some() {
|
||||
let mv = selected_move.unwrap();
|
||||
app.game.check_and_apply_move(&mv).unwrap();
|
||||
app.selected_piece = None;
|
||||
app.available_moves.clear();
|
||||
if app.game.check_and_apply_move(&mv).is_ok() {
|
||||
app.selected_piece = None;
|
||||
app.available_moves.clear();
|
||||
}
|
||||
} else {
|
||||
app.selected_piece = Some(position);
|
||||
let mut available_moves = Vec::<Move>::new();
|
||||
|
||||
Reference in New Issue
Block a user