void Shogi::GenerateMoves1Step( Moves& moves, GEN_INFO& info, int dir ){ /************************************************ 任意の方向への着手可能手を列挙する。 ************************************************/ int from; // 移動元 int to; // 移動先 int n; int flag; bool nz; if( info.dir_p != 0 && dir != info.dir_p && dir != -info.dir_p ) return; from = info.addr; to = info.addr + dir; if( ban[to] == EMPTY || ban[to] & (ksengo^SENGO) ){ if( ( info.flag & MOVE_CAPTURE && ban[to] != EMPTY ) || ( info.flag & MOVE_NOCAPTURE && ban[to] == EMPTY ) // 新しいGenerateCheckOnBoard内で空き王手のチェックは行う。 /*|| ( info.flag & MOVE_CHECK && IsDiscCheckMove( info.ou2, to, from ) )*/ ){ flag = 1; } else{ flag = 0; } // 着手可能手追加 n = 0; if( !( info.koma & NARI ) && info.koma != SKI && info.koma != GKI && ( ( ksengo == SENTE && ( to <= BanAddr(9,3) || from <= BanAddr(9,3) ) ) || ( ksengo == GOTE && ( to >= BanAddr(1,7) || from >= BanAddr(1,7) ) ) ) ) { // 成る場合 if( flag || info.flag & MOVE_PROMOTE || ( info.flag & MOVE_CHECK && IsCheckMove( info.ou2, to, info.koma + NARI ) ) || ( info.flag & MOVE_NCHECK && !IsCheckMove( info.ou2, to, info.koma + NARI ) ) ){ moves.Add( from, to, 1, info.koma ); } n = 1; } nz = !n || Narazu( info.koma, to ); if( !MoveError( info.koma, to ) && // 王手の場合でも不成は生成しないように変更 ( /*info.flag & MOVE_CHECK ||*/ nz ) ) { // 成らない場合 if( flag || info.flag & MOVE_NOPROMOTE || ( info.flag & MOVE_CHECK && IsCheckMove( info.ou2, to, info.koma ) ) || ( nz && info.flag & MOVE_NCHECK && !IsCheckMove( info.ou2, to, info.koma ) ) ){ moves.Add( from, to, 0, info.koma ); } } } }
void Shogi::GenerateMovesDropKy( Moves& moves ){ /************************************************ 香車を打つ手を列挙する。 ************************************************/ KOMA koma; int to; int i, j; koma = KY | ksengo; if( dai[koma] == 0 ) return; for( j = 0x10 ; j <= 0x90 ; j += 0x10 ){ for( i = 1 ; i <= 9 ; i++ ){ to = i + j; if( ban[to] == EMPTY ){ // 合法手チェック if( ksengo == SENTE ){ if( to <= BanAddr(9,1) ) continue; } else{ if( to >= BanAddr(1,9) ) continue; } // 着手可能手追加 moves.Add( DAI + koma, to, 0, koma ); } } } }
int Book::GetMoveAll( Shogi* pshogi, Moves& moves, TYPE type ){ /************************************************ 定跡手を列挙する。 ************************************************/ int i; int flag; list<BLIST>::iterator ib; list<MLIST>::iterator im; list<MLIST>* pmlist; uint64 hash = pshogi->GetHash(); MOVE mtemp; i = (int)( hash & BOOK_HASH_MASK ); // 局面が既にあるか調べる。 flag = 0; for( ib = blist[i].begin() ; ib != blist[i].end() ; ++ib ){ if( (*ib).hash == hash ){ flag = 1; break; } } if( flag == 0 ) return 0; // 指し手を列挙 pmlist = &(*ib).mlist; for( im = pmlist->begin() ; im != pmlist->end() ; ++im ){ mtemp.Import( (*im).mv ); if( pshogi->IsLegalMove( mtemp ) ){ switch( type ){ // 評価値を用いる場合 case TYPE_EVAL: mtemp.value = (*im).val; break; // 出現頻度を用いる場合 case TYPE_FREQ: default: mtemp.value = (*im).cnt * 100 / (*ib).cnt; break; } moves.Add( mtemp ); } } moves.Sort(); return moves.GetNumber(); }
void Shogi::GenerateEvasionDrop( Moves& moves, GEN_INFO& info, int to ){ /************************************************ 持ち駒による合駒 ************************************************/ KOMA koma; int i; for( koma = ksengo + FU ; koma <= ksengo + HI ; koma++ ){ if( dai[koma] > 0 && !MoveError( koma, to ) ){ if( info.flag & MOVE_CHECK && !IsCheckMove( info.ou2, to, koma ) ){ continue; } if( koma == SFU || koma == GFU ){ // 二歩のチェック i = to % 0x10; if( ksengo == SENTE ){ if( kifu[know].sfu & ( 1 << i ) ) goto lab_nifu; } else{ if( kifu[know].gfu & ( 1 << i ) ) goto lab_nifu; } // 打ち歩詰めのチェック if( ksengo == SENTE ){ if( to - 0x10 == gou && IsUchifu( to ) ) goto lab_nifu; } else{ if( to + 0x10 == sou && IsUchifu( to ) ) goto lab_nifu; } } // 着手可能手追加 moves.Add( DAI + koma, to, 0, koma ); } lab_nifu: ; } }
void Shogi::GenerateMovesDropFu( Moves& moves ){ /************************************************ 歩を打つ手を列挙する。 ************************************************/ KOMA koma; int to; int i, j; koma = FU | ksengo; if( dai[koma] == 0 ) return; for( i = 1 ; i <= 9 ; i++ ){ // 二歩のチェック if( ksengo == SENTE ){ if( kifu[know].sfu & ( 1 << i ) ) continue; } else{ if( kifu[know].gfu & ( 1 << i ) ) continue; } for( j = 0x10 ; j <= 0x90 ; j += 0x10 ){ to = i + j; if( ban[to] == EMPTY ){ // 合法手チェック if( ksengo == SENTE ){ if( to <= BanAddr(9,1) || ( to - 0x10 == gou && IsUchifu( to ) ) ) continue; } else{ if( to >= BanAddr(1,9) || ( to + 0x10 == sou && IsUchifu( to ) ) ) continue; } // 着手可能手追加 moves.Add( DAI + koma, to, 0, koma ); } } } }
void Shogi::GenerateMovesDrop( Moves& moves, KOMA koma ){ /************************************************ 持ち駒を打つ手を列挙する。 ************************************************/ int to; int i, j; if( dai[koma] == 0 ) return; for( j = 0x10 ; j <= 0x90 ; j += 0x10 ){ for( i = 1 ; i <= 9 ; i++ ){ to = i + j; if( ban[to] == EMPTY ){ // 着手可能手追加 moves.Add( DAI + koma, to, 0, koma ); } } } }
void Shogi::GenerateMovesOu( Moves& moves, GEN_INFO& info, int dir ){ /************************************************ 王の移動を生成 ************************************************/ int to; to = info.ou + dir; if( ban[to] == EMPTY || ban[to] & (ksengo^SENGO) ){ if( ( info.flag & MOVE_KING ) || ( info.flag & MOVE_CAPTURE && ban[to] != EMPTY ) || ( info.flag & MOVE_NOCAPTURE && ban[to] == EMPTY ) || ( info.flag & MOVE_CHECK && IsDiscCheckMove( info.ou2, to, info.ou ) ) ){ // 王手放置 if( !IsCheckNeglect( dir ) ){ // 着手可能手追加 moves.Add( info.ou, to, 0, OU | ksengo ); } } } }
void Shogi::GenerateEvasionBan( Moves& moves, GEN_INFO& info, bool eff ){ /************************************************ 駒を取る手と移動合 eff は紐のついていない合駒を除去するために使用 利きを使えばその方向に駒があるかはわかるはず。=> 要検討 ************************************************/ int to = info.addr; // 移動先 int from; // 移動元 int dir; // 方向 int b; // ビット位置 int dflag; // 空き王手フラグ unsigned* effect = ( ksengo == SENTE ? effectS : effectG ); unsigned e = effect[to]; if( e == 0U ){ return; } // 利きを見て現在のマスに動ける駒があるか調べる。 b = 0; for( int x = getFirstBit( e ) ; x != 0 ; x = getFirstBit( e >> b ) ){ b += x; if( b <= 12 ){ dir = _dir[b- 1]; if( dir == info.check ){ // 王様は除外 continue; } from = to - dir; } else{ dir = _dir[b-13]; for( from = to - dir ; ban[from] == EMPTY ; from -= dir ) ; } // 紐がついているかチェック if( eff && !( effect[from] & _dir2bitF[dir] ) ){ continue; } // ピンされていないか if( ( info.pin & _addr2bit[from] ) != 0x00U ){ continue; } // 王手 if( info.flag & MOVE_CHECK && IsDiscCheckMove( info.ou2, to, from ) ){ dflag = 1; } else{ dflag = 0; } // 着手可能手追加 bool n = 0; KOMA koma = ban[from]; if( !( koma & NARI ) && koma != SKI && koma != GKI && ( ( ksengo == SENTE && ( to <= BanAddr(9,3) || from <= BanAddr(9,3) ) ) || ( ksengo == GOTE && ( to >= BanAddr(1,7) || from >= BanAddr(1,7) ) ) ) ) { // 成る場合 if( dflag || !( info.flag & MOVE_CHECK ) || IsCheckMove( info.ou2, to, koma + NARI ) ){ moves.Add( from, to, 1, koma ); n = true; } } if( !MoveError( koma, to ) && // 王手の場合でも不成は生成しないように変更 ( !n /*|| info.flag & MOVE_CHECK*/ || Narazu( koma, to) ) ) { // 成らない場合 if( dflag || !( info.flag & MOVE_CHECK ) || IsCheckMove( info.ou2, to, koma ) ){ moves.Add( from, to, 0, koma ); } } } }