big refactoring: put everything in model to allow
for better mvc structure (yes i'm doing view in cpp)
This commit is contained in:
23
cpp/src/model/pieces/bishop.cpp
Normal file
23
cpp/src/model/pieces/bishop.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
#include "piece.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<Move> bishop_moves(const Board& b, const Coords xy) {
|
||||
std::vector<Move> ret;
|
||||
auto ne = look_direction(b, xy, 1, 1);
|
||||
ret.insert(ret.end(), ne.begin(), ne.end());
|
||||
|
||||
auto se = look_direction(b, xy, 1, -1);
|
||||
ret.insert(ret.end(), se.begin(), se.end());
|
||||
|
||||
auto sw = look_direction(b, xy, -1, -1);
|
||||
ret.insert(ret.end(), sw.begin(), sw.end());
|
||||
|
||||
auto nw = look_direction(b, xy, -1, 1);
|
||||
ret.insert(ret.end(), nw.begin(), nw.end());
|
||||
|
||||
return ret;
|
||||
}
|
75
cpp/src/model/pieces/king.cpp
Normal file
75
cpp/src/model/pieces/king.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
#include "piece.hpp"
|
||||
|
||||
static bool is_clear_king_side(const Board& b, const Coords xy) {
|
||||
for (int dx = 1; dx < 3; dx++) {
|
||||
Coords c{xy.x + dx, xy.y};
|
||||
if (b.squares[c.to_index()] != Piece::None)
|
||||
return false;
|
||||
|
||||
std::optional<Move> move = move_for_position(b, xy, c);
|
||||
Board board_after_move = b.make_move(move.value());
|
||||
if (board_after_move.is_check_for(b.colour_at(xy)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_clear_queen_side(const Board& b, const Coords xy) {
|
||||
for (int dx = 1; dx < 4; dx++) {
|
||||
Coords c{xy.x - dx, xy.y};
|
||||
if (b.squares[c.to_index()] != Piece::None)
|
||||
return false;
|
||||
|
||||
std::optional<Move> move = move_for_position(b, xy, c);
|
||||
Board board_after_move = b.make_move(move.value());
|
||||
if (dx < 3 && board_after_move.is_check_for(b.colour_at(xy)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Move> king_moves(const Board& b, const Coords xy) {
|
||||
std::vector<Move> ret;
|
||||
|
||||
// -- Regular moves
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
if (dx == 0 && dy == 0) // skip staying in the same position
|
||||
continue;
|
||||
Coords c{xy.x + dx, xy.y + dy};
|
||||
std::optional<Move> move = move_for_position(b, xy, c);
|
||||
if (move.has_value())
|
||||
ret.push_back(move.value());
|
||||
}
|
||||
}
|
||||
|
||||
if (b.is_check_for(b.colour_at(xy)))
|
||||
return keep_only_blocking(ret, b);
|
||||
|
||||
// -- Castles
|
||||
int8_t castling_rights = b.colour_at(xy) == Colour::White
|
||||
? b.w_castle_rights
|
||||
: b.b_castle_rights;
|
||||
|
||||
if (castling_rights == CastleSide::NeitherSide)
|
||||
return ret;
|
||||
|
||||
if (castling_rights & CastleSide::KingSide && is_clear_king_side(b, xy)) {
|
||||
ret.push_back(Move{
|
||||
xy.to_index(),
|
||||
Coords{6, xy.y}.to_index(),
|
||||
});
|
||||
}
|
||||
|
||||
if (castling_rights & CastleSide::QueenSide && is_clear_queen_side(b, xy)) {
|
||||
ret.push_back(Move{
|
||||
xy.to_index(),
|
||||
Coords{2, xy.y}.to_index(),
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
28
cpp/src/model/pieces/knight.cpp
Normal file
28
cpp/src/model/pieces/knight.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
#include "piece.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<Move> knight_moves(const Board& b, const Coords xy) {
|
||||
std::vector<Move> ret;
|
||||
std::vector<std::pair<int, int>> moves = {
|
||||
{+2, +1},
|
||||
{+1, +2}, // north east
|
||||
{+2, -1},
|
||||
{+1, -2}, // south east
|
||||
{-2, -1},
|
||||
{-1, -2}, // south west
|
||||
{-2, +1},
|
||||
{-1, +2} // north west
|
||||
};
|
||||
|
||||
for (const auto& [dx, dy] : moves) {
|
||||
std::optional<Move> move =
|
||||
move_for_position(b, xy, Coords{xy.x + dx, xy.y + dy});
|
||||
if (move.has_value())
|
||||
ret.push_back(move.value());
|
||||
}
|
||||
return ret;
|
||||
}
|
83
cpp/src/model/pieces/pawn.cpp
Normal file
83
cpp/src/model/pieces/pawn.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
#include "piece.hpp"
|
||||
|
||||
std::vector<Move> pawn_moves(const Board& b, const Coords xy) {
|
||||
std::vector<Move> ret{};
|
||||
int8_t my_colour = b.colour_at(xy);
|
||||
|
||||
// -- Capture to the left
|
||||
if (xy.x > 0) {
|
||||
int dy = my_colour == Colour::White ? 1 : -1;
|
||||
Coords left{xy.x - 1, xy.y + dy};
|
||||
int8_t capturable_piece = b.squares[left.to_index()];
|
||||
if (capturable_piece != 0) {
|
||||
if (my_colour != b.colour_at(left))
|
||||
if ((my_colour == White && left.y == 7)
|
||||
|| (my_colour == Black && left.y == 0))
|
||||
for (auto piece : {Rook, Knigt, Bishop, Queen})
|
||||
ret.push_back(Move{
|
||||
xy.to_index(),
|
||||
left.to_index(),
|
||||
(int8_t) (my_colour | piece)
|
||||
});
|
||||
else
|
||||
ret.push_back(Move{xy.to_index(), left.to_index()});
|
||||
}
|
||||
}
|
||||
|
||||
// -- Capture to the right
|
||||
if (xy.x < 7) {
|
||||
int dy = my_colour == Colour::White ? 1 : -1;
|
||||
Coords right{xy.x + 1, xy.y + dy};
|
||||
int8_t capturable_piece = b.squares[right.to_index()];
|
||||
if (capturable_piece != 0) {
|
||||
if (my_colour != b.colour_at(right))
|
||||
if ((my_colour == White && right.y == 7)
|
||||
|| (my_colour == Black && right.y == 0))
|
||||
|
||||
for (auto piece : {Rook, Knigt, Bishop, Queen})
|
||||
ret.push_back(Move{
|
||||
xy.to_index(),
|
||||
right.to_index(),
|
||||
(int8_t) (my_colour | piece)
|
||||
});
|
||||
else
|
||||
ret.push_back(Move{xy.to_index(), right.to_index()});
|
||||
}
|
||||
}
|
||||
|
||||
// -- Capture en passant
|
||||
if (b.en_passant_target != -1) {
|
||||
Coords c = Coords::from_index(b.en_passant_target);
|
||||
int dy = my_colour == Colour::White ? 1 : -1;
|
||||
if (c.y == xy.y + dy && (c.x == xy.x - 1 || c.x == xy.x + 1))
|
||||
ret.push_back(Move{xy.to_index(), c.to_index()});
|
||||
}
|
||||
|
||||
// -- Normal move + promotion
|
||||
bool is_on_starting_rank =
|
||||
my_colour == Colour::White ? xy.y == 1 : xy.y == 6;
|
||||
int max_dy = is_on_starting_rank ? 3 : 2;
|
||||
for (int dy = 1; dy < max_dy; dy++) {
|
||||
int actual_dy = my_colour == Colour::White ? dy : -dy;
|
||||
Coords new_xy{xy.x, xy.y + actual_dy};
|
||||
if (b.squares[new_xy.to_index()] != Piece::None)
|
||||
break;
|
||||
if (new_xy.y == 7 || new_xy.y == 0)
|
||||
for (auto piece : {Rook, Knigt, Bishop, Queen})
|
||||
ret.push_back(Move{
|
||||
xy.to_index(),
|
||||
new_xy.to_index(),
|
||||
.promoting_to = (int8_t) (my_colour | piece)
|
||||
});
|
||||
else
|
||||
ret.push_back(Move{
|
||||
xy.to_index(),
|
||||
new_xy.to_index(),
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
82
cpp/src/model/pieces/piece.cpp
Normal file
82
cpp/src/model/pieces/piece.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include "piece.hpp"
|
||||
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
|
||||
std::vector<Move>
|
||||
keep_only_blocking(const std::vector<Move> candidates, const Board& board) {
|
||||
if (candidates.size() == 0)
|
||||
return {};
|
||||
|
||||
int8_t my_colour = board.colour_at(candidates[0].source_square);
|
||||
std::vector<Move> ret;
|
||||
for (Move move : candidates) {
|
||||
Board board_after_move = board.make_move(move);
|
||||
if (!board_after_move.is_check_for(my_colour))
|
||||
ret.push_back(move);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Move>
|
||||
legal_moves(int8_t p, const Board& b, const Coords xy, bool looking_for_check) {
|
||||
std::vector<Move> ret;
|
||||
int8_t simple_piece = p & 0b00111;
|
||||
switch (simple_piece) {
|
||||
case Piece::Pawn:
|
||||
ret = pawn_moves(b, xy);
|
||||
break;
|
||||
case Piece::Bishop:
|
||||
ret = bishop_moves(b, xy);
|
||||
break;
|
||||
case Piece::Rook:
|
||||
ret = rook_moves(b, xy);
|
||||
break;
|
||||
case Piece::Knigt:
|
||||
ret = knight_moves(b, xy);
|
||||
break;
|
||||
case Piece::Queen:
|
||||
ret = queen_moves(b, xy);
|
||||
break;
|
||||
case Piece::King:
|
||||
ret = king_moves(b, xy);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!looking_for_check)
|
||||
return keep_only_blocking(ret, b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<Move>
|
||||
move_for_position(const Board& board, const Coords source, const Coords dest) {
|
||||
if (!dest.is_within_bounds()
|
||||
|| board.colour_at(source) == board.colour_at(dest))
|
||||
return {};
|
||||
|
||||
return Move{source.to_index(), dest.to_index()};
|
||||
}
|
||||
|
||||
std::vector<Move>
|
||||
look_direction(const Board& board, const Coords xy, int mult_dx, int mult_dy) {
|
||||
std::vector<Move> ret;
|
||||
for (int d = 1; d < 8; d++) {
|
||||
int dx = mult_dx * d;
|
||||
int dy = mult_dy * d;
|
||||
|
||||
Coords target{xy.x + dx, xy.y + dy};
|
||||
std::optional<Move> move = move_for_position(board, xy, target);
|
||||
if (move.has_value()) {
|
||||
ret.push_back(move.value());
|
||||
if (board.squares[target.to_index()] != Piece::None)
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
42
cpp/src/model/pieces/piece.hpp
Normal file
42
cpp/src/model/pieces/piece.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
enum Piece : int8_t {
|
||||
None = 0,
|
||||
Rook = 1,
|
||||
Knigt = 2,
|
||||
Bishop = 3,
|
||||
Queen = 4,
|
||||
King = 5,
|
||||
Pawn = 6,
|
||||
};
|
||||
|
||||
enum Colour : int8_t {
|
||||
White = 8,
|
||||
Black = 16,
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const int8_t& i) {
|
||||
os << std::to_string(i);
|
||||
return os;
|
||||
}
|
||||
|
||||
class Board;
|
||||
struct Coords;
|
||||
struct Move;
|
||||
|
||||
std::vector<Move> legal_moves(int8_t, const Board&, const Coords, bool = false);
|
||||
std::vector<Move> keep_only_blocking(const std::vector<Move>, const Board&);
|
||||
std::optional<Move> move_for_position(const Board&, const Coords, const Coords);
|
||||
std::vector<Move> look_direction(const Board&, const Coords, int, int);
|
||||
|
||||
std::vector<Move> pawn_moves(const Board&, const Coords);
|
||||
std::vector<Move> rook_moves(const Board&, const Coords);
|
||||
std::vector<Move> knight_moves(const Board&, const Coords);
|
||||
std::vector<Move> bishop_moves(const Board&, const Coords);
|
||||
std::vector<Move> queen_moves(const Board&, const Coords);
|
||||
std::vector<Move> king_moves(const Board&, const Coords);
|
35
cpp/src/model/pieces/queen.cpp
Normal file
35
cpp/src/model/pieces/queen.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
#include "piece.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<Move> queen_moves(const Board& b, const Coords xy) {
|
||||
std::vector<Move> ret;
|
||||
auto e = look_direction(b, xy, 1, 0);
|
||||
ret.insert(ret.end(), e.begin(), e.end());
|
||||
|
||||
auto s = look_direction(b, xy, 0, -1);
|
||||
ret.insert(ret.end(), s.begin(), s.end());
|
||||
|
||||
auto w = look_direction(b, xy, -1, 0);
|
||||
ret.insert(ret.end(), w.begin(), w.end());
|
||||
|
||||
auto n = look_direction(b, xy, 0, 1);
|
||||
ret.insert(ret.end(), n.begin(), n.end());
|
||||
|
||||
auto ne = look_direction(b, xy, 1, 1);
|
||||
ret.insert(ret.end(), ne.begin(), ne.end());
|
||||
|
||||
auto se = look_direction(b, xy, 1, -1);
|
||||
ret.insert(ret.end(), se.begin(), se.end());
|
||||
|
||||
auto sw = look_direction(b, xy, -1, -1);
|
||||
ret.insert(ret.end(), sw.begin(), sw.end());
|
||||
|
||||
auto nw = look_direction(b, xy, -1, 1);
|
||||
ret.insert(ret.end(), nw.begin(), nw.end());
|
||||
|
||||
return ret;
|
||||
}
|
23
cpp/src/model/pieces/rook.cpp
Normal file
23
cpp/src/model/pieces/rook.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "../board/board.hpp"
|
||||
#include "../utils/coords.hpp"
|
||||
#include "../utils/move.hpp"
|
||||
#include "piece.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<Move> rook_moves(const Board& b, const Coords xy) {
|
||||
std::vector<Move> ret;
|
||||
auto e = look_direction(b, xy, 1, 0);
|
||||
ret.insert(ret.end(), e.begin(), e.end());
|
||||
|
||||
auto s = look_direction(b, xy, 0, -1);
|
||||
ret.insert(ret.end(), s.begin(), s.end());
|
||||
|
||||
auto w = look_direction(b, xy, -1, 0);
|
||||
ret.insert(ret.end(), w.begin(), w.end());
|
||||
|
||||
auto n = look_direction(b, xy, 0, 1);
|
||||
ret.insert(ret.end(), n.begin(), n.end());
|
||||
|
||||
return ret;
|
||||
}
|
Reference in New Issue
Block a user