Skip to content

Commit

Permalink
Expose some chess-specific information in pyspiel.
Browse files Browse the repository at this point in the history
Ref: #989
PiperOrigin-RevId: 502352342
Change-Id: If95b2c713a4a648742f963780d45230d32034da2
  • Loading branch information
lanctot committed Jan 16, 2023
1 parent 48d64e7 commit 453ab85
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
1 change: 1 addition & 0 deletions open_spiel/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ set(PYTHON_TESTS ${PYTHON_TESTS}
tests/bot_test.py
tests/game_transforms_test.py
tests/games_bridge_test.py
tests/games_chess_test.py
tests/games_euchre_test.py
tests/games_gin_rummy_test.py
tests/games_sim_test.py
Expand Down
52 changes: 52 additions & 0 deletions open_spiel/python/pybind11/games_chess.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,66 @@
#include "open_spiel/python/pybind11/games_chess.h"

#include "open_spiel/games/chess.h"
#include "open_spiel/games/chess/chess_board.h"
#include "open_spiel/games/chess/chess_common.h"
#include "open_spiel/spiel.h"
#include "open_spiel/python/pybind11/pybind11.h"

namespace py = ::pybind11;
using open_spiel::State;
using open_spiel::chess::ChessState;
using open_spiel::chess::ChessBoard;
using open_spiel::chess::Color;
using open_spiel::chess::Square;
using open_spiel::chess::Piece;
using open_spiel::chess::PieceType;
using open_spiel::chess::Move;

PYBIND11_SMART_HOLDER_TYPE_CASTERS(ChessBoard);
PYBIND11_SMART_HOLDER_TYPE_CASTERS(ChessState);

void open_spiel::init_pyspiel_games_chess(py::module& m) {
py::module_ chess = m.def_submodule("chess");

py::enum_<Color>(chess, "Color")
.value("BLACK", Color::kBlack)
.value("WHITE", Color::kWhite)
.value("EMPTY", Color::kEmpty)
.export_values();

py::enum_<PieceType>(chess, "PieceType")
.value("EMPTY", PieceType::kEmpty)
.value("KING", PieceType::kKing)
.value("QUEEN", PieceType::kQueen)
.value("ROOK", PieceType::kRook)
.value("BISHOP", PieceType::kBishop)
.value("KNIGHT", PieceType::kKnight)
.value("PAWN", PieceType::kPawn)
.export_values();

py::class_<Piece>(chess, "Piece")
.def(py::init<>())
.def_readonly("color", &Piece::color)
.def_readonly("type", &Piece::type);

py::class_<Square>(chess, "Square")
.def(py::init<>())
.def_readonly("x", &Square::x)
.def_readonly("y", &Square::y);

py::class_<Move>(chess, "Move")
.def(py::init<>())
.def_readonly("from_square", &Move::from) // "from" is a python keyword
.def_readonly("to_square", &Move::to)
.def_readonly("piece", &Move::piece)
.def_readonly("promotion_type", &Move::promotion_type)
.def_readonly("is_castling", &Move::is_castling);

py::classh<ChessBoard>(chess, "ChessBoard")
.def("has_legal_moves", &ChessBoard::HasLegalMoves);

py::classh<ChessState, State>(m, "ChessState")
.def("board", py::overload_cast<>(&ChessState::Board))
.def("debug_string", &ChessState::DebugString)
.def("parse_move_to_action", &ChessState::ParseMoveToAction)
// Pickle support
Expand All @@ -38,4 +87,7 @@ void open_spiel::init_pyspiel_games_chess(py::module& m) {
game_and_state = DeserializeGameAndState(data);
return dynamic_cast<ChessState*>(game_and_state.second.release());
}));

// action_to_move(action: int, board: ChessBoard)
chess.def("action_to_move", &chess::ActionToMove);
}
50 changes: 50 additions & 0 deletions open_spiel/python/tests/games_chess_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright 2019 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Tests for the game-specific functions for chess."""


from absl.testing import absltest
import numpy as np

import pyspiel
chess = pyspiel.chess


class GamesChessTest(absltest.TestCase):

def test_bindings_sim(self):
game = pyspiel.load_game("chess")
state = game.new_initial_state()
while not state.is_terminal():
print(state)
player = state.current_player()
legal_actions = state.legal_actions()
board = state.board()
for action in legal_actions:
action_str = state.action_to_string(player, action)
move = chess.action_to_move(action, board)
move_from = move.from_square
move_to = move.to_square
decoded_from_to = (f"({move_from.x} {move_from.y}) -> " +
f"({move_to.x} {move_to.y})")
print(f"Legal action: {action_str} decoded from to {decoded_from_to}")
action = np.random.choice(legal_actions)
state.apply_action(action)
self.assertTrue(state.is_terminal())


if __name__ == "__main__":
np.random.seed(87375711)
absltest.main()

0 comments on commit 453ab85

Please sign in to comment.