splitting file structure, enabling pages deployment
This commit is contained in:
parent
98abdcea45
commit
3734d68a64
36
.github/workflows/test.yml
vendored
36
.github/workflows/test.yml
vendored
@ -24,21 +24,27 @@ jobs:
|
|||||||
- name: Test WASM in-browser
|
- name: Test WASM in-browser
|
||||||
run: wasm-pack test --firefox --chrome --headless
|
run: wasm-pack test --firefox --chrome --headless
|
||||||
|
|
||||||
# - name: Install Node
|
- name: Install Node
|
||||||
# uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
# with:
|
with:
|
||||||
# node-version: 16
|
node-version: 16
|
||||||
|
|
||||||
# - name: Install Node Modules
|
- name: Install Node Modules
|
||||||
# run: npm ci
|
run: npm ci
|
||||||
# working-directory: ./www
|
working-directory: ./www
|
||||||
|
|
||||||
# - name: Build Js
|
- name: Build Js
|
||||||
# run: npm run build --if-present
|
run: npm run build --if-present
|
||||||
# working-directory: ./www
|
working-directory: ./www
|
||||||
|
|
||||||
# - name: Deploy To Pages
|
- name: Build Docs
|
||||||
# uses: peaceiris/actions-gh-pages@v3
|
run: cargo doc --no-deps --document-private-items
|
||||||
# with:
|
|
||||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
- name: Move Docs to Staging Directory
|
||||||
# publish_dir: ./www/dist
|
run: mv target/doc www/dist/
|
||||||
|
|
||||||
|
- name: Deploy To Pages
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: ./www/dist
|
||||||
|
57
src/board/enums.rs
Normal file
57
src/board/enums.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
extern crate wasm_bindgen;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
use std::fmt::{Display, Write};
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Team {
|
||||||
|
Black = 0,
|
||||||
|
White = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Team {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Team::White => write!(f, "{}", 'W'),
|
||||||
|
Team::Black => write!(f, "{}", 'B'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Strength {
|
||||||
|
Man = 0,
|
||||||
|
King = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum SquareState {
|
||||||
|
Empty = 0,
|
||||||
|
Occupied = 1,
|
||||||
|
Unplayable = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SquareState {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
SquareState::Empty => write!(f, "{}", 'E'),
|
||||||
|
SquareState::Occupied => write!(f, "{}", 'O'),
|
||||||
|
SquareState::Unplayable => write!(f, "{}", 'U'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Moveable {
|
||||||
|
Allowed = 0,
|
||||||
|
Occupied = 1,
|
||||||
|
OutOfBounds = 2,
|
||||||
|
}
|
106
src/board/iter.rs
Normal file
106
src/board/iter.rs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
use crate::board::{Board, Square};
|
||||||
|
|
||||||
|
pub struct RowIndexIterator<'a> {
|
||||||
|
board: &'a Board,
|
||||||
|
row_cursor: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RowIndexIterator<'a> {
|
||||||
|
pub fn new(board: &'a Board) -> Self {
|
||||||
|
Self {
|
||||||
|
board,
|
||||||
|
row_cursor: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for RowIndexIterator<'a> {
|
||||||
|
type Item = Vec<usize>;
|
||||||
|
|
||||||
|
/// Get next item from the iterator
|
||||||
|
fn next(&mut self) -> Option<Vec<usize>> {
|
||||||
|
if self.row_cursor >= self.board.height {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
let mut holder = Vec::with_capacity(self.board.width);
|
||||||
|
|
||||||
|
let start_idx = self.board.cell_index(self.row_cursor, 0);
|
||||||
|
for i in start_idx..start_idx + self.board.width {
|
||||||
|
holder.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.row_cursor += 1;
|
||||||
|
Some(holder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RowSquareIterator<'a> {
|
||||||
|
board: &'a Board,
|
||||||
|
index_iter: RowIndexIterator<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RowSquareIterator<'a> {
|
||||||
|
pub fn new(board: &'a Board) -> Self {
|
||||||
|
Self {
|
||||||
|
board,
|
||||||
|
index_iter: RowIndexIterator::new(board)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for RowSquareIterator<'a> {
|
||||||
|
type Item = Vec<Square>;
|
||||||
|
|
||||||
|
/// Get next item from the iterator
|
||||||
|
fn next(&mut self) -> Option<Vec<Square>> {
|
||||||
|
|
||||||
|
match self.index_iter.next() {
|
||||||
|
Some(x) => {
|
||||||
|
let mut holder: Vec<Square> = Vec::with_capacity(self.board.width);
|
||||||
|
for i in x {
|
||||||
|
holder.push(self.board.cell(i));
|
||||||
|
}
|
||||||
|
Some(holder)
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::board::enums::SquareState;
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
|
wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn index_iterator() {
|
||||||
|
let board = Board::new(2, 2);
|
||||||
|
let iter = RowIndexIterator::new(&board);
|
||||||
|
let collected: Vec<Vec<usize>> = iter.collect();
|
||||||
|
assert_eq!(vec![
|
||||||
|
vec![0, 1],
|
||||||
|
vec![2, 3]
|
||||||
|
], collected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn square_iterator() {
|
||||||
|
let board = Board::new(2, 2);
|
||||||
|
let iter = RowSquareIterator::new(&board);
|
||||||
|
let collected: Vec<Vec<Square>> = iter.collect();
|
||||||
|
assert_eq!(vec![
|
||||||
|
vec![
|
||||||
|
Square::new(SquareState::Unplayable, Option::None),
|
||||||
|
Square::new(SquareState::Empty, Option::None)
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
Square::new(SquareState::Empty, Option::None),
|
||||||
|
Square::new(SquareState::Unplayable, Option::None)
|
||||||
|
]
|
||||||
|
], collected);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
544
src/board/mod.rs
Normal file
544
src/board/mod.rs
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
|
||||||
|
pub mod enums;
|
||||||
|
use enums::*;
|
||||||
|
|
||||||
|
pub mod iter;
|
||||||
|
use iter::*;
|
||||||
|
|
||||||
|
use std::fmt::{Display, Write};
|
||||||
|
use std::option::Option;
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
pub const STD_WIDTH: usize = 8;
|
||||||
|
pub const STD_HEIGHT: usize = 8;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Piece {
|
||||||
|
team: Team,
|
||||||
|
strength: Strength
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Piece {
|
||||||
|
pub fn new(team: Team, strength: Strength) -> Piece {
|
||||||
|
Piece {
|
||||||
|
team, strength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Direction<T: Clone + Copy> {
|
||||||
|
nw: Option<T>,
|
||||||
|
ne: Option<T>,
|
||||||
|
se: Option<T>,
|
||||||
|
sw: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone + Copy> Direction<T> {
|
||||||
|
pub fn empty() -> Direction<T> {
|
||||||
|
Direction {
|
||||||
|
nw: Option::None,
|
||||||
|
ne: Option::None,
|
||||||
|
se: Option::None,
|
||||||
|
sw: Option::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Square {
|
||||||
|
occupant: Option<Piece>,
|
||||||
|
state: SquareState
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Square {
|
||||||
|
pub fn new(state: SquareState, occupant: Option<Piece>) -> Square{
|
||||||
|
Square {
|
||||||
|
occupant,
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct BrdIdx {
|
||||||
|
row: usize,
|
||||||
|
col: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl BrdIdx {
|
||||||
|
pub fn from(row: usize, col: usize) -> BrdIdx {
|
||||||
|
BrdIdx{
|
||||||
|
row, col
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// BOARD
|
||||||
|
///////////////
|
||||||
|
|
||||||
|
/// Models a single state for a checkers board
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Board {
|
||||||
|
cells: Vec<Square>,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
|
||||||
|
current_turn: Team
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
pub fn cell_mut(&mut self, idx: usize) -> &mut Square {
|
||||||
|
&mut self.cells[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn diagonal_indices(&self, idx: BrdIdx) -> Option<Vec<usize>> {
|
||||||
|
if self.cell_state(self.cell_idx(idx)) == SquareState::Unplayable {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let height_idx = self.height - 1;
|
||||||
|
let width_idx = self.width - 1;
|
||||||
|
|
||||||
|
let mut cells = Vec::with_capacity(4);
|
||||||
|
let mut dir = Direction::empty();
|
||||||
|
|
||||||
|
if idx.row > 0 {
|
||||||
|
if idx.col > 0 {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row - 1, idx.col - 1)
|
||||||
|
);
|
||||||
|
dir.nw = Option::Some(self.cell(self.cell_index(idx.row - 1, idx.col - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx.col < width_idx {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row - 1, idx.col + 1)
|
||||||
|
);
|
||||||
|
dir.ne = Option::Some(self.cell(self.cell_index(idx.row - 1, idx.col + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx.row < height_idx {
|
||||||
|
if idx.col > 0 {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row + 1, idx.col - 1)
|
||||||
|
);
|
||||||
|
dir.sw = Option::Some(self.cell(self.cell_index(idx.row + 1, idx.col - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx.col < width_idx {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row + 1, idx.col + 1)
|
||||||
|
);
|
||||||
|
dir.se = Option::Some(self.cell(self.cell_index(idx.row + 1, idx.col + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cells.shrink_to_fit();
|
||||||
|
Some(cells)
|
||||||
|
// Some(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filter_indices(&self, idx: BrdIdx, player: Team, indices: Vec<usize>) -> Vec<usize> {
|
||||||
|
indices.into_iter().filter(|i| {
|
||||||
|
match player {
|
||||||
|
Team::Black => self.board_index(*i).row < idx.row,
|
||||||
|
Team::White => self.board_index(*i).row > idx.row,
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn player_diagonal_indices(&self, idx: BrdIdx, player: Team) -> Option<Vec<usize>> {
|
||||||
|
match self.diagonal_indices(idx) {
|
||||||
|
Some(x) => Some(self.filter_indices(idx, player, x)),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn jumpable_indices(&self, idx: BrdIdx) -> Option<Vec<usize>> {
|
||||||
|
if self.cell_state(self.cell_idx(idx)) == SquareState::Unplayable {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let height_idx = self.height - 1;
|
||||||
|
let width_idx = self.width - 1;
|
||||||
|
|
||||||
|
let mut cells = Vec::with_capacity(4);
|
||||||
|
|
||||||
|
if idx.row > 1 {
|
||||||
|
if idx.col > 1 {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row - 2, idx.col - 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx.col < width_idx - 1 {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row - 2, idx.col + 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx.row < height_idx - 1 {
|
||||||
|
if idx.col > 1 {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row + 2, idx.col - 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx.col < width_idx - 1 {
|
||||||
|
cells.push(
|
||||||
|
self.cell_index(idx.row + 2, idx.col + 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cells.shrink_to_fit();
|
||||||
|
Some(cells)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn player_jumpable_indices(&self, idx: BrdIdx, player: Team) -> Option<Vec<usize>> {
|
||||||
|
match self.jumpable_indices(idx) {
|
||||||
|
Some(x) => Some(self.filter_indices(idx, player, x)),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl Board {
|
||||||
|
pub fn cell(&self, idx: usize) -> Square {
|
||||||
|
self.cells[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grid_cell(&self, idx: BrdIdx) -> Square {
|
||||||
|
self.cell(self.cell_idx(idx))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cell_index(&self, row: usize, col: usize) -> usize {
|
||||||
|
(row * self.width) + col
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cell_idx(&self, idx: BrdIdx) -> usize {
|
||||||
|
self.cell_index(idx.row, idx.col)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn board_index(&self, idx: usize) -> BrdIdx {
|
||||||
|
let row = idx / self.width;
|
||||||
|
let col = idx - (row * self.width);
|
||||||
|
BrdIdx::from(row, col)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn can_move(&self, from: BrdIdx, to: BrdIdx) -> bool {
|
||||||
|
// let diagonals = self.diagonal_indices(from);
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn new(width: usize, height: usize) -> Board {
|
||||||
|
let total_cells = width * height;
|
||||||
|
|
||||||
|
let mut cells: Vec<Square> = Vec::with_capacity(total_cells);
|
||||||
|
let mut playable = false;
|
||||||
|
|
||||||
|
for i in 0..height {
|
||||||
|
for _ in 0..width {
|
||||||
|
if playable {
|
||||||
|
cells.push(Square::new(SquareState::Empty, None));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cells.push(Square::new(SquareState::Unplayable, None));
|
||||||
|
}
|
||||||
|
playable = !playable;
|
||||||
|
}
|
||||||
|
playable = i % 2 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Board {
|
||||||
|
cells,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
|
||||||
|
current_turn: Team::Black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_game(board: Board) -> Board {
|
||||||
|
let mut new_board = board.clone();
|
||||||
|
for (idx, row) in RowSquareIterator::new(&board).enumerate() {
|
||||||
|
for (jdx, square) in row.iter().enumerate() {
|
||||||
|
|
||||||
|
if square.state == SquareState::Empty || square.state == SquareState::Occupied {
|
||||||
|
if idx < 3 {
|
||||||
|
let cell_idx = new_board.cell_index(idx, jdx);
|
||||||
|
new_board.cells[cell_idx] = Square::new(
|
||||||
|
SquareState::Occupied,
|
||||||
|
Some(Piece::new(Team::White, Strength::Man))
|
||||||
|
);
|
||||||
|
} else if idx >= board.height - 3 {
|
||||||
|
let cell_idx = new_board.cell_index(idx, jdx);
|
||||||
|
new_board.cells[cell_idx] = Square::new(
|
||||||
|
SquareState::Occupied,
|
||||||
|
Some(Piece::new(Team::Black, Strength::Man))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let cell_idx = new_board.cell_index(idx, jdx);
|
||||||
|
new_board.cells[cell_idx] = Square::new(
|
||||||
|
SquareState::Empty,
|
||||||
|
None
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_board
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_turn(&self) -> Team {
|
||||||
|
self.current_turn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cells(&self) -> *const Square {
|
||||||
|
self.cells.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_cells(&self) -> usize {
|
||||||
|
self.cells.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cell_state(&self, idx: usize) -> SquareState {
|
||||||
|
self.cell(idx).state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Board {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result{
|
||||||
|
let mut string = String::new();
|
||||||
|
|
||||||
|
for i in 0..self.height {
|
||||||
|
for j in 0..self.width {
|
||||||
|
let idx = self.cell_index(i, j);
|
||||||
|
|
||||||
|
match self.cell_state(idx) {
|
||||||
|
SquareState::Empty => { write!(string, "{}", SquareState::Empty); },
|
||||||
|
SquareState::Occupied => { write!(string, "{}", self.cell(idx).occupant.unwrap().team); },
|
||||||
|
SquareState::Unplayable => { write!(string, "{}", SquareState::Unplayable); },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "{}", string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
use crate::log;
|
||||||
|
|
||||||
|
wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn create() {
|
||||||
|
let board = Board::new(STD_WIDTH, STD_HEIGHT);
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn std_num_cells() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(64, board.num_cells());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// INDEXING
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn cell_index_top_left() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(0, board.cell_index(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn cell_index_central() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(9, board.cell_index(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn cell_index_central_2() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(17, board.cell_index(2, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn board_index() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
|
||||||
|
// first row
|
||||||
|
assert_eq!(BrdIdx::from(0, 5), board.board_index(5));
|
||||||
|
// second row
|
||||||
|
assert_eq!(BrdIdx::from(1, 6), board.board_index(14));
|
||||||
|
// third row
|
||||||
|
assert_eq!(BrdIdx::from(2, 4), board.board_index(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
// SQUARE STATE
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn first_square_unplayable() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(SquareState::Unplayable, board.cell_state(board.cell_index(0, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn first_square_row_5_unplayable() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(SquareState::Empty, board.cell_state(board.cell_index(5, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// DIAGNOAL INDICES
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_unplayable() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(None, board.diagonal_indices(BrdIdx::from(7, 7)));
|
||||||
|
assert_eq!(None, board.diagonal_indices(BrdIdx::from(0, 0)));
|
||||||
|
assert_eq!(None, board.diagonal_indices(BrdIdx::from(1, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_central() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![1, 3, 17, 19]), board.diagonal_indices(BrdIdx::from(1, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_top_row() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![8, 10]), board.diagonal_indices(BrdIdx::from(0, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_left_column() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![1, 17]), board.diagonal_indices(BrdIdx::from(1, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_bottom_row() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![49, 51]), board.diagonal_indices(BrdIdx::from(7, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_right_column() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![14, 30]), board.diagonal_indices(BrdIdx::from(2, 7)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_top_right() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![14]), board.diagonal_indices(BrdIdx::from(0, 7)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn moveable_indices_bottom_left() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![49]), board.diagonal_indices(BrdIdx::from(7, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// JUMPABLE INDICES
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_unplayable() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(None, board.jumpable_indices(BrdIdx::from(7, 7)));
|
||||||
|
assert_eq!(None, board.jumpable_indices(BrdIdx::from(0, 0)));
|
||||||
|
assert_eq!(None, board.jumpable_indices(BrdIdx::from(1, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![24, 28]), board.jumpable_indices(BrdIdx::from(1, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_central() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![10, 14, 42, 46]), board.jumpable_indices(BrdIdx::from(3, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_top_row() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![19]), board.jumpable_indices(BrdIdx::from(0, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_left_column() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![26]), board.jumpable_indices(BrdIdx::from(1, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_bottom_row() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![40, 44]), board.jumpable_indices(BrdIdx::from(7, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_right_column() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![5, 37]), board.jumpable_indices(BrdIdx::from(2, 7)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_top_right() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![21]), board.jumpable_indices(BrdIdx::from(0, 7)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn jumpable_indices_bottom_left() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![42]), board.jumpable_indices(BrdIdx::from(7, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn init_game() {
|
||||||
|
let board = Board::init_game(Board::new(8, 8));
|
||||||
|
log!("{}", board);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn black_diagonal_indices() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![1, 3]), board.player_diagonal_indices(BrdIdx::from(1, 2), Team::Black));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn white_diagonal_indices() {
|
||||||
|
let board = Board::new(8, 8);
|
||||||
|
assert_eq!(Some(vec![17, 19]), board.player_diagonal_indices(BrdIdx::from(1, 2), Team::White));
|
||||||
|
}
|
||||||
|
}
|
12
src/game.rs
Normal file
12
src/game.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::board::Board;
|
||||||
|
use indextree::Arena;
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct Game {
|
||||||
|
current: Board,
|
||||||
|
previous_boards: Vec<Board>,
|
||||||
|
tree: Arena<Board>
|
||||||
|
}
|
260
src/lib.rs
260
src/lib.rs
@ -1,27 +1,17 @@
|
|||||||
mod utils;
|
pub mod board;
|
||||||
|
pub mod utils;
|
||||||
use std::fmt::{Display, Write};
|
pub mod game;
|
||||||
use std::option::Option;
|
|
||||||
|
|
||||||
extern crate wasm_bindgen;
|
extern crate wasm_bindgen;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
extern crate indextree;
|
|
||||||
use indextree::Arena;
|
|
||||||
|
|
||||||
pub const STD_WIDTH: usize = 8;
|
|
||||||
pub const STD_HEIGHT: usize = 8;
|
|
||||||
|
|
||||||
// use rand::prelude::*;
|
|
||||||
|
|
||||||
// use rand_pcg::Pcg64Mcg;
|
|
||||||
|
|
||||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||||
// allocator.
|
// allocator.
|
||||||
// #[cfg(feature = "wee_alloc")]
|
// #[cfg(feature = "wee_alloc")]
|
||||||
// #[global_allocator]
|
// #[global_allocator]
|
||||||
// static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
// static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! log {
|
macro_rules! log {
|
||||||
( $( $t:tt )* ) => {
|
( $( $t:tt )* ) => {
|
||||||
web_sys::console::log_1(&format!( $( $t )* ).into());
|
web_sys::console::log_1(&format!( $( $t )* ).into());
|
||||||
@ -35,246 +25,4 @@ pub fn init_game() {
|
|||||||
|
|
||||||
#[cfg(feature = "random_init")]
|
#[cfg(feature = "random_init")]
|
||||||
log!("random layout enabled");
|
log!("random layout enabled");
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
pub enum Team {
|
|
||||||
Black = 0,
|
|
||||||
White = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
pub enum Strength {
|
|
||||||
Man = 0,
|
|
||||||
King = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
pub enum SquareState {
|
|
||||||
Empty = 0,
|
|
||||||
Occupied = 1,
|
|
||||||
Unplayable = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for SquareState {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
SquareState::Empty => {write!(f, "{}", 'E')},
|
|
||||||
SquareState::Occupied => {write!(f, "{}", 'O')},
|
|
||||||
SquareState::Unplayable => {write!(f, "{}", 'U')},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Piece {
|
|
||||||
id: u8,
|
|
||||||
team: Team,
|
|
||||||
strength: Strength
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Square {
|
|
||||||
occupant: Option<Piece>,
|
|
||||||
state: SquareState
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Square {
|
|
||||||
fn new(state: SquareState, occupant: Option<Piece>) -> Square{
|
|
||||||
Square {
|
|
||||||
occupant,
|
|
||||||
state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
pub struct BrdIdx {
|
|
||||||
row: usize,
|
|
||||||
col: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
impl BrdIdx {
|
|
||||||
pub fn from(row: usize, col: usize) -> BrdIdx {
|
|
||||||
BrdIdx{
|
|
||||||
row, col
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// BOARD
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Board {
|
|
||||||
cells: Vec<Square>,
|
|
||||||
width: usize,
|
|
||||||
height: usize,
|
|
||||||
|
|
||||||
current_turn: Team
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Board {
|
|
||||||
pub fn cell(&self, idx: usize) -> &Square {
|
|
||||||
&self.cells[idx]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn grid_cell(&self, idx: BrdIdx) -> &Square {
|
|
||||||
self.cell(self.cell_idx(idx))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cell_mut(&mut self, idx: usize) -> &mut Square {
|
|
||||||
&mut self.cells[idx]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
impl Board {
|
|
||||||
pub fn cell_index(&self, row: usize, col: usize) -> usize {
|
|
||||||
(row * self.width) + col
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cell_idx(&self, idx: BrdIdx) -> usize {
|
|
||||||
self.cell_index(idx.row, idx.col)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn board_index(&self, idx: usize) -> BrdIdx {
|
|
||||||
let row = idx / self.width;
|
|
||||||
let col = idx - (row * self.width);
|
|
||||||
BrdIdx::from(row, col)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn diagonal_indices(&self, idx: BrdIdx) -> Option<Vec<usize>> {
|
|
||||||
if self.cell_state(self.cell_idx(idx)) == SquareState::Unplayable {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let height_idx = self.height - 1;
|
|
||||||
let width_idx = self.width - 1;
|
|
||||||
|
|
||||||
let mut cells = Vec::with_capacity(4);
|
|
||||||
|
|
||||||
if idx.row > 0 {
|
|
||||||
if idx.col > 0 {
|
|
||||||
cells.push(
|
|
||||||
self.cell_index(idx.row - 1, idx.col - 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx.col < width_idx {
|
|
||||||
cells.push(
|
|
||||||
self.cell_index(idx.row - 1, idx.col + 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx.row < height_idx {
|
|
||||||
if idx.col > 0 {
|
|
||||||
cells.push(
|
|
||||||
self.cell_index(idx.row + 1, idx.col - 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx.col < width_idx {
|
|
||||||
cells.push(
|
|
||||||
self.cell_index(idx.row + 1, idx.col + 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cells.shrink_to_fit();
|
|
||||||
Some(cells)
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn can_move(&self, from: BrdIdx, to: BrdIdx) -> bool {
|
|
||||||
// let diagonals = self.diagonal_indices(from);
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn new(width: usize, height: usize) -> Board {
|
|
||||||
let total_cells = width * height;
|
|
||||||
|
|
||||||
let mut cells: Vec<Square> = Vec::with_capacity(total_cells);
|
|
||||||
let mut playable = false;
|
|
||||||
|
|
||||||
for i in 0..height {
|
|
||||||
for _ in 0..width {
|
|
||||||
if playable {
|
|
||||||
cells.push(Square::new(SquareState::Empty, None));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cells.push(Square::new(SquareState::Unplayable, None));
|
|
||||||
}
|
|
||||||
playable = !playable;
|
|
||||||
}
|
|
||||||
playable = i % 2 == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Board {
|
|
||||||
cells,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
|
|
||||||
current_turn: Team::Black
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_turn(&self) -> Team {
|
|
||||||
self.current_turn
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cells(&self) -> *const Square {
|
|
||||||
self.cells.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn num_cells(&self) -> usize {
|
|
||||||
self.cells.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cell_state(&self, idx: usize) -> SquareState {
|
|
||||||
self.cell(idx).state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Board {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result{
|
|
||||||
let mut string = String::new();
|
|
||||||
|
|
||||||
for i in 0..self.height {
|
|
||||||
for j in 0..self.width {
|
|
||||||
write!(string, "{}",
|
|
||||||
self.cell_state( // empty, unocc, unplayable
|
|
||||||
self.cell_index( // 1d vec idx from 2d board idx
|
|
||||||
i, j // 2d board idx
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
string.push('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "{}", string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// GAME
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
pub struct Game {
|
|
||||||
current: Board,
|
|
||||||
tree: Arena<Board>
|
|
||||||
}
|
}
|
122
tests/board.rs
122
tests/board.rs
@ -7,125 +7,3 @@ extern crate wasm_bindgen_test;
|
|||||||
use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
|
use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
|
||||||
|
|
||||||
wasm_bindgen_test_configure!(run_in_browser);
|
wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
extern crate web_sys;
|
|
||||||
use web_sys::console;
|
|
||||||
|
|
||||||
extern crate draught;
|
|
||||||
use draught::{Board, BrdIdx, SquareState, STD_WIDTH, STD_HEIGHT};
|
|
||||||
|
|
||||||
macro_rules! log {
|
|
||||||
( $( $t:tt )* ) => {
|
|
||||||
web_sys::console::log_1(&format!( $( $t )* ).into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn create() {
|
|
||||||
let board = Board::new(STD_WIDTH, STD_HEIGHT);
|
|
||||||
assert!(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn std_num_cells() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(64, board.num_cells());
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// INDEXING
|
|
||||||
//////////////
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn cell_index_top_left() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(0, board.cell_index(0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn cell_index_central() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(9, board.cell_index(1, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn cell_index_central_2() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(17, board.cell_index(2, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn board_index() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
|
|
||||||
// first row
|
|
||||||
assert_eq!(BrdIdx::from(0, 5), board.board_index(5));
|
|
||||||
// second row
|
|
||||||
assert_eq!(BrdIdx::from(1, 6), board.board_index(14));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////
|
|
||||||
// SQUARE STATE
|
|
||||||
///////////////////
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn first_square_unplayable() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(SquareState::Unplayable, board.cell_state(board.cell_index(0, 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn first_square_row_5_unplayable() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(SquareState::Empty, board.cell_state(board.cell_index(5, 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_unplayable() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(None, board.diagonal_indices(BrdIdx::from(7, 7)));
|
|
||||||
assert_eq!(None, board.diagonal_indices(BrdIdx::from(0, 0)));
|
|
||||||
assert_eq!(None, board.diagonal_indices(BrdIdx::from(1, 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_central() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![1, 3, 17, 19]), board.diagonal_indices(BrdIdx::from(1, 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_top_row() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![8, 10]), board.diagonal_indices(BrdIdx::from(0, 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_left_column() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![1, 17]), board.diagonal_indices(BrdIdx::from(1, 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_bottom_row() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![49, 51]), board.diagonal_indices(BrdIdx::from(7, 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_right_column() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![14, 30]), board.diagonal_indices(BrdIdx::from(2, 7)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_top_right() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![14]), board.diagonal_indices(BrdIdx::from(0, 7)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn moveable_indices_bottom_left() {
|
|
||||||
let board = Board::new(8, 8);
|
|
||||||
assert_eq!(Some(vec![49]), board.diagonal_indices(BrdIdx::from(7, 0)));
|
|
||||||
}
|
|
||||||
|
@ -34,7 +34,16 @@
|
|||||||
<h1>Draught 🚀</h1>
|
<h1>Draught 🚀</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<div class="row p-1">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<p class="text-muted">Working on an implementation of checkers in Rust WASM with a thin Js frontend, mainly as an exercise to learn Rust and to have a larger project in the language to fiddle with. The idea is to use the <a href="https://en.wikipedia.org/wiki/Minimax">minimax</a> algorithm to create an AI player that can operate with reasonable performance as a result of Rust's compiled performance.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row p-1">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<a href="doc/draught" class="btn btn-secondary">Docs</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
11277
www/package-lock.json
generated
Normal file
11277
www/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/Sarsoo/draught#readme",
|
"homepage": "https://github.com/Sarsoo/draught#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"gameoflife": "file:../pkg"
|
"draught": "file:../pkg"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"copy-webpack-plugin": "^9.0.0",
|
"copy-webpack-plugin": "^9.0.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user