Compare commits

..

1 Commits

Author SHA1 Message Date
60b65e3eec simplified memory layout 2025-07-02 09:10:52 +08:00
5 changed files with 35 additions and 140 deletions

View File

@@ -1,6 +1,5 @@
use glib::ExitCode; use glib::ExitCode;
use rdraught::draughts::DraughtsGame; use rdraught::draughts::DraughtsGame;
use rdraught_ui;
fn main() -> ExitCode { fn main() -> ExitCode {
let game = DraughtsGame::default(); let game = DraughtsGame::default();

View File

@@ -6,7 +6,7 @@ use gtk4::glib::{MainContext, Propagation};
use gtk4::{self as gtk, gdk::ffi::GDK_BUTTON_PRIMARY}; use gtk4::{self as gtk, gdk::ffi::GDK_BUTTON_PRIMARY};
use gtk4::{Application, DrawingArea, prelude::*}; use gtk4::{Application, DrawingArea, prelude::*};
use rdraught::{ use rdraught::{
DraughtsBoard, DraughtsGame, Error, Move, Piece, Player, Position, RDraughtApplication, DraughtsBoard, DraughtsGame, Move, Piece, Player, Position, RDraughtApplication,
RectangularBoard, RectangularBoard,
}; };
use rsvg::SvgHandle; use rsvg::SvgHandle;
@@ -473,17 +473,17 @@ fn create_game_window(
let mut rd_app = rd.borrow_mut(); let mut rd_app = rd.borrow_mut();
println!("Applied move: {:?}", mv); println!("Applied move: {:?}", mv);
rd_app.apply_move(mv).unwrap(); rd_app.apply_move(mv).unwrap();
let game_copy = rd_app.game().clone(); // let game_copy = rd_app.game().clone();
thread::spawn(move || { // thread::spawn(move || {
if let (Some(mv), analyzed_moves) = // if let (Some(mv), analyzed_moves) =
game_copy.get_best_move(10) // game_copy.get_best_move(10)
{ // {
println!( // println!(
"Next best move: {:?}, analyzed moves: {}", // "Next best move: {:?}, analyzed moves: {}",
mv, analyzed_moves // mv, analyzed_moves
); // );
} // }
}); // });
move_applied = true; move_applied = true;
break; break;
} }

View File

@@ -12,7 +12,7 @@ pub trait RectangularBoard {
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct DraughtsBoard { pub struct DraughtsBoard {
data: [u8; (POSITIONS * BITS_PER_POSITION + 7) / 8], data: [u8; (POSITIONS * BITS_PER_POSITION).div_ceil(8)],
} }
impl DraughtsBoard { impl DraughtsBoard {
@@ -38,23 +38,23 @@ impl DraughtsBoard {
let index = offset_bits / 8; let index = offset_bits / 8;
let remainder = offset_bits % 8; let remainder = offset_bits % 8;
let mut value = 0; let mut value = 0;
value = value | ((self.data[index] >> remainder) & 7); value |= (self.data[index] >> remainder) & 7;
if remainder > 5 { if remainder > 5 {
let written_bits = 8 - remainder; let written_bits = 8 - remainder;
value = value | ((self.data[index + 1] & (7 >> written_bits)) << written_bits) value |= (self.data[index + 1] & (7 >> written_bits)) << written_bits
} }
Piece::from_repr(value as usize).unwrap() Piece::from_repr(value as usize).unwrap()
} }
pub fn new<T: FnMut(Position) -> Piece>(mut cb: T) -> DraughtsBoard { pub fn new<T: FnMut(Position) -> Piece>(mut cb: T) -> DraughtsBoard {
let mut result = DraughtsBoard { let mut result = DraughtsBoard {
data: [0u8; (POSITIONS * BITS_PER_POSITION + 7) / 8], data: [0u8; (POSITIONS * BITS_PER_POSITION).div_ceil(8)],
}; };
for i in 0..DraughtsBoard::rows() { for i in 0..DraughtsBoard::rows() {
for j in 0..DraughtsBoard::columns() { for j in 0..DraughtsBoard::columns() {
if (i + j) % 2 == 0 { if (i + j) % 2 == 0 {
let position = Position::new(i as u8, j as u8).unwrap(); let position = Position::new(i as u8, j as u8).unwrap();
let piece = cb(position.clone()); let piece = cb(position);
result.set(position, piece); result.set(position, piece);
} }
} }
@@ -254,12 +254,6 @@ pub struct DraughtsGame {
next_move: Player, next_move: Player,
} }
#[derive(Clone)]
pub struct SerializedDraughtsGame {
data: Vec<u8, 24>,
next_move: Player,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Error { pub enum Error {
WrongPlayer, WrongPlayer,
@@ -355,22 +349,20 @@ impl DraughtsGame {
} else { } else {
return Err(Error::WrongPlayer); return Err(Error::WrongPlayer);
} }
} else { } else if self.next_move == player {
if self.next_move == player { self.board.apply_move(mv)?;
self.board.apply_move(mv)?; // Check if more captures are available for the current piece
// Check if more captures are available for the current piece if self
if self .board
.board .moves_for_piece(mv.get_end_position(), true)
.moves_for_piece(mv.get_end_position(), true) .next()
.next() .is_some()
.is_some() {
{ return Ok(());
return Ok(());
}
self.next_turn();
} else {
return Err(Error::WrongPlayer);
} }
self.next_turn();
} else {
return Err(Error::WrongPlayer);
}; };
let end = mv.get_end_position(); let end = mv.get_end_position();
//Promote pawns that reach the last row //Promote pawns that reach the last row
@@ -519,68 +511,6 @@ impl DraughtsGame {
} }
} }
impl SerializedDraughtsGame {
fn serialize(position: Position, piece: Piece) -> u8 {
let p = position.row() * 4 + position.col() / 2;
p << 3 | piece as u8
}
fn deserialize(byte: u8) -> Result<(Position, Piece), Error> {
let index = byte >> 3;
let row = index >> 2;
let col = ((index - (row << 2)) % 4) * 2 + (row % 2);
let pos = Position::new(row, col)?;
Ok((
pos,
Piece::from_repr((byte & 7) as usize).ok_or(Error::InvalidPiece)?,
))
}
fn from(
DraughtsGame { board, next_move }: &DraughtsGame,
) -> Result<SerializedDraughtsGame, Error> {
let mut data = Vec::<u8, 24>::new();
for i in 0..DraughtsBoard::rows() {
for j in 0..DraughtsBoard::columns() {
let p = Position::new(i as u8, j as u8)?;
let piece = board.get_piece(&p);
if piece != Piece::NoPiece {
data.push(Self::serialize(p, piece)).unwrap();
}
}
}
Ok(SerializedDraughtsGame {
data,
next_move: *next_move,
})
}
}
impl From<DraughtsGame> for SerializedDraughtsGame {
fn from(DraughtsGame { board, next_move }: DraughtsGame) -> Self {
let mut data = Vec::<u8, 24>::new();
for i in 0..DraughtsBoard::rows() {
for j in 0..DraughtsBoard::columns() {
let p = Position::new(i as u8, j as u8).unwrap();
let piece = board.get_piece(&p);
if piece != Piece::NoPiece {
data.push(Self::serialize(p, piece)).unwrap();
}
}
}
SerializedDraughtsGame {
data,
next_move: next_move,
}
}
}
impl Into<DraughtsGame> for SerializedDraughtsGame {
fn into(self) -> DraughtsGame {
todo!()
}
}
pub struct MoveIterator<'a> { pub struct MoveIterator<'a> {
board: &'a DraughtsBoard, board: &'a DraughtsBoard,
position: Position, position: Position,
@@ -742,44 +672,12 @@ mod std {
} }
} }
#[cfg(feature = "std")]
pub use std::*;
#[cfg(test)] #[cfg(test)]
#[cfg(feature = "std")] #[cfg(feature = "std")]
mod tests { mod tests {
extern crate std; extern crate std;
use super::{ use super::{DraughtsBoard, Piece, Position};
DraughtsBoard, DraughtsGame, Move, MoveDirection, Piece, Player, Position,
SerializedDraughtsGame,
};
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{Hash, Hasher};
#[test]
fn test_serialize_deserialize_piece() {
for (pos, piece) in [
(Position::new(4u8, 2u8), Piece::SimpleRedPawn),
(Position::new(0u8, 6u8), Piece::CrownedRedPawn),
(Position::new(1u8, 7u8), Piece::SimpleWhitePawn),
(Position::new(2u8, 4u8), Piece::CrownedWhitePawn),
(Position::new(3u8, 5u8), Piece::SimpleRedPawn),
(Position::new(6u8, 2u8), Piece::CrownedRedPawn),
(Position::new(7u8, 7u8), Piece::SimpleWhitePawn),
(Position::new(7u8, 1u8), Piece::CrownedWhitePawn),
(Position::new(6u8, 6u8), Piece::SimpleRedPawn),
(Position::new(4u8, 6u8), Piece::CrownedRedPawn),
(Position::new(6u8, 6u8), Piece::SimpleWhitePawn),
(Position::new(4u8, 6u8), Piece::CrownedWhitePawn),
] {
let pos = pos.unwrap();
let serialized = SerializedDraughtsGame::serialize(pos, piece);
let (deserialized_pos, deserialized_piece) =
SerializedDraughtsGame::deserialize(serialized).unwrap();
assert_eq!(piece, deserialized_piece);
assert_eq!(pos, deserialized_pos);
}
}
#[test] #[test]
fn test_create() { fn test_create() {
@@ -823,7 +721,7 @@ mod tests {
#[cfg(feature = "std")] #[cfg(feature = "std")]
mod ai_tests { mod ai_tests {
extern crate std; extern crate std;
use super::{DraughtsBoard, DraughtsGame, Move, MoveDirection, Piece, Player, Position}; use super::{DraughtsGame, Move, MoveDirection, Piece, Player, Position};
use std::collections::HashMap; use std::collections::HashMap;
#[test] #[test]

View File

@@ -1,6 +1,4 @@
#![no_std] #![no_std]
#[macro_use]
extern crate strum;
mod constants; mod constants;
pub mod draughts; pub mod draughts;

View File

@@ -117,9 +117,9 @@ impl Mul<(i32, i32)> for Position {
} }
} }
impl Into<u8> for Position { impl From<Position> for u8 {
fn into(self) -> u8 { fn from(pos: Position) -> Self {
(8 - 1 - self.row()) * (POSITIONS_PER_ROW as u8) + self.col() / 2 (8 - 1 - pos.row()) * (POSITIONS_PER_ROW as u8) + pos.col() / 2
} }
} }