Compare commits
1 Commits
60b65e3eec
...
dev
Author | SHA1 | Date | |
---|---|---|---|
6d415468e0
|
@@ -1,5 +1,6 @@
|
|||||||
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();
|
||||||
|
@@ -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, Move, Piece, Player, Position, RDraughtApplication,
|
DraughtsBoard, DraughtsGame, Error, 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;
|
||||||
}
|
}
|
||||||
|
@@ -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).div_ceil(8)],
|
data: [u8; (POSITIONS * BITS_PER_POSITION + 7) / 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 |= (self.data[index] >> remainder) & 7;
|
value = value | ((self.data[index] >> remainder) & 7);
|
||||||
if remainder > 5 {
|
if remainder > 5 {
|
||||||
let written_bits = 8 - remainder;
|
let written_bits = 8 - remainder;
|
||||||
value |= (self.data[index + 1] & (7 >> written_bits)) << written_bits
|
value = 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).div_ceil(8)],
|
data: [0u8; (POSITIONS * BITS_PER_POSITION + 7) / 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);
|
let piece = cb(position.clone());
|
||||||
result.set(position, piece);
|
result.set(position, piece);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,6 +254,12 @@ 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,
|
||||||
@@ -349,20 +355,22 @@ impl DraughtsGame {
|
|||||||
} else {
|
} else {
|
||||||
return Err(Error::WrongPlayer);
|
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 {
|
} else {
|
||||||
return Err(Error::WrongPlayer);
|
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();
|
let end = mv.get_end_position();
|
||||||
//Promote pawns that reach the last row
|
//Promote pawns that reach the last row
|
||||||
@@ -511,6 +519,68 @@ 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,
|
||||||
@@ -672,12 +742,44 @@ 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::{DraughtsBoard, Piece, Position};
|
use super::{
|
||||||
|
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() {
|
||||||
@@ -721,7 +823,7 @@ mod tests {
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod ai_tests {
|
mod ai_tests {
|
||||||
extern crate std;
|
extern crate std;
|
||||||
use super::{DraughtsGame, Move, MoveDirection, Piece, Player, Position};
|
use super::{DraughtsBoard, DraughtsGame, Move, MoveDirection, Piece, Player, Position};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate strum;
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
pub mod draughts;
|
pub mod draughts;
|
||||||
|
@@ -117,9 +117,9 @@ impl Mul<(i32, i32)> for Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Position> for u8 {
|
impl Into<u8> for Position {
|
||||||
fn from(pos: Position) -> Self {
|
fn into(self) -> u8 {
|
||||||
(8 - 1 - pos.row()) * (POSITIONS_PER_ROW as u8) + pos.col() / 2
|
(8 - 1 - self.row()) * (POSITIONS_PER_ROW as u8) + self.col() / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user