Skip to content

Commit

Permalink
REMOVE: vshogi::Game::{get_move_at, get_sfen_at}()
Browse files Browse the repository at this point in the history
  • Loading branch information
ctgk committed Oct 7, 2024
1 parent 5ce1d37 commit 1d78d5d
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 106 deletions.
83 changes: 24 additions & 59 deletions cpp/include/vshogi/common/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,10 @@ class Game

private:
StateType m_current_state;

std::vector<std::uint64_t> m_zobrist_hash_list;
std::vector<MoveType> m_move_list;
ResultEnum m_result;
std::uint64_t m_zobrist_hash;
const std::string m_initial_sfen_without_ply;
std::vector<ZobristHashType> m_hash_list;

public:
Game() : Game(StateType())
Expand Down Expand Up @@ -113,27 +111,13 @@ class Game
{
if (include_move_count)
return m_current_state.to_sfen() + " "
+ std::to_string(m_move_list.size() + 1);
+ std::to_string(m_hash_list.size() + 1);
else
return m_current_state.to_sfen();
}
std::size_t record_length() const
{
return m_move_list.size();
}
MoveType get_move_at(const std::size_t n) const
{
return m_move_list[n];
}
std::string
get_sfen_at(const std::size_t n, const bool include_move_count = true) const
{
auto s = StateType(m_initial_sfen_without_ply);
for (std::size_t ii = 0; ii < n; ++ii)
s.apply(m_move_list[ii]);
if (include_move_count)
return s.to_sfen() + ' ' + std::to_string(n + 1);
return s.to_sfen();
return m_hash_list.size();
}

/**
Expand Down Expand Up @@ -181,11 +165,10 @@ class Game
{
auto out = Game(
m_current_state,
m_zobrist_hash_list,
m_move_list,
m_result,
m_zobrist_hash,
m_initial_sfen_without_ply);
m_initial_sfen_without_ply,
m_hash_list);
out.apply_dfpn(move);
return out;
}
Expand Down Expand Up @@ -223,10 +206,8 @@ class Game
}
void clear_records_for_dfpn()
{
m_zobrist_hash_list.clear();
m_move_list.clear();
m_zobrist_hash_list.emplace_back(
m_current_state.get_board().zobrist_hash());
m_hash_list.clear();
m_hash_list.emplace_back(m_current_state.get_board().zobrist_hash());
}
void to_feature_map(float* const data) const
{
Expand Down Expand Up @@ -264,25 +245,22 @@ class Game

protected:
Game(const StateType& s)
: m_current_state(s), m_zobrist_hash_list(), m_move_list(),
m_result(ONGOING), m_zobrist_hash(m_current_state.zobrist_hash()),
m_initial_sfen_without_ply(m_current_state.to_sfen())
: m_current_state(s), m_result(ONGOING),
m_zobrist_hash(m_current_state.zobrist_hash()),
m_initial_sfen_without_ply(m_current_state.to_sfen()), m_hash_list{}
{
m_zobrist_hash_list.reserve(128);
m_move_list.reserve(128);
m_hash_list.reserve(256);
update_result();
}
Game(
const StateType& s,
const std::vector<uint64_t>& zobrist_hash_list,
const std::vector<MoveType>& move_list,
const ResultEnum& result,
const uint64_t& zobrist_hash,
const std::string& initial_sfen_without_ply)
: m_current_state(s), m_zobrist_hash_list(zobrist_hash_list),
m_move_list(move_list), m_result(result),
m_zobrist_hash(zobrist_hash),
m_initial_sfen_without_ply(initial_sfen_without_ply)
const std::string& initial_sfen_without_ply,
const std::vector<ZobristHashType>& hash_list)
: m_current_state(s), m_result(result), m_zobrist_hash(zobrist_hash),
m_initial_sfen_without_ply(initial_sfen_without_ply),
m_hash_list(hash_list)
{
}
static uint num_pieces(const StateType& s, const ColorEnum& c)
Expand Down Expand Up @@ -320,16 +298,13 @@ class Game
protected:
void add_record_and_update_state(const MoveType& move)
{
m_zobrist_hash_list.emplace_back(m_zobrist_hash);
m_move_list.emplace_back(move);
m_hash_list.emplace_back(m_zobrist_hash);
m_current_state.apply(move, &m_zobrist_hash);
}
void add_record_and_update_state_for_dfpn(const MoveType& move)
{
m_move_list.emplace_back(move);
m_current_state.apply(move, &m_zobrist_hash);
m_zobrist_hash_list.emplace_back(
m_current_state.get_board().zobrist_hash());
m_hash_list.emplace_back(m_current_state.get_board().zobrist_hash());
}

protected:
Expand All @@ -354,7 +329,7 @@ class Game
const auto turn = get_turn();
if (LegalMoveGenerator<Config>(m_current_state).is_end())
m_result = (turn == BLACK) ? WHITE_WIN : BLACK_WIN;
if (is_duplicate_at_least_once())
if (is_repetitions(1u))
m_result = DRAW;
if (can_declare_win_by_king_enter())
m_result = (turn == BLACK) ? BLACK_WIN : WHITE_WIN;
Expand All @@ -365,34 +340,24 @@ class Game
const auto turn = get_turn();
if (LegalMoveGenerator<Config>(m_current_state).is_end())
m_result = (turn == BLACK) ? WHITE_WIN : BLACK_WIN;
if (is_duplicate_at_least_once())
if (is_repetitions(1u))
m_result = DRAW;
if (can_declare_win_by_king_enter())
m_result = (turn == BLACK) ? BLACK_WIN : WHITE_WIN;
}
bool is_repetitions() const
bool is_repetitions(
const uint max_repetitions_inclusive = max_acceptable_repetitions) const
{
uint num = 1u;
const int n = static_cast<int>(m_move_list.size());
const int n = static_cast<int>(m_hash_list.size());
for (int ii = n - 4; ii >= 0; ii -= 2) {
const uint index = static_cast<uint>(ii);
num += (m_zobrist_hash == m_zobrist_hash_list[index]);
num += (m_zobrist_hash == m_hash_list[index]);
if (num > max_acceptable_repetitions)
return true;
}
return false;
}
bool is_duplicate_at_least_once() const
{
const int n = static_cast<int>(m_move_list.size());
for (int ii = n - 4; ii >= 0; ii -= 2) {
const uint index = static_cast<uint>(ii);
if (m_zobrist_hash_list[static_cast<uint>(n)]
== m_zobrist_hash_list[index])
return true;
}
return false;
}
bool can_declare_win_by_king_enter() const
{
// http://www2.computer-shogi.org/wcsc17/rule_e.html
Expand Down
1 change: 1 addition & 0 deletions cpp/include/vshogi/common/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace vshogi
{

using uint = unsigned int;
using ZobristHashType = std::uint64_t;
static std::random_device seed_gen;
static std::default_random_engine random_engine(seed_gen());
static std::uniform_real_distribution<float>
Expand Down
15 changes: 6 additions & 9 deletions cpp/include/vshogi/variants/animal_shogi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,7 @@ inline animal_shogi::Game&
animal_shogi::Game::apply(const animal_shogi::Move& move)
{
const auto illegal = !is_legal(move);
m_zobrist_hash_list.emplace_back(m_zobrist_hash);
m_move_list.emplace_back(move);
m_hash_list.emplace_back(m_zobrist_hash);
if (!move.is_drop()) {
const auto moving = get_board()[move.source_square()];
const auto captured = get_board()[move.destination()];
Expand All @@ -508,8 +507,7 @@ template <>
inline animal_shogi::Game&
animal_shogi::Game::apply_nocheck(const animal_shogi::Move& move)
{
m_zobrist_hash_list.emplace_back(m_zobrist_hash);
m_move_list.emplace_back(move);
m_hash_list.emplace_back(m_zobrist_hash);
if (!move.is_drop()) {
const auto moving = get_board()[move.source_square()];
const auto captured = get_board()[move.destination()];
Expand All @@ -524,12 +522,11 @@ animal_shogi::Game::apply_nocheck(const animal_shogi::Move& move)

template <>
inline animal_shogi::Game::Game(const animal_shogi::State& s)
: m_current_state(s), m_zobrist_hash_list(), m_move_list(),
m_result(ONGOING), m_zobrist_hash(m_current_state.zobrist_hash()),
m_initial_sfen_without_ply(m_current_state.to_sfen())
: m_current_state(s), m_result(ONGOING),
m_zobrist_hash(m_current_state.zobrist_hash()),
m_initial_sfen_without_ply(m_current_state.to_sfen()), m_hash_list()
{
m_zobrist_hash_list.reserve(128);
m_move_list.reserve(128);
m_hash_list.reserve(128);
update_result();
}

Expand Down
2 changes: 0 additions & 2 deletions cpp/python/vshogi_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,6 @@ inline void export_game(pybind11::module& m)
.def("hflip", &Game::hflip)
.def("apply", [](Game& self, const Move& m) { return self.apply(m); })
.def("resign", [](Game& self) { return self.resign(); })
.def("get_move_at", &Game::get_move_at)
.def("get_sfen_at", &Game::get_sfen_at)
.def_static("ranks", []() { return &Game::num_ranks; })
.def_static("files", []() { return &Game::num_files; })
.def_static("feature_channels", &Game::feature_channels)
Expand Down
20 changes: 0 additions & 20 deletions cpp/tests/test_vshogi/test_animal_shogi/test_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,6 @@ TEST(animal_shogi_game, to_sfen)
}
}

TEST(animal_shogi_game, get_sfen_at)
{
{
const auto actual = Game().apply(Move(SQ_B2, SQ_B3)).get_sfen_at(0);
STRCMP_EQUAL("gle/1c1/1C1/ELG b - 1", actual.c_str());
}
{
const auto actual
= Game().apply(Move(SQ_B2, SQ_B3)).get_sfen_at(0, false);
STRCMP_EQUAL("gle/1c1/1C1/ELG b -", actual.c_str());
}
{
const auto actual = Game()
.apply(Move(SQ_B2, SQ_B3))
.apply(Move(SQ_B2, SQ_B1))
.get_sfen_at(1);
STRCMP_EQUAL("gle/1C1/3/ELG w C 2", actual.c_str());
}
}

TEST(animal_shogi_game, get_legal_moves)
{
{
Expand Down
2 changes: 1 addition & 1 deletion cpp/tests/test_vshogi/test_engine/test_dfpn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ TEST(dfpn, no_mate_1)
// Black: GIx2
auto searcher = Searcher();
searcher.set_game(Game("2k2/5/1+P3/5/5 b 2S"));
searcher.explore(700);
searcher.explore(1000);
CHECK_TRUE(searcher.found_conclusion());
CHECK_FALSE(searcher.found_mate());
CHECK_TRUE(searcher.found_no_mate());
Expand Down
11 changes: 0 additions & 11 deletions cpp/tests/test_vshogi/test_minishogi/test_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,15 +443,4 @@ TEST(minishogi_game, result)
}
}

TEST(minishogi_game, get_sfen_move_at)
{
{
const auto game = Game().apply(Move(SQ_3D, SQ_4E));
CHECK_TRUE(Move(SQ_3D, SQ_4E) == game.get_move_at(0));
STRCMP_EQUAL("rbsgk/4p/5/P4/KGSBR b - 1", game.get_sfen_at(0).c_str());
STRCMP_EQUAL(
"rbsgk/4p/5/P4/KGSBR b -", game.get_sfen_at(0, false).c_str());
}
}

} // namespace test_vshogi::test_minishogi
13 changes: 9 additions & 4 deletions python/vshogi/_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def __init__(self, sfen: tp.Optional[str] = None) -> None:
self._game = sfen
else:
self._game = cls_(sfen)
self._move_list: tp.List[Move] = []
self._sfen_list: tp.List[str] = []

@_ClassProperty
def ranks(self) -> int:
Expand Down Expand Up @@ -281,6 +283,8 @@ def apply(self, move=None, *arg, **kwargs) -> 'Game':
Game(sfen="r2gk/2bsp/5/PGBS1/K3R w - 6")
"""
move = self._get_move(move, *arg, **kwargs)
self._move_list.append(move)
self._sfen_list.append(self.to_sfen(False))
self._game.apply(move)
return self

Expand Down Expand Up @@ -364,9 +368,7 @@ def get_move_at(self, n: int):
>>> game.get_move_at(-1)
Move(dst=SQ_2B, src=SQ_3A)
"""
if n < 0:
n = self.record_length + n
return self._game.get_move_at(n)
return self._move_list[n]

def get_sfen_at(self, n: int, include_move_count: bool = True) -> str:
"""Return n-th game state in SFEN, where n starts from 0.
Expand Down Expand Up @@ -398,7 +400,10 @@ def get_sfen_at(self, n: int, include_move_count: bool = True) -> str:
"""
if n < 0:
n = self.record_length + n
return self._game.get_sfen_at(n, include_move_count)
if include_move_count:
return self._sfen_list[n] + f' {n + 1}'
else:
return self._sfen_list[n]

def dump_records(
self,
Expand Down

0 comments on commit 1d78d5d

Please sign in to comment.