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 rdraught::draughts::DraughtsGame;
use rdraught_ui;
fn main() -> ExitCode {
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::{Application, DrawingArea, prelude::*};
use rdraught::{
DraughtsBoard, DraughtsGame, Error, Move, Piece, Player, Position, RDraughtApplication,
DraughtsBoard, DraughtsGame, Move, Piece, Player, Position, RDraughtApplication,
RectangularBoard,
};
use rsvg::SvgHandle;
@@ -473,17 +473,17 @@ fn create_game_window(
let mut rd_app = rd.borrow_mut();
println!("Applied move: {:?}", mv);
rd_app.apply_move(mv).unwrap();
let game_copy = rd_app.game().clone();
thread::spawn(move || {
if let (Some(mv), analyzed_moves) =
game_copy.get_best_move(10)
{
println!(
"Next best move: {:?}, analyzed moves: {}",
mv, analyzed_moves
);
}
});
// let game_copy = rd_app.game().clone();
// thread::spawn(move || {
// if let (Some(mv), analyzed_moves) =
// game_copy.get_best_move(10)
// {
// println!(
// "Next best move: {:?}, analyzed moves: {}",
// mv, analyzed_moves
// );
// }
// });
move_applied = true;
break;
}

View File

@@ -12,7 +12,7 @@ pub trait RectangularBoard {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DraughtsBoard {
data: [u8; (POSITIONS * BITS_PER_POSITION + 7) / 8],
data: [u8; (POSITIONS * BITS_PER_POSITION).div_ceil(8)],
}
impl DraughtsBoard {
@@ -38,23 +38,23 @@ impl DraughtsBoard {
let index = offset_bits / 8;
let remainder = offset_bits % 8;
let mut value = 0;
value = value | ((self.data[index] >> remainder) & 7);
value |= (self.data[index] >> remainder) & 7;
if remainder > 5 {
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()
}
pub fn new<T: FnMut(Position) -> Piece>(mut cb: T) -> 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 j in 0..DraughtsBoard::columns() {
if (i + j) % 2 == 0 {
let position = Position::new(i as u8, j as u8).unwrap();
let piece = cb(position.clone());
let piece = cb(position);
result.set(position, piece);
}
}
@@ -254,12 +254,6 @@ pub struct DraughtsGame {
next_move: Player,
}
#[derive(Clone)]
pub struct SerializedDraughtsGame {
data: Vec<u8, 24>,
next_move: Player,
}
#[derive(Debug, Clone)]
pub enum Error {
WrongPlayer,
@@ -355,22 +349,20 @@ impl DraughtsGame {
} else {
return Err(Error::WrongPlayer);
}
} else {
if self.next_move == player {
self.board.apply_move(mv)?;
// Check if more captures are available for the current piece
if self
.board
.moves_for_piece(mv.get_end_position(), true)
.next()
.is_some()
{
return Ok(());
}
self.next_turn();
} else {
return Err(Error::WrongPlayer);
} else if self.next_move == player {
self.board.apply_move(mv)?;
// Check if more captures are available for the current piece
if self
.board
.moves_for_piece(mv.get_end_position(), true)
.next()
.is_some()
{
return Ok(());
}
self.next_turn();
} else {
return Err(Error::WrongPlayer);
};
let end = mv.get_end_position();
//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> {
board: &'a DraughtsBoard,
position: Position,
@@ -742,44 +672,12 @@ mod std {
}
}
#[cfg(feature = "std")]
pub use std::*;
#[cfg(test)]
#[cfg(feature = "std")]
mod tests {
extern crate std;
use super::{
DraughtsBoard, DraughtsGame, Move, MoveDirection, Piece, Player, Position,
SerializedDraughtsGame,
};
use super::{DraughtsBoard, Piece, Position};
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]
fn test_create() {
@@ -823,7 +721,7 @@ mod tests {
#[cfg(feature = "std")]
mod ai_tests {
extern crate std;
use super::{DraughtsBoard, DraughtsGame, Move, MoveDirection, Piece, Player, Position};
use super::{DraughtsGame, Move, MoveDirection, Piece, Player, Position};
use std::collections::HashMap;
#[test]

View File

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

View File

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