<commit_before>#pragma once
#include <array>
#include "piece.hpp"
#include "game_state.hpp"
#include "action_result.hpp"
#include "util.hpp"

namespace shogi
{

	class game
	{
	public:

		explicit game(bool initial_turn = false)
		{
			reset(initial_turn);
		}

		void reset(bool initial_turn = false)
		{
			turn_ = initial_turn;

			state_.table[0][0] = piece(piece_type::kyosha, true);
			state_.table[0][1] = piece(piece_type::keima, true);
			state_.table[0][2] = piece(piece_type::ginsho, true);
			state_.table[0][3] = piece(piece_type::kinsho, true);
			state_.table[0][4] = piece(piece_type::ousho, true);
			state_.table[0][5] = piece(piece_type::kinsho, true);
			state_.table[0][6] = piece(piece_type::ginsho, true);
			state_.table[0][7] = piece(piece_type::keima, true);
			state_.table[0][8] = piece(piece_type::kyosha, true);
			state_.table[1][1] = piece(piece_type::hisha, true);
			state_.table[1][7] = piece(piece_type::kaku, true);
			state_.table[2][0] = piece(piece_type::fuhyo, true);
			state_.table[2][1] = piece(piece_type::fuhyo, true);
			state_.table[2][2] = piece(piece_type::fuhyo, true);
			state_.table[2][3] = piece(piece_type::fuhyo, true);
			state_.table[2][4] = piece(piece_type::fuhyo, true);
			state_.table[2][5] = piece(piece_type::fuhyo, true);
			state_.table[2][6] = piece(piece_type::fuhyo, true);
			state_.table[2][7] = piece(piece_type::fuhyo, true);
			state_.table[2][8] = piece(piece_type::fuhyo, true);

			state_.table[6][0] = piece(piece_type::fuhyo, false);
			state_.table[6][1] = piece(piece_type::fuhyo, false);
			state_.table[6][2] = piece(piece_type::fuhyo, false);
			state_.table[6][3] = piece(piece_type::fuhyo, false);
			state_.table[6][4] = piece(piece_type::fuhyo, false);
			state_.table[6][5] = piece(piece_type::fuhyo, false);
			state_.table[6][6] = piece(piece_type::fuhyo, false);
			state_.table[6][7] = piece(piece_type::fuhyo, false);
			state_.table[6][8] = piece(piece_type::fuhyo, false);
			state_.table[7][1] = piece(piece_type::kaku, false);
			state_.table[7][7] = piece(piece_type::hisha, false);
			state_.table[8][0] = piece(piece_type::kyosha, false);
			state_.table[8][1] = piece(piece_type::keima, false);
			state_.table[8][2] = piece(piece_type::ginsho, false);
			state_.table[8][3] = piece(piece_type::kinsho, false);
			state_.table[8][4] = piece(piece_type::ousho, false);
			state_.table[8][5] = piece(piece_type::kinsho, false);
			state_.table[8][6] = piece(piece_type::ginsho, false);
			state_.table[8][7] = piece(piece_type::keima, false);
			state_.table[8][8] = piece(piece_type::kyosha, false);

			state_count_.clear();

			++state_count_[state_];
		}

		const game_state& state() const
		{
			return state_;
		}

		action_result test_move(int org_row, int org_col, int new_row, int new_col) const
		{
			game_state temp_state = state_;
			return move_impl(temp_state, org_row, org_col, new_row, new_col, false);
		}

		action_result move(int org_row, int org_col, int new_row, int new_col, bool promote)
		{
			game_state temp_state = state_;
			action_result result = move_impl(temp_state, org_row, org_col, new_row, new_col, promote);

			if (result == action_result::succeeded)
			{
				state_ = temp_state;
				++state_count_[state_];
				turn_ = !turn_;
			}

			return result;
		}

		action_result test_put(piece_type type, int row, int col) const
		{
			game_state temp_state = state_;
			return put_impl(temp_state, type, row, col);
		}

		action_result put(piece_type type, int row, int col)
		{
			game_state temp_state = state_;
			action_result result = put_impl(temp_state, type, row, col);

			if (result == action_result::succeeded)
			{
				state_ = temp_state;
				++state_count_[state_];
				turn_ = !turn_;
			}

			return result;
		}

	private:

		action_result move_impl(game_state& state, int org_row, int org_col, int new_row, int new_col, bool promote) const
		{
			BOOST_ASSERT(org_row >= 0 && org_row < 9);
			BOOST_ASSERT(org_col >= 0 && org_col < 9);
			BOOST_ASSERT(new_row >= 0 && new_row < 9);
			BOOST_ASSERT(new_col >= 0 && new_col < 9);

			piece& org_piece = state.table[org_row][org_col];
			piece& new_piece = state.table[new_row][new_col];

			if (org_piece.type() == piece_type::none)
				return action_result::failed;

			if (org_piece.side() != turn_)
				return action_result::failed;

			int dx = new_col - org_col;
			int dy = new_row - org_row;
			if (!is_piece_movable(org_piece, dx, dy))
				return action_result::failed;

			switch (org_piece.type())
			{
			case piece_type::kaku:
			case piece_type::ryuma:
			case piece_type::hisha:
			case piece_type::ryuou:
			case piece_type::kyosha:
			{
				int sign_dx = sign(dx);
				int sign_dy = sign(dy);
				int x = org_col + sign_dx;
				int y = org_row + sign_dy;

				while (x != new_col || y != new_row)
				{
					const piece& p = state.table[y][x];

					if (p.type() != piece_type::none)
						return action_result::failed;

					x += sign_dx;
					y += sign_dy;
				}

				break;
			}
			}

			if (new_piece.type() != piece_type::none)
			{
				if (new_piece.side() == turn_)
					return action_result::failed;

				hand_type& hand = turn_ ? state.hand2 : state.hand1;
				++hand[static_cast<std::size_t>(original(new_piece.type()))];
			}

			new_piece = org_piece;
			org_piece = piece();

			if (!promote)
			{<commit_msg>Implement Win<commit_after>#pragma once
#include <array>
#include "piece.hpp"
#include "game_state.hpp"
#include "action_result.hpp"
#include "util.hpp"

namespace shogi
{

	class game
	{
	public:

		explicit game(bool initial_turn = false)
		{
			reset(initial_turn);
		}

		void reset(bool initial_turn = false)
		{
			turn_ = initial_turn;

			state_.table[0][0] = piece(piece_type::kyosha, true);
			state_.table[0][1] = piece(piece_type::keima, true);
			state_.table[0][2] = piece(piece_type::ginsho, true);
			state_.table[0][3] = piece(piece_type::kinsho, true);
			state_.table[0][4] = piece(piece_type::ousho, true);
			state_.table[0][5] = piece(piece_type::kinsho, true);
			state_.table[0][6] = piece(piece_type::ginsho, true);
			state_.table[0][7] = piece(piece_type::keima, true);
			state_.table[0][8] = piece(piece_type::kyosha, true);
			state_.table[1][1] = piece(piece_type::hisha, true);
			state_.table[1][7] = piece(piece_type::kaku, true);
			state_.table[2][0] = piece(piece_type::fuhyo, true);
			state_.table[2][1] = piece(piece_type::fuhyo, true);
			state_.table[2][2] = piece(piece_type::fuhyo, true);
			state_.table[2][3] = piece(piece_type::fuhyo, true);
			state_.table[2][4] = piece(piece_type::fuhyo, true);
			state_.table[2][5] = piece(piece_type::fuhyo, true);
			state_.table[2][6] = piece(piece_type::fuhyo, true);
			state_.table[2][7] = piece(piece_type::fuhyo, true);
			state_.table[2][8] = piece(piece_type::fuhyo, true);

			state_.table[6][0] = piece(piece_type::fuhyo, false);
			state_.table[6][1] = piece(piece_type::fuhyo, false);
			state_.table[6][2] = piece(piece_type::fuhyo, false);
			state_.table[6][3] = piece(piece_type::fuhyo, false);
			state_.table[6][4] = piece(piece_type::fuhyo, false);
			state_.table[6][5] = piece(piece_type::fuhyo, false);
			state_.table[6][6] = piece(piece_type::fuhyo, false);
			state_.table[6][7] = piece(piece_type::fuhyo, false);
			state_.table[6][8] = piece(piece_type::fuhyo, false);
			state_.table[7][1] = piece(piece_type::kaku, false);
			state_.table[7][7] = piece(piece_type::hisha, false);
			state_.table[8][0] = piece(piece_type::kyosha, false);
			state_.table[8][1] = piece(piece_type::keima, false);
			state_.table[8][2] = piece(piece_type::ginsho, false);
			state_.table[8][3] = piece(piece_type::kinsho, false);
			state_.table[8][4] = piece(piece_type::ousho, false);
			state_.table[8][5] = piece(piece_type::kinsho, false);
			state_.table[8][6] = piece(piece_type::ginsho, false);
			state_.table[8][7] = piece(piece_type::keima, false);
			state_.table[8][8] = piece(piece_type::kyosha, false);

			state_count_.clear();

			++state_count_[state_];
		}

		const game_state& state() const
		{
			return state_;
		}

		action_result test_move(int org_row, int org_col, int new_row, int new_col) const
		{
			game_state temp_state = state_;
			return move_impl(temp_state, org_row, org_col, new_row, new_col, false);
		}

		action_result move(int org_row, int org_col, int new_row, int new_col, bool promote)
		{
			game_state temp_state = state_;
			action_result result = move_impl(temp_state, org_row, org_col, new_row, new_col, promote);

			if (result == action_result::succeeded)
			{
				state_ = temp_state;
				++state_count_[state_];
				turn_ = !turn_;
			}

			return result;
		}

		action_result test_put(piece_type type, int row, int col) const
		{
			game_state temp_state = state_;
			return put_impl(temp_state, type, row, col);
		}

		action_result put(piece_type type, int row, int col)
		{
			game_state temp_state = state_;
			action_result result = put_impl(temp_state, type, row, col);

			if (result == action_result::succeeded)
			{
				state_ = temp_state;
				++state_count_[state_];
				turn_ = !turn_;
			}

			return result;
		}

	private:

		action_result move_impl(game_state& state, int org_row, int org_col, int new_row, int new_col, bool promote) const
		{
			BOOST_ASSERT(org_row >= 0 && org_row < 9);
			BOOST_ASSERT(org_col >= 0 && org_col < 9);
			BOOST_ASSERT(new_row >= 0 && new_row < 9);
			BOOST_ASSERT(new_col >= 0 && new_col < 9);

			piece& org_piece = state.table[org_row][org_col];
			piece& new_piece = state.table[new_row][new_col];

			if (org_piece.type() == piece_type::none)
				return action_result::failed;

			if (org_piece.side() != turn_)
				return action_result::failed;

			int dx = new_col - org_col;
			int dy = new_row - org_row;
			if (!is_piece_movable(org_piece, dx, dy))
				return action_result::failed;

			switch (org_piece.type())
			{
			case piece_type::kaku:
			case piece_type::ryuma:
			case piece_type::hisha:
			case piece_type::ryuou:
			case piece_type::kyosha:
			{
				int sign_dx = sign(dx);
				int sign_dy = sign(dy);
				int x = org_col + sign_dx;
				int y = org_row + sign_dy;

				while (x != new_col || y != new_row)
				{
					const piece& p = state.table[y][x];

					if (p.type() != piece_type::none)
						return action_result::failed;

					x += sign_dx;
					y += sign_dy;
				}

				break;
			}
			}

			if (new_piece.type() != piece_type::none)
			{
				if (new_piece.side() == turn_)
					return action_result::failed;

				if (new_piece.type() == piece_type::ousho)
					return action_result::win;

				hand_type& hand = turn_ ? state.hand2 : state.hand1;
				++hand[static_cast<std::size_t>(original(new_piece.type()))];
			}

			new_piece = org_piece;
			org_piece = piece();

			if (!promote)
			{
{'fraction_non_alphanumeric': 0.16174010039040715, 'fraction_numerical': 0.016731734523145567, 'mean_word_length': 4.230432668935343, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3479010', 'n_tokens_mistral': 4753, 'n_tokens_neox': 4061, 'n_words': 758}