tangled
alpha
login
or
join now
nove.dev
/
outsider
0
fork
atom
cleanroom implementation of a chess engine. doesn't work :)
0
fork
atom
overview
issues
pulls
pipelines
change to bitboard repr, convert some functions
nove.dev
8 months ago
c3c200df
f379095d
+148
-57
3 changed files
expand all
collapse all
unified
split
Cargo.lock
Cargo.toml
src
lib.rs
+42
Cargo.lock
···
3
3
version = 4
4
4
5
5
[[package]]
6
6
+
name = "bitvec"
7
7
+
version = "1.0.1"
8
8
+
source = "registry+https://github.com/rust-lang/crates.io-index"
9
9
+
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
10
10
+
dependencies = [
11
11
+
"funty",
12
12
+
"radium",
13
13
+
"tap",
14
14
+
"wyz",
15
15
+
]
16
16
+
17
17
+
[[package]]
6
18
name = "chessbot"
7
19
version = "0.1.0"
20
20
+
dependencies = [
21
21
+
"bitvec",
22
22
+
]
23
23
+
24
24
+
[[package]]
25
25
+
name = "funty"
26
26
+
version = "2.0.0"
27
27
+
source = "registry+https://github.com/rust-lang/crates.io-index"
28
28
+
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
29
29
+
30
30
+
[[package]]
31
31
+
name = "radium"
32
32
+
version = "0.7.0"
33
33
+
source = "registry+https://github.com/rust-lang/crates.io-index"
34
34
+
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
35
35
+
36
36
+
[[package]]
37
37
+
name = "tap"
38
38
+
version = "1.0.1"
39
39
+
source = "registry+https://github.com/rust-lang/crates.io-index"
40
40
+
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
41
41
+
42
42
+
[[package]]
43
43
+
name = "wyz"
44
44
+
version = "0.5.1"
45
45
+
source = "registry+https://github.com/rust-lang/crates.io-index"
46
46
+
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
47
47
+
dependencies = [
48
48
+
"tap",
49
49
+
]
+1
Cargo.toml
···
4
4
edition = "2024"
5
5
6
6
[dependencies]
7
7
+
bitvec = "1.0.1"
+105
-57
src/lib.rs
···
1
1
+
use bitvec::prelude::*;
1
2
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2
3
enum Piece {
3
4
Pawn,
···
31
32
}
32
33
}
33
34
34
34
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35
35
-
struct LocatedPiece {
36
36
-
piece: Piece,
37
37
-
rank: usize,
38
38
-
file: usize,
35
35
+
#[derive(Clone, Copy, PartialEq, Eq, Default)]
36
36
+
struct BitBoard {
37
37
+
backing: u64,
38
38
+
}
39
39
+
impl BitBoard {
40
40
+
fn get_square(&self, file: u8, rank: u8) -> bool {
41
41
+
self.backing & (rank * 8 + file) as u64 != 0
42
42
+
}
43
43
+
fn set_square(&mut self, file: u8, rank: u8) {
44
44
+
self.backing &= (rank * 8 + file) as u64
45
45
+
}
46
46
+
fn del_square(&mut self, file: u8, rank: u8) {
47
47
+
self.backing &= !((rank * 8 + file) as u64)
48
48
+
}
49
49
+
fn toggle_square(&mut self, file: u8, rank: u8) {
50
50
+
self.backing ^= (rank * 8 + file) as u64
51
51
+
}
52
52
+
fn value(&self) -> u32 {
53
53
+
self.backing.count_ones()
54
54
+
}
55
55
+
}
56
56
+
57
57
+
struct Move {
58
58
+
source_rank: u8,
59
59
+
dest_rank: u8,
60
60
+
source_file: u8,
61
61
+
dest_file: u8,
39
62
}
40
63
41
64
pub struct Board {
42
42
-
white: Vec<LocatedPiece>,
43
43
-
black: Vec<LocatedPiece>,
44
65
white_to_move: bool,
66
66
+
white_pawns: BitBoard,
67
67
+
white_knights: BitBoard,
68
68
+
white_bishops: BitBoard,
69
69
+
white_rooks: BitBoard,
70
70
+
white_queens: BitBoard,
71
71
+
white_king: BitBoard,
72
72
+
black_pawns: BitBoard,
73
73
+
black_knights: BitBoard,
74
74
+
black_bishops: BitBoard,
75
75
+
black_rooks: BitBoard,
76
76
+
black_queens: BitBoard,
77
77
+
black_king: BitBoard,
45
78
}
46
79
47
80
impl Board {
48
81
pub fn new() -> Self {
49
49
-
let white_pawns = (0..8)
50
50
-
.map(|file| LocatedPiece {
51
51
-
piece: Piece::Pawn,
52
52
-
rank: 1,
53
53
-
file,
54
54
-
})
55
55
-
.collect::<Vec<_>>();
56
56
-
let black_pawns = white_pawns
57
57
-
.iter()
58
58
-
.map(|&lp| LocatedPiece { rank: 6, ..lp })
59
59
-
.collect::<Vec<_>>();
60
60
-
61
61
-
let white_pieces = vec![
62
62
-
Piece::Rook,
63
63
-
Piece::Knight,
64
64
-
Piece::Bishop,
65
65
-
Piece::Queen,
66
66
-
Piece::King,
67
67
-
Piece::Bishop,
68
68
-
Piece::Knight,
69
69
-
Piece::Rook,
70
70
-
]
71
71
-
.into_iter()
72
72
-
.enumerate()
73
73
-
.map(|(idx, piece)| LocatedPiece {
74
74
-
piece,
75
75
-
rank: 0,
76
76
-
file: idx,
77
77
-
});
78
78
-
79
79
-
let black_pieces = white_pieces
80
80
-
.clone()
81
81
-
.rev()
82
82
-
.map(|lp| LocatedPiece { rank: 7, ..lp });
83
83
-
82
82
+
let white_pawns = BitBoard {
83
83
+
backing: 0xff << 1 * 8,
84
84
+
};
85
85
+
let black_pawns = BitBoard {
86
86
+
backing: 0xff << 6 * 8,
87
87
+
};
88
88
+
let white_knights = BitBoard {
89
89
+
backing: 0b01000010,
90
90
+
};
91
91
+
let black_knights = BitBoard {
92
92
+
backing: 0b01000010 << 7 * 8,
93
93
+
};
94
94
+
let white_bishops = BitBoard {
95
95
+
backing: 0b00100100,
96
96
+
};
97
97
+
let black_bishops = BitBoard {
98
98
+
backing: 0b00100100 << 7 * 8,
99
99
+
};
100
100
+
let white_rooks = BitBoard {
101
101
+
backing: 0b10000001,
102
102
+
};
103
103
+
let black_rooks = BitBoard {
104
104
+
backing: 0b10000001 << 7 * 8,
105
105
+
};
106
106
+
let white_queens = BitBoard {
107
107
+
backing: 0b00001000,
108
108
+
};
109
109
+
let black_queens = BitBoard {
110
110
+
backing: 0b00001000 << 7 * 8,
111
111
+
};
112
112
+
let white_king = BitBoard {
113
113
+
backing: 0b00010000,
114
114
+
};
115
115
+
let black_king = BitBoard {
116
116
+
backing: 0b00010000 << 7 * 8,
117
117
+
};
84
118
Self {
85
85
-
white: white_pieces.chain(white_pawns).collect(),
86
86
-
black: black_pieces.chain(black_pawns).collect(),
87
119
white_to_move: true,
120
120
+
white_pawns,
121
121
+
white_knights,
122
122
+
white_bishops,
123
123
+
white_rooks,
124
124
+
white_queens,
125
125
+
white_king,
126
126
+
127
127
+
black_pawns,
128
128
+
black_knights,
129
129
+
black_bishops,
130
130
+
black_rooks,
131
131
+
black_queens,
132
132
+
black_king,
88
133
}
89
134
}
90
135
fn material(&self) -> i32 {
91
91
-
let white_value = self
92
92
-
.white
93
93
-
.iter()
94
94
-
.map(|piece| piece.piece.value())
95
95
-
.sum::<i32>();
96
96
-
let black_value = self
97
97
-
.black
98
98
-
.iter()
99
99
-
.map(|piece| piece.piece.value())
100
100
-
.sum::<i32>();
101
101
-
white_value - black_value
136
136
+
let white_value = self.white_pawns.value()
137
137
+
+ self.white_knights.value() * 3
138
138
+
+ self.white_bishops.value() * 3
139
139
+
+ self.white_rooks.value() * 5
140
140
+
+ self.white_queens.value() * 9;
141
141
+
let black_value = self.black_pawns.value()
142
142
+
+ self.black_knights.value() * 3
143
143
+
+ self.black_bishops.value() * 3
144
144
+
+ self.black_rooks.value() * 5
145
145
+
+ self.black_queens.value() * 9;
146
146
+
white_value as i32 - black_value as i32
102
147
}
103
148
pub fn make_move(&mut self, algebra: &str) {
104
149
let (mover, non_mover) = self.movers_or_not();
···
170
215
source_rank.is_none_or(|rank| rank == lp.rank)
171
216
&& source_file.is_none_or(|file| file == lp.file)
172
217
})
173
173
-
.find(|lp| self.valid_moves(lp.clone()).contains(&(dest_file, dest_rank)))
218
218
+
.find(|lp| {
219
219
+
self.valid_moves(lp.clone())
220
220
+
.contains(&(dest_file, dest_rank))
221
221
+
})
174
222
.unwrap();
175
223
176
224
self.capture_if_possible(dest_file, dest_rank);
···
180
228
fn valid_moves(&self, lp: &LocatedPiece) -> Vec<(usize, usize)> {
181
229
let mut moves = vec![];
182
230
match lp.piece {
183
183
-
Piece::Pawn => ,//todo: en passant (requires a list of moves to keep track of whether the previous
231
231
+
Piece::Pawn => todo!(), //todo: en passant (requires a list of moves to keep track of whether the previous
184
232
//move was one that is en passantable?)
185
233
Piece::Knight => todo!(),
186
234
Piece::Bishop => todo!(),