Commit dd617cae authored by Emil's avatar Emil

Added masks for simple moves in legalmoves

parent 07da586e
......@@ -96,6 +96,8 @@ namespace std
}
};
} // END namespace std
......@@ -105,11 +107,18 @@ namespace gameengine // resume namespace gameengine
using BitBoard = std::array<BitPieces, 2>;
using BitPosSet = std::unordered_set<BitPos>;
struct Move{
BitPieces start_pos;
std::vector<BitPieces> moves;
};
Move(BitPieces start_pos_in, std::vector<BitPieces> Valid_moves_in, BitPieces Cap_piecs_in): start_pos(start_pos_in), Valid_moves(Valid_moves_in), Cap_piecs(Cap_piecs_in) {}
Move(): start_pos(BitPieces{}), Valid_moves(std::vector<BitPieces>{}), Cap_piecs(BitPieces{}) {}
bool operator==(const Move& lhs)const{
return this->Cap_piecs==lhs.Cap_piecs and this->Valid_moves==lhs.Valid_moves and this->start_pos==lhs.start_pos;
}
BitPieces start_pos;
std::vector<BitPieces> Valid_moves;
BitPieces Cap_piecs;
};
using Moves = std::unordered_set<Move>;
enum class PlayerId : size_t { One = 0UL, Two = 1UL };
using PlayerIdOpt = std::optional<PlayerId>;
......@@ -118,5 +127,13 @@ namespace gameengine // resume namespace gameengine
enum class PlayerType { Human, AI };
using PlayerTypeOpt = std::optional<PlayerType>;
} // namespace gameengine
namespace std {
template <>
struct hash<gameengine::Move> {
size_t operator()(const gameengine::Move& move) const
{
return std::hash<gameengine::BitPieces>{}(move.start_pos) ^ std::hash<gameengine::BitPieces>{}(move.Cap_piecs) ^std::hash<gameengine::BitPieces>{}(move.Valid_moves.back());
}
};
}
#endif // BASIC_TYPES_H
......@@ -23,7 +23,7 @@ namespace gameengine
= 0;
/*! Query the best move after decided by the player */
virtual BitPos bestMove() const = 0;
virtual Move bestMove() const = 0;
/*! Query the player type {humen or A.I.} */
virtual PlayerType type() const = 0;
......@@ -43,7 +43,7 @@ namespace gameengine
/*! Specialication of the best move method for humans
* No-one needs to know what I think is the best move */
BitPos bestMove() const override final { return {}; }
Move bestMove() const override final { return {}; }
/*! Specialication of the type function returning the player type */
PlayerType type() const override final { return PlayerType::Human; }
......
......@@ -20,11 +20,11 @@ namespace gameengine
public:
void think(const BitBoard& board, const PlayerId& player_id,
const std::chrono::seconds& max_time);
BitPos bestMove() const;
Move bestMove() const;
private:
mutable BitPos m_best_move;
mutable Move m_best_move;
std::random_device m_rd;
std::mt19937 m_engine;
};
......
......@@ -36,7 +36,7 @@ namespace gameengine::utility
* \param[in] board The board
* \param[in] player_id Querying player's id
* \return Set of legal moves */
BitPosSet legalMoves(const BitBoard& board, const PlayerId& player_id);
Moves legalMoves(const BitBoard& board, const PlayerId& player_id);
/*! Query wherther a move for a given player is legal for a given bitboard
* \param[in] board The board
......
......@@ -27,11 +27,11 @@ namespace gameengine
m_best_move = *b_iter;
}
BitPos MonkeyAI::bestMove() const
Move MonkeyAI::bestMove() const
{
const auto best_move = BitPos(m_best_move.value());
m_best_move = BitPos::invalid();
const auto best_move = Move(m_best_move);
m_best_move = {};
return best_move;
}
......
......@@ -31,23 +31,32 @@ namespace gameengine::utility
return occupied(occupiedPositions(board),board_pos);
}
const BitPieces MaskE = BitPieces("00000001"
"00000001"
"00000001"
"00000001"
"00000001"
"00000001"
"00000001"
"00000001");
const BitPieces MaskW = BitPieces("10000000"
"10000000"
"10000000"
"10000000"
"10000000"
"10000000"
"10000000"
"10000000");
const BitPieces MaskWest = BitPieces("11111110"
"11111110"
"11111110"
"11111110"
"11111110"
"11111110"
"11111110"
"11111110");
const BitPieces MaskEast = BitPieces("01111111"
"01111111"
"01111111"
"01111111"
"01111111"
"01111111"
"01111111"
"01111111");
const BitPieces MaskCheck = BitPieces("00000000"
"00000000"
"00000000"
"00000000"
"00000000"
"00000000"
"00000000"
"00000001");
BitPos nextPosition(const BitPos& board_pos, const MoveDirection& dir)
{
......@@ -67,19 +76,19 @@ namespace gameengine::utility
switch (dir) {
case MoveDirection::N: //new position when moving North
return gameengine::BitPos(board_pos.value()+8);
return BitPos(board_pos.value()+8);
case MoveDirection::S: //new position when moving South
return gameengine::BitPos(board_pos.value()-8);
return BitPos(board_pos.value()-8);
case MoveDirection::E: //new position when moving East
return gameengine::BitPos(board_pos.value()+1);
return BitPos(board_pos.value()+1);
case MoveDirection::W: //new position when moving West
return gameengine::BitPos(board_pos.value()-1);
return BitPos(board_pos.value()-1);
case MoveDirection::SE: //new position when moving South_East
return gameengine::BitPos(board_pos.value()-7);
return BitPos(board_pos.value()-7);
case MoveDirection::SW: //new position when moving South-West
return gameengine::BitPos(board_pos.value()-9);
return BitPos(board_pos.value()-9);
case MoveDirection::NE: //new position when moving North-East
return gameengine::BitPos(board_pos.value()+9);
return BitPos(board_pos.value()+9);
case MoveDirection::NW: //new position when moving North-West
return gameengine::BitPos(board_pos.value()+7);
}
......@@ -89,24 +98,62 @@ namespace gameengine::utility
}
BitPosSet legalMoves(const BitBoard& board, const PlayerId& player_id)
Moves legalMoves(const BitBoard& board, const PlayerId& player_id)
{
//BitPieces board_player = occupiedPosition(board,player_id);
BitPosSet Legal_pos;
for (int Nstep = 0; Nstep < 63; Nstep++)
{
if (occupied(occupiedPosition(board,player_id),BitPos(Nstep)) == true){
if (isLegalMove(board,player_id,BitPos(Nstep),nextPosition(BitPos(Nstep),MoveDirection::NE)) == true)
{
Legal_pos.insert(nextPosition(BitPos(Nstep),MoveDirection::NE));
Moves new_moves{};
BitPieces East;
BitPieces West;
BitPieces mask = MaskCheck;
BitPieces unoccupied = ~occupiedPositions(board);
// Masks for player One (simple moves)
if (player_id == PlayerId::One) {
East = (unoccupied & MaskEast)>>9 & occupiedPosition(board,player_id);
West = (unoccupied & MaskWest)>>7 & occupiedPosition(board,player_id);
}
// Masks for player Two (simple moves)
else {
East = (unoccupied & MaskEast)<<7 & occupiedPosition(board,player_id);
West = (unoccupied & MaskWest)<<9 & occupiedPosition(board,player_id);
}
//oder all legal moves for player 1
if (player_id == PlayerId::One){
while (!mask.none()) {
BitPieces EastMove = East & mask;
BitPieces WestMove = West & mask;
if (EastMove.none()||WestMove.none()){
mask<<=1;
}
if (!EastMove.none()) {
new_moves.emplace(Move{BitPieces(EastMove), std::vector<BitPieces>{EastMove<<9},{}});
mask<<=1;
}
else {
new_moves.emplace(Move{BitPieces(WestMove), std::vector<BitPieces>{WestMove<<7},{}});
mask<<=1;
}
}
}
//oder all legal moves for player 2
else {
while (!mask.none()) {
BitPieces EastMove = East & mask;
BitPieces WestMove = West & mask;
if (EastMove.none()||WestMove.none()){
mask<<=1;
}
if (isLegalMove(board,player_id,BitPos(Nstep),nextPosition(BitPos(Nstep),MoveDirection::NW)) == true)
{
Legal_pos.insert(nextPosition(BitPos(Nstep),MoveDirection::NW));
if (!EastMove.none()) {
new_moves.emplace(Move{BitPieces(EastMove), std::vector<BitPieces>{EastMove>>7},{}});
mask<<=1;
}
}
else {
new_moves.emplace(Move{BitPieces(WestMove), std::vector<BitPieces>{WestMove>>9},{}});
mask<<=1;
}
}
}
return {Legal_pos};
return new_moves;
}
bool isLegalMove(const BitBoard& board, const PlayerId& player_id,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment