fix frontend board mapping, game-over handling, and WASM-4
- fix Xform yx and add a shared view-aware board_position helper - add GTK automatic game-over, restart, status, and multi-capture selection - pin librsvg to the 2.60 series to match GTK4/glib 0.20 - add WASM orientation, undo/redo/new/flip controls, and winner overlay - replace WASM crown images with canvas paths and remove dead files/deps - make WASM-4 playable with mouse input, crowns, winner handling, and correct mapping - move the WASM-4 release profile to the workspace root - clean up frontend dead code and update the README
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
use rdraught::{DraughtsBoard, Error, Player, Position, RectangularBoard};
|
||||
|
||||
/// Maps a screen square to a board square for the given point of view.
|
||||
///
|
||||
/// Both views place pieces on screen squares where
|
||||
/// `(screen_row + screen_col) % 2 == 1`.
|
||||
pub fn board_position(view: Player, screen_row: u8, screen_col: u8) -> Result<Position, Error> {
|
||||
let rows = DraughtsBoard::rows() as u8;
|
||||
let columns = DraughtsBoard::columns() as u8;
|
||||
if screen_row >= rows || screen_col >= columns {
|
||||
return Err(Error::InvalidPosition);
|
||||
}
|
||||
match view {
|
||||
Player::White => Position::new(rows - 1 - screen_row, screen_col),
|
||||
Player::Red => Position::new(screen_row, columns - 1 - screen_col),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::board_position;
|
||||
use rdraught::{Player, Position};
|
||||
|
||||
#[test]
|
||||
fn white_view_mapping() {
|
||||
assert_eq!(
|
||||
Position::new(7, 1).unwrap(),
|
||||
board_position(Player::White, 0, 1).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Position::new(0, 0).unwrap(),
|
||||
board_position(Player::White, 7, 0).unwrap()
|
||||
);
|
||||
assert!(board_position(Player::White, 0, 0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn red_view_mapping() {
|
||||
assert_eq!(
|
||||
Position::new(0, 6).unwrap(),
|
||||
board_position(Player::Red, 0, 1).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Position::new(7, 7).unwrap(),
|
||||
board_position(Player::Red, 7, 0).unwrap()
|
||||
);
|
||||
assert!(board_position(Player::Red, 0, 0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn both_views_have_32_squares() {
|
||||
for view in [Player::White, Player::Red] {
|
||||
let mut count = 0;
|
||||
for row in 0..8 {
|
||||
for col in 0..8 {
|
||||
if board_position(view, row, col).is_ok() {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(32, count);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn out_of_bounds_is_rejected() {
|
||||
assert!(board_position(Player::White, 8, 0).is_err());
|
||||
assert!(board_position(Player::Red, 0, 8).is_err());
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ impl Xform {
|
||||
}
|
||||
|
||||
pub fn yx(&self) -> f64 {
|
||||
self.0[(1, 0)]
|
||||
self.0[(0, 1)]
|
||||
}
|
||||
|
||||
pub fn yy(&self) -> f64 {
|
||||
@@ -259,3 +259,41 @@ impl Display for Xform {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Point, Xform};
|
||||
use core::f64::consts::PI;
|
||||
|
||||
fn close(actual: f64, expected: f64) {
|
||||
assert!((actual - expected).abs() < 1e-9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rotation_uses_all_matrix_components() {
|
||||
let rotation = Xform::rot(PI / 2.0);
|
||||
close(rotation.yx(), 1.0);
|
||||
close(rotation.xy(), -1.0);
|
||||
|
||||
let point = Point::new(1.0, 0.0) * &rotation;
|
||||
close(point.x(), 0.0);
|
||||
close(point.y(), 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn translation_and_scaling() {
|
||||
let transform = Xform::scale(2.0, 3.0) * Xform::xlate(3.0, 4.0);
|
||||
let point = Point::new(1.0, 2.0) * &transform;
|
||||
close(point.x(), 5.0);
|
||||
close(point.y(), 10.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inversion_round_trips() {
|
||||
let transform = Xform::xlate(3.0, 4.0) * Xform::rot(0.3) * Xform::scale(2.0, 0.5);
|
||||
let point = Point::new(1.0, 2.0);
|
||||
let result = (point * &transform) * &transform.invert();
|
||||
close(result.x(), point.x());
|
||||
close(result.y(), point.y());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mod board;
|
||||
mod geo2d;
|
||||
mod types;
|
||||
|
||||
pub use board::board_position;
|
||||
pub use geo2d::{Point, Rect, Xform};
|
||||
pub use types::{SharedMutable, SharedMutableRef, new_shared_mut, new_shared_mut_ref};
|
||||
|
||||
Reference in New Issue
Block a user