#pragma once
#include "overall_define.h"
#include "util/combinatorics.h"
#include <array>

//=======================================================================================

/* 发牌过程，需要根据规则具体实现 */
template<typename Poker_t>
void deal_all_hand(type::card_t (*holes)[Poker_t::hole_len[Poker_t::num_rounds-1]], type::card_t* board);

template<typename Poker_t>
std::string card_to_string(type::card_t card);

/* 下一个行动的玩家 */
template<typename Poker_t>
int next_player(int survivor_code, int player);

////////////////////////////////////////////////////////////////////////////////////////////////

template<typename Poker>
class GameBase{
public:
    using Poker_t = Poker;
public:
    /* initialize the game description */
    static void init();

    /* free the leduc game description */
    static void free();

protected:
    /* construct the betting sequences */
    static void construct_sequences();

    /* count the number of each type of betting sequences */
    static constexpr std::tuple<int, int, int, int, std::array<int,Poker_t::num_rounds>, std::array<int,Poker_t::num_rounds>, std::array<int,Poker_t::num_rounds>, std::array<int,Poker_t::num_rounds>> count_sequences();

    /* count the number of actions sequence can do */
    static void count_actions();

protected:

    // /* number of sequence per round */
    // inline static int num_sequence_round_[Poker_t::num_rounds]{0};

    // /* number of internal, terminal and total sequences */
    // inline static int num_internal_, num_terminal_, num_total_;

    /* number of sequence parameter  */
    const static std::tuple<int, int, int, int, std::array<int,Poker_t::num_rounds>, std::array<int,Poker_t::num_rounds>, std::array<int,Poker_t::num_rounds>, std::array<int,Poker_t::num_rounds>> num_sequences_;

    /* sequence list of each round */
    inline static int* sequence_list_round_[Poker_t::num_rounds]{nullptr};

    /* number of actions at an internal sequence */
    inline static int * num_actions_;

    /* transition table at an internal sequence */
    inline static int **transition_;
    
    /* round for each internal sequence */
    inline static int * round_;

    /* whose turn for each internal sequence */
    inline static int * whose_turn_; // 对于终端节点剩下谁就是谁，剩下多于一个玩家赋值-1

    /* survive player in each sequence 最多32个玩家*/
    inline static int * survivor_code_;

    // /* how much is won at terminal sequence */
    // inline static type::chip_t * win_amount_;

    /* how much is won at terminal sequence */
    inline static type::chip_t (*pot_)[Poker_t::num_players];

    /* parent of each sequence */
    inline static int * parent_;

    /* the action that resulted in each sequence*/
    inline static type::action_t * action_result_from_;

    /* the action index that resulted in each sequence*/
    inline static int * action_result_from_idx_;

public:
    const static int  num_chance;//  |***
    const static int num_internal;// |***------|
    const static int  num_terminal;//          |-------|
    const static int  num_total; //  |***------|-------|
    const static std::array<int, Poker_t::num_rounds> num_chance_round;
    const static std::array<int, Poker_t::num_rounds> num_internal_round;
    const static std::array<int, Poker_t::num_rounds> num_terminal_round;
    const static std::array<int, Poker_t::num_rounds> num_sequence_round;
    const inline static int * const * const &sequence_list_round = sequence_list_round_;
    const inline static int * const &num_actions = num_actions_;
    const inline static int * const* const &transition = transition_;
    const inline static int * const &round = round_;
    const inline static int * const &whose_turn = whose_turn_;
    const inline static int * const &survivor_code = survivor_code_;
    // const inline static type::chip_t * const &win_amount = win_amount_;
    const inline static type::chip_t (* const &pot)[Poker_t::num_players] = pot_;
    const inline static int * const &parent = parent_;
    const inline static type::action_t * const &action_result_from = action_result_from_;
    const inline static int * const &action_result_from_idx = action_result_from_idx_;
    inline static bool initialized = false;
};

////////////////////////////////////////////////////////////////////////////
// constexpr函数应放在h中实现
template<typename PokerAssist_t>
inline constexpr std::array<int, PokerAssist_t::num_rounds> get_hole_len(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_hole_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    std::array<int, PokerAssist_t::num_rounds> ret{0};
    for(int i = 0; i<PokerAssist_t::num_rounds; ++i){
        ret[i] = PokerAssist_t::deal_hole_round[i] + (i>0? ret[i-1]: 0);
    }
    return ret;
}

template<typename PokerAssist_t>
inline constexpr std::array<int, PokerAssist_t::num_rounds> get_board_len(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_board_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    std::array<int, PokerAssist_t::num_rounds> ret{0};
    for(int i = 0; i<PokerAssist_t::num_rounds; ++i){
        ret[i] = PokerAssist_t::deal_board_round[i] + (i>0? ret[i-1]: 0);
    }
    return ret;
}

template<typename PokerAssist_t>
inline constexpr std::array<int, PokerAssist_t::num_rounds> get_hand_len(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_hand_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    std::array<int, PokerAssist_t::num_rounds> ret{0};
    for(int i = 0; i<PokerAssist_t::num_rounds; ++i){
        ret[i] = PokerAssist_t::deal_board_round[i] + PokerAssist_t::deal_hole_round[i] + (i>0? ret[i-1]: 0);
    }
    return ret;
}

template<typename PokerAssist_t>
inline constexpr int get_deal_combine_len(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_deal_combine_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    int deal_combine_len = 0;
    for(int i = 0; i<PokerAssist_t::num_rounds; ++i){
        deal_combine_len += (PokerAssist_t::deal_hole_round[i]>0? PokerAssist_t::num_players : 0) 
                          + (PokerAssist_t::deal_board_round[i]>0? 1 : 0);
    }
    return deal_combine_len;
}

template<typename PokerAssist_t>
inline constexpr int get_single_deal_combine_len(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_single_deal_combine_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    int single_deal_combine_len = 0;
    for(int i = 0; i<PokerAssist_t::num_rounds; ++i){
        single_deal_combine_len += (PokerAssist_t::deal_hole_round[i]>0? 1 : 0) 
                          + (PokerAssist_t::deal_board_round[i]>0? 1 : 0);
    }
    return single_deal_combine_len;
}

template<typename PokerAssist_t>
inline constexpr auto get_deal_combine(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_deal_combine函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    constexpr int deal_combine_len = get_deal_combine_len<PokerAssist_t>();
    std::array<uint8_t, deal_combine_len> deal_combine{};

    int idx = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        //先发手牌
        if(PokerAssist_t::deal_hole_round[cur_round]>0){
            for(int i = 0; i<PokerAssist_t::num_players; ++i){
                deal_combine[idx++] = PokerAssist_t::deal_hole_round[cur_round];
            }
        }
        //再发公共牌
        if(PokerAssist_t::deal_board_round[cur_round]>0)
            deal_combine[idx++] = PokerAssist_t::deal_board_round[cur_round];
    }

    return deal_combine;
}

template<typename PokerAssist_t>
inline constexpr auto get_single_deal_combine(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_single_deal_combine_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    constexpr int single_deal_combine_len = get_single_deal_combine_len<PokerAssist_t>();
    std::array<uint8_t, single_deal_combine_len> single_deal_combine{};

    int idx = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        //先发手牌
        if(PokerAssist_t::deal_hole_round[cur_round]>0){
            single_deal_combine[idx++] = PokerAssist_t::deal_hole_round[cur_round];
        }
        //再发公共牌
        if(PokerAssist_t::deal_board_round[cur_round]>0)
            single_deal_combine[idx++] = PokerAssist_t::deal_board_round[cur_round];
    }

    return single_deal_combine;
}

template<typename PokerAssist_t>
inline constexpr auto get_deal_combine_begin_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_deal_combine_begin_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> deal_combine_begin_round{};
    
    int dealed_combine = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        deal_combine_begin_round[cur_round] = dealed_combine;
        dealed_combine += (PokerAssist_t::deal_hole_round[cur_round]>0? PokerAssist_t::num_players: 0) 
                        + (PokerAssist_t::deal_board_round[cur_round]>0? 1: 0);
    }

    return deal_combine_begin_round;
}

template<typename PokerAssist_t>
inline constexpr auto get_deal_combine_end_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_deal_combine_end_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> deal_combine_end_round{};
    
    int dealed_combine = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        dealed_combine += (PokerAssist_t::deal_hole_round[cur_round]>0? PokerAssist_t::num_players: 0)
                        + (PokerAssist_t::deal_board_round[cur_round]>0? 1: 0);
        deal_combine_end_round[cur_round] = dealed_combine;
    }

    return deal_combine_end_round;
}

template<typename PokerAssist_t>
inline constexpr auto get_single_deal_combine_begin_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_single_deal_combine_begin_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> single_deal_combine_begin_round{};
    
    int dealed_combine = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        single_deal_combine_begin_round[cur_round] = dealed_combine;
        dealed_combine += (PokerAssist_t::deal_hole_round[cur_round]>0? 1: 0) 
                        + (PokerAssist_t::deal_board_round[cur_round]>0? 1: 0);
    }

    return single_deal_combine_begin_round;
}

template<typename PokerAssist_t>
inline constexpr auto get_single_deal_combine_end_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_single_deal_combine_end_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> single_deal_combine_end_round{};
    
    int dealed_combine = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        dealed_combine += (PokerAssist_t::deal_hole_round[cur_round]>0? 1: 0)
                        + (PokerAssist_t::deal_board_round[cur_round]>0? 1: 0);
        single_deal_combine_end_round[cur_round] = dealed_combine;
    }

    return single_deal_combine_end_round;
}

template<typename PokerAssist_t>
inline constexpr auto get_dealed_card_num_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_dealed_card_num_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> dealed_card_num_round{0};
    
    int dealed_card = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        dealed_card_num_round[cur_round] = dealed_card;
        dealed_card += PokerAssist_t::deal_hole_round[cur_round] * PokerAssist_t::num_players
                     + PokerAssist_t::deal_board_round[cur_round];
    }

    return dealed_card_num_round;
}

template<typename PokerAssist_t>
inline constexpr auto get_single_dealed_card_num_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_single_dealed_card_num_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> single_dealed_card_num_round{0};
    
    int dealed_card = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        single_dealed_card_num_round[cur_round] = dealed_card;
        dealed_card += PokerAssist_t::deal_hole_round[cur_round] 
                     + PokerAssist_t::deal_board_round[cur_round];
    }

    return single_dealed_card_num_round;
}

template<typename PokerAssist_t>
inline constexpr std::array<int, PokerAssist_t::num_rounds> get_deal_combine_num_round() {
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_deal_combine_num_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    constexpr std::array deal_combine = get_deal_combine<PokerAssist_t>();
    constexpr std::array deal_combine_begin_round = get_deal_combine_begin_round<PokerAssist_t>();
    constexpr std::array deal_combine_end_round =  get_deal_combine_end_round<PokerAssist_t>();
    constexpr std::array dealed_card_num_round =  get_dealed_card_num_round<PokerAssist_t>();
    const int deck_len = PokerAssist_t::deck.size();

    std::array<int, PokerAssist_t::num_rounds> deal_combine_num_round{};
    assist::constexpr_for<0, PokerAssist_t::num_rounds, 1>([&](auto i){
        deal_combine_num_round[i] = combinatorics::MULTI_COMB<deck_len - dealed_card_num_round[i], deal_combine, deal_combine_begin_round[i], deal_combine_end_round[i]>::value;
    });
    return deal_combine_num_round;
}

template<typename PokerAssist_t>
inline constexpr std::array<int, PokerAssist_t::num_rounds> get_single_deal_combine_num_round() {
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_single_deal_combine_num_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    constexpr std::array single_deal_combine = get_single_deal_combine<PokerAssist_t>();
    constexpr std::array single_deal_combine_begin_round = get_single_deal_combine_begin_round<PokerAssist_t>();
    constexpr std::array single_deal_combine_end_round =  get_single_deal_combine_end_round<PokerAssist_t>();
    constexpr std::array single_dealed_card_num_round =  get_single_dealed_card_num_round<PokerAssist_t>();
    const int deck_len = PokerAssist_t::deck.size();

    std::array<int, PokerAssist_t::num_rounds> single_deal_combine_num_round{};
    assist::constexpr_for<0, PokerAssist_t::num_rounds, 1>([&](auto i){
        single_deal_combine_num_round[i] = combinatorics::MULTI_COMB<deck_len - single_dealed_card_num_round[i], single_deal_combine, single_deal_combine_begin_round[i], single_deal_combine_end_round[i]>::value;
    });
    return single_deal_combine_num_round;
}
// add
template<typename PokerAssist_t>
inline constexpr int get_opponents_holes_deal_combine_len(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_opponents_holes_deal_combine_len函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    int deal_combine_len = 0;
    for(int i = 0; i<PokerAssist_t::num_rounds; ++i){
        deal_combine_len += (PokerAssist_t::deal_hole_round[i]>0? PokerAssist_t::num_players-1 : 0);
    }
    return deal_combine_len;
}

template<typename PokerAssist_t>
inline constexpr auto get_opponents_holes_deal_combine(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_opponents_holes_deal_combine函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    constexpr int opponents_holes_deal_combine_len = get_opponents_holes_deal_combine_len<PokerAssist_t>();
    std::array<uint8_t, opponents_holes_deal_combine_len> opponents_holes_deal_combine{};

    int idx = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        if(PokerAssist_t::deal_hole_round[cur_round]>0){
            for(int i = 0; i<PokerAssist_t::num_players-1; ++i){
                opponents_holes_deal_combine[idx++] = PokerAssist_t::deal_hole_round[cur_round];
            }
        }
    }

    return opponents_holes_deal_combine;
}
template<typename PokerAssist_t>
inline constexpr auto get_opponents_holes_deal_combine_end_round(){
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_opponents_holes_deal_combine_end_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    
    std::array<int, PokerAssist_t::num_rounds> opponents_holes_deal_combine_end_round{};
    
    int dealed_combine = 0;
    for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
        dealed_combine += (PokerAssist_t::deal_hole_round[cur_round]>0? PokerAssist_t::num_players-1: 0);
        opponents_holes_deal_combine_end_round[cur_round] = dealed_combine;
    }

    return opponents_holes_deal_combine_end_round;
}
template<typename PokerAssist_t>
inline constexpr std::array<int, PokerAssist_t::num_rounds> get_opponents_holes_after_single_deal_combine_num_round() {
    static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_opponents_holes_after_single_deal_combine_num_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
    constexpr std::array opponents_holes_deal_combine = get_opponents_holes_deal_combine<PokerAssist_t>();
    constexpr std::array opponents_holes_deal_combine_end_round =  get_opponents_holes_deal_combine_end_round<PokerAssist_t>();
    constexpr std::array hand_len = get_hand_len<PokerAssist_t>();
    const int deck_len = PokerAssist_t::deck.size();

    std::array<int, PokerAssist_t::num_rounds> opponents_holes_after_single_deal_combine_num_round{};
    assist::constexpr_for<0, PokerAssist_t::num_rounds, 1>([&](auto i){
        opponents_holes_after_single_deal_combine_num_round[i] = combinatorics::MULTI_COMB<deck_len - hand_len[i], opponents_holes_deal_combine, 0, opponents_holes_deal_combine_end_round[i]>::value;
    });
    return opponents_holes_after_single_deal_combine_num_round;
}

// template<typename PokerAssist_t>
// inline constexpr std::array<std::array<uint8_t, MAX_ROUNDS>, PokerAssist_t::num_rounds*(PokerAssist_t::num_rounds+1)/2> get_isomorphism_configs() {
//     static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_isomorphism_configs函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
//     std::array<std::array<uint8_t, MAX_ROUNDS>, PokerAssist_t::num_rounds*(PokerAssist_t::num_rounds+1)/2> isomorphism_configs;

//     for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
//         uint8_t sum_hole = 0;
//         uint8_t sum_board = 0;

//         for(int recall_round = 0; recall_round <= cur_round; ++recall_round){
//             int id_1d = cur_round * (cur_round+1)/2 + recall_round;

//             sum_hole += PokerAssist_t::deal_hole_round[recall_round];
//             sum_board += PokerAssist_t::deal_board_round[recall_round];

//             //hole与board的发牌分别计数，以便后面拼接起来
//             uint8_t temp_chole[MAX_ROUNDS]{0};
//             uint8_t temp_cboard[MAX_ROUNDS]{0};
//             int chole_len = 0;
//             int cboard_len = 0;

//             // 计数
//             if (sum_hole > 0) {
//                 temp_chole[chole_len] = sum_hole;
//                 chole_len += 1;
//             }
//             if (sum_board > 0) {
//                 temp_cboard[cboard_len] = sum_board;
//                 cboard_len += 1;
//             }

//             for (int i = recall_round + 1; i <= cur_round; ++i){
//                 if (PokerAssist_t::deal_hole_round[i] > 0) {
//                     temp_chole[chole_len] += PokerAssist_t::deal_board_round[i];
//                     chole_len += 1;
//                 }
//                 if (PokerAssist_t::deal_board_round[i] > 0) {
//                     temp_cboard[cboard_len] += PokerAssist_t::deal_board_round[i];
//                     cboard_len += 1;
//                 }
//             }

//             // 拼接
//             int i = 0;
//             while (i < chole_len) {
//                 isomorphism_configs[id_1d][i] = temp_chole[i];
//                 i += 1;
//             }
//             while (i < chole_len + cboard_len) {
//                 isomorphism_configs[id_1d][i] = temp_cboard[i - chole_len];
//                 i += 1;
//             }
//         }
//     }
//     return isomorphism_configs;
// }

// template<typename PokerAssist_t>
// inline constexpr std::array<int, PokerAssist_t::num_rounds*(PokerAssist_t::num_rounds+1)/2> get_isomorphism_stages(){
//     static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_isomorphism_stages函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
//     std::array<int, PokerAssist_t::num_rounds*(PokerAssist_t::num_rounds+1)/2> isomorphism_stages;

//     for(int cur_round = 0; cur_round < PokerAssist_t::num_rounds; ++cur_round){
//         uint8_t sum_hole = 0;
//         uint8_t sum_board = 0;

//         for(int recall_round = 0; recall_round <= cur_round; ++recall_round){
//             int id_1d = cur_round * (cur_round+1)/2 + recall_round;

//             sum_hole += PokerAssist_t::deal_hole_round[recall_round];
//             sum_board += PokerAssist_t::deal_board_round[recall_round];

//             //hole与board的发牌分别计数，以便后面拼接起来
//             int stage_len = 0;

//             // 计数
//             if (sum_hole > 0) {
//                 stage_len += 1;
//             }
//             if (sum_board > 0) {
//                 stage_len += 1;
//             }

//             for (int i = recall_round + 1; i <= cur_round; ++i){
//                 if (PokerAssist_t::deal_hole_round[i] > 0) {
//                     stage_len += 1;
//                 }
//                 if (PokerAssist_t::deal_board_round[i] > 0) {
//                     stage_len += 1;
//                 }
//             }

//             // 拼接
//             isomorphism_stages[id_1d] = stage_len;
//             assert(stage_len < MAX_ROUNDS);
//         }
//     }
//     return isomorphism_stages;
// }
/////////////////////////////////////////////////////////////////////////////////////////////
// template<typename PokerAssist_t>
// constexpr auto get_deal_combine_round(){
//     static_assert(std::is_base_of<PokerAssistBase, PokerAssist_t>::value && !std::is_same<PokerAssistBase, PokerAssist_t>::value, "get_deal_combine_round函数模板中PokerAssist_t必须是PokerAssistBase的派生类");
//     constexpr std::array deal_combine_len = get_deal_combine_len<PokerAssist_t>();
//     constexpr int deal_combine_len_max = deal_combine_len[PokerAssist_t::num_rounds-1];
//     std::array<std::array<int, deal_combine_len_max>, PokerAssist_t::num_rounds> deal_combine_round{};

//     for(int cur_round = 0; cur_round<PokerAssist_t::num_rounds; ++cur_round){
//         int idx = 0;
//         for(int sub_round = 0; sub_round <= cur_round; ++sub_round){
//             int sur_round_combin_len = PokerAssist_t::deal_card[sub_round] * (PokerAssist_t::deal_private[sub_round]?PokerAssist_t::num_players:1);
//             for(int i = 0; i<sur_round_combin_len; ++i){
//                 deal_combine_round[cur_round][idx++] = PokerAssist_t::deal_card[sub_round];
//             }
//         }
//     }
//     return deal_combine_round;
// }