Exemple #1
0
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 );
			}
		}
	}
}
Exemple #2
0
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 );
			}
		}
	}
}
Exemple #3
0
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();
}
Exemple #4
0
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:
		;
	}
}
Exemple #5
0
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 );
			}
		}
	}
}
Exemple #6
0
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 );
			}
		}
	}
}
Exemple #7
0
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 );
			}
		}
	}
}
Exemple #8
0
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 );
			}
		}
	}
}