int Kyokumen::MakeLegalMoves(Teban teban, Te *teBuf, int *pin) { int pbuf[16*11]; int teNum = 0; if (pin == nullptr) { MakePinInf(pbuf); pin = pbuf; } if (teban == SELF && m_ControlE[m_KingS] != 0) { return AntiCheck(teban, teBuf, pin, m_ControlE[m_KingS]); } if (teban == ENEMY && m_ControlS[m_KingE] != 0) { return AntiCheck(teban, teBuf, pin, m_ControlS[m_KingE]); } int suji, dan; int sujiMax, danMax; int StartDan, EndDan; sujiMax = GetSuji(); danMax = GetDan(); // 盤上の駒を動かす. for (suji=1; suji <= sujiMax; suji++) { for (dan=1; dan <= danMax; dan++) { KomaPos pos = SUJIDAN2KOMAPOS(suji, dan); if ((m_Ban[pos] & teban) != 0) { AddMoves(teban, teNum, teBuf, pos, pin[pos]); } } } // 歩を打つ. if (m_Hand[teban|FU] > 0) { for (suji=1; suji <= sujiMax; suji++) { // 二歩チェック. int nifu = 0; for (dan=1; dan <= danMax; dan++) { KomaPos pos = SUJIDAN2KOMAPOS(suji, dan); if (m_Ban[pos]== (teban|FU)) { nifu = true; break; } } if (nifu) continue; // (先手なら2段目より下に、後手なら8段目より上に打つ). if (teban == SELF) { StartDan = 2; EndDan = danMax; } else { StartDan = 1; EndDan = danMax-1; } for (dan=StartDan; dan<=EndDan; dan++) { // 打ち歩詰めもチェック. KomaPos pos = SUJIDAN2KOMAPOS(suji, dan); if (m_Ban[pos] == EMPTY && !Utifudume(teban, pos, pin)) { teBuf[teNum++] = Te(0, pos, teban|FU, EMPTY); } } } } // 香を打つ. if (m_Hand[teban|KY] > 0) { for (suji=1; suji <= sujiMax; suji++) { // (先手なら2段目より下に、後手なら8段目より上に打つ). if (teban == SELF) { StartDan = 2; EndDan = danMax; } else { StartDan = 1; EndDan = danMax-1; } for (dan=StartDan; dan <= EndDan; dan++) { KomaPos pos = SUJIDAN2KOMAPOS(suji, dan); if (m_Ban[pos] == EMPTY) { teBuf[teNum++] = Te(0, pos, teban|KY, EMPTY); } } } } // 桂を打つ. if (m_Hand[teban|KE] > 0) { // (先手なら3段目より下に、後手なら7段目より上に打つ). for(suji=1; suji <= sujiMax; suji++) { if (teban == SELF) { StartDan = 3; EndDan = danMax; } else { StartDan = 1; EndDan = danMax-2; } for (dan=StartDan; dan <= EndDan; dan++) { KomaPos pos = SUJIDAN2KOMAPOS(suji, dan); if (m_Ban[pos] == EMPTY) { teBuf[teNum++] = Te(0, pos, teban|KE, EMPTY); } } } } // 銀〜飛車は、どこにでも打てる. for (int koma=GI; koma <= HI; koma++) { if (m_Hand[teban|koma] > 0) { for (suji=1; suji <= sujiMax; suji++) { for (dan=1; dan <= danMax; dan++) { KomaPos pos = SUJIDAN2KOMAPOS(suji, dan); if (m_Ban[pos] == EMPTY) { teBuf[teNum++] = Te(0, pos, teban|koma, EMPTY); } } } } } return teNum; }
int CNegaScout_TT_HH::NegaScout(int depth, int alpha, int beta){ int count,i; int type; int a,b,t; int side; int score; i = IsGameOver(m_cur_position, depth); if (i != 0) return i; side = 1-(m_max_depth-depth)%2; score = m_tt->LookupHashTable(alpha, beta, depth, side); if (score != INVALID_SCORE && depth != m_max_depth){ /*if (depth == m_max_depth){ ChessMove move = new ChessMove(); move.Move = m_tt.LookupBestMove(side); m_best_move = move; }*/ return score; } if (depth <= 0) { score = m_evaluator->Evaluate(m_cur_position, side == 0, depth); m_tt->EnterHashTable(EXACT, score, depth, side); return score; } //m_nMovecount = 0; count = m_move_generator->CreatePossibleMove(m_cur_position, m_moves, depth, side); AddMoves(count, depth); for (i = 0; i < count; ++i) { m_move_list[depth][i].m_score = m_hh->GetHistoryScore(m_move_list[depth][i]); } m_hh->MergeSort(m_move_list[depth], count, false); int bestmove = -1; a = alpha; b = beta; int eval_is_exact = 0; for (i = 0; i < count; ++i){ m_tt->HashMakeMove(m_move_list[depth][i], m_cur_position); type = MakeMove(m_move_list[depth][i]); t = -NegaScout(depth-1 , -b, -a); if (t > a && t < beta && i > 0){ a = -NegaScout (depth-1, -beta, -t); /* re-search */ eval_is_exact = 1; if(depth == m_max_depth){ m_best_move = m_move_list[depth][i]; //m_tt.EnterHashBestMove(m_best_move.Move, side); } bestmove = i; } m_tt->HashUnmakeMove(m_move_list[depth][i], type, m_cur_position); UnmakeMove(m_move_list[depth][i],type); if (a < t){ eval_is_exact = 1; a = t; if(depth == m_max_depth) { m_best_move = m_move_list[depth][i]; //m_tt.EnterHashBestMove(m_best_move.Move, side); } } if (a >= beta) { m_tt->EnterHashTable(LOWER_BOUND, a, depth, side); m_hh->EnterHistoryScore(m_move_list[depth][i], depth); return a; } b = a + 1; /* set new null window */ } if (bestmove != -1) m_hh->EnterHistoryScore(m_move_list[depth][bestmove], depth); if (eval_is_exact != 0) m_tt->EnterHashTable(EXACT, a, depth, side); else m_tt->EnterHashTable(UPPER_BOUND, a, depth, side); return a; }