⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 searchengine.java

📁 一个网络对弈的中国象棋程序 操作: 1、Setting,选择对战方式。如果选择“网络对战”
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
					if (!inCheck && futValue <= Alpha) {
						futPrune = thisDepth;
						bestValue = futValue;
					}
				}
			}

			// 7. 空着裁减
			if (nullMove && futPrune==0 && !inCheck && activeBoard.lastMove().src != -1 && activeBoard.getEvalue(activeBoard.getPlayer()) > CCEvalue.EndgameMargin) {
				activeBoard.nullMove();
				thisValue = -search(subKillerTab, -Beta, 1 - Beta, thisDepth - 1 - RAdapt(thisDepth));
				activeBoard.undoNull();
				if (thisValue >= Beta) {
					nullNodes ++;
					return Beta;
				}
			}
			

			// 8. 搜索命中Hash Table
			if (hashValue == ObsoleteValue) {
				//System.out.println(ThisMove.Coord());
				if (activeBoard.movePiece(thisMove)) {
					movable = true;
					if (futPrune!=0 && -activeBoard.evaluation() + (futPrune == 2 ? CCEvalue.ExtFutMargin : CCEvalue.SelFutMargin) <= Alpha && activeBoard.lastMove().chk) {
						activeBoard.undoMove();
					} else {
						thisValue = -search(subKillerTab, -Beta, -thisAlpha, thisDepth - 1);
						searched = true;
						activeBoard.undoMove();
						if (stop) {
							return 0;
						}
						if (thisValue > bestValue) {
							if (thisValue >= Beta) {
								histTab[thisMove.src][thisMove.dst] += 1 << (thisDepth - 1);
								recordHash(thisMove, HashBeta, Beta, thisDepth);
								hashNodes ++;
								return thisValue;
							}
							bestValue = thisValue;
							bestMove = thisMove;
							if (thisValue > thisAlpha) {
								thisAlpha = thisValue;
								hashFlag = HashPv;
								if (activeBoard.getMoveNum() == startMove) {
									recordHash(bestMove, hashFlag, thisAlpha, thisDepth);
									popInfo(thisAlpha, Depth);
								}
							}
						}
					}		 
				}
			}

			// 9. 命中杀着表
			for (i = 0; i < KillerTab.moveNum; i ++) {
				thisMove = KillerTab.moveList[i];
				if (activeBoard.leagalMove(thisMove)) {
					if (activeBoard.movePiece(thisMove)) {
						movable = true;
						if (futPrune!=0 && -activeBoard.evaluation() + (futPrune == 2 ? CCEvalue.ExtFutMargin : CCEvalue.SelFutMargin) <= Alpha && activeBoard.lastMove().chk) {
							activeBoard.undoMove();
						} else {
							if (searched) {
								thisValue = -search(subKillerTab, -thisAlpha - 1, -thisAlpha, thisDepth - 1);
								if (thisValue > thisAlpha && thisValue < Beta) {
									thisValue = -search(subKillerTab, -Beta, -thisAlpha, thisDepth - 1);
								}
							} else {
								thisValue = -search(subKillerTab, -Beta, -thisAlpha, thisDepth - 1);
								searched = true;
							}
							activeBoard.undoMove();
							if (stop) {
								return 0;
							}
							if (thisValue > bestValue) {
								if (thisValue >= Beta) {
									killerNodes ++;
									histTab[thisMove.src][thisMove.dst] += 1 << (thisDepth - 1);
									recordHash(thisMove, HashBeta, Beta, thisDepth);
									return thisValue;
								}
								bestValue = thisValue;
								bestMove = thisMove;
								if (thisValue > thisAlpha) {
									thisAlpha = thisValue;
									hashFlag = HashPv;
									if (activeBoard.getMoveNum() == startMove) {
										recordHash(bestMove, hashFlag, thisAlpha, thisDepth);
										popInfo(thisAlpha, Depth);
									}
								}
							}
						}
					}
				}
			}

			// 10. 生成当前所有合法着法并排序
			moveSort.GenMoves(activeBoard, histTab);
			nodes+=moveSort.MoveNum;
			for (i = 0; i < moveSort.MoveNum; i ++) {
				moveSort.BubbleSortMax(i);
				thisMove = moveSort.MoveList[i];

				if (activeBoard.movePiece(thisMove)) {
					movable = true;
					// 11. Alpha-Beta Search
					if (futPrune!=0 && -activeBoard.evaluation() + (futPrune == 2 ? CCEvalue.ExtFutMargin : CCEvalue.SelFutMargin) <= Alpha && activeBoard.lastMove().chk) {
						activeBoard.undoMove();
					} else {
						if (searched) {
							thisValue = -search(subKillerTab, -thisAlpha - 1, -thisAlpha, thisDepth - 1);
							if (thisValue > thisAlpha && thisValue < Beta) {
								thisValue = -search(subKillerTab, -Beta, -thisAlpha, thisDepth - 1);
							}
						} else {
							thisValue = -search(subKillerTab, -Beta, -thisAlpha, thisDepth - 1);
							searched = true;
						}
						activeBoard.undoMove();
						if (stop) {
							return 0;
						}
						// 12. 超出边界Alpha-Beta
						if (thisValue > bestValue) {
							if (thisValue >= Beta) {
								betaNodes ++;
								histTab[thisMove.src][thisMove.dst] += 1 << (thisDepth - 1);
								recordHash(thisMove, HashBeta, Beta, thisDepth);
								if (KillerTab.moveNum < MaxKiller) {
									KillerTab.moveList[KillerTab.moveNum] = thisMove;
									KillerTab.moveNum ++;
								}
								return thisValue;
							}
							bestValue = thisValue;
							bestMove = thisMove;
							if (thisValue > thisAlpha) {
								thisAlpha = thisValue;
								hashFlag = HashPv;
								if (activeBoard.getMoveNum() == startMove) {
									recordHash(bestMove, hashFlag, thisAlpha, thisDepth);
									popInfo(thisAlpha, Depth);
								}
							}
						}
					}
				}
			}
			// 13.无路可走,输棋!
			if (!movable) {
				mateNodes ++;
				return activeBoard.getMoveNum() - startMove - CCEvalue.MaxValue;
			}

			// 14. Update History Tables and Hash Tables
			if (futPrune!=0 && bestValue == futValue) {
				bestMove.src = bestMove.dst = -1;
			}
			if ((hashFlag & HashAlpha)!=0) {
				alphaNodes ++;
			} else {
				pvNodes ++;
				histTab[bestMove.src][bestMove.dst] += 1 << (thisDepth - 1);
				if (KillerTab.moveNum < MaxKiller) {
					KillerTab.moveList[KillerTab.moveNum] = bestMove;
					KillerTab.moveNum ++;
				}
			}
			recordHash(bestMove, hashFlag, thisAlpha, thisDepth);
			return bestValue;

			// 15. 静态搜索
		} else {
			thisValue = quiesc(Alpha, Beta);
			thisMove.src = bestMove.dst =  -1;
			if (thisValue <= Alpha) {
				recordHash(thisMove, HashAlpha, Alpha, 0);
			} else if (thisValue >= Beta) {
				recordHash(thisMove, HashBeta, Beta, 0);
			} else {
				recordHash(thisMove, HashPv, thisValue, 0);
			}
			leafNodes ++;
			return thisValue;
		}
	}
//	End Search Procedures
// Start Control Procedures
	private boolean interrupt(){
		if (stop)
			return true;
		return false;
	}
	public void stopSearch(){this.stop=true;}
	private void popInfo(int value, int depth) {
		int i, quiescNodes, nps, npsQuiesc;
		char[] moveStr;
		long tempLong;
		if (depth!=0) {
			String logString="PVNode:  depth=" + depth + ",score=" + value +",Move: "+"\n";
			pvLineNum = 0;
			GetPvLine();
			for (i = 0; i < pvLineNum; i ++) {
				moveStr = pvLine[i].location();
				logString+=" " + String.copyValueOf(moveStr)+"\n";
			}
			if (ponder && System.currentTimeMillis() > minTimer && value + CCEvalue.InadequateValue > lastScore) {
				stop = true;
			}
			if(log.isDebugEnabled()) log.debug(logString);
		}
	}
	
	public void setupControl(int depth,long proper,long limit){
		this.depth = depth;
		this.properTimer = proper;
		this.limitTimer = limit;
	}
	
	public void control() throws LostException{
		//int Depth, int ProperTimer, int LimitTimer) throws IOException {
		int i, MoveNum, ThisValue; 
		char[] MoveStr;
		stop=false;
		bestMove=null;
		MoveNode ThisMove=new MoveNode(), UniqueMove=new MoveNode();
		HashRecord TempHash;
		SortedMoveNodes MoveSort=new SortedMoveNodes();
		KillerStruct SubKillerTab=new KillerStruct();
		// The Computer Thinking Procedure:
		// 1. Search the moveNodes in Book
		int tmpInt = (int) (activeBoard.getZobristKey() & hashMask);
		TempHash = hashList[(int) (activeBoard.getZobristKey() & hashMask)];
		if (TempHash.flag!=0 && TempHash.zobristLock == activeBoard.getZobristLock()) {
			if ((TempHash.flag==BookUnique)) {
				MoveStr = TempHash.bestMove.location();
				bestMove = new MoveNode(String.copyValueOf(MoveStr));
				return;
			} else if (TempHash.flag == BookMulti) {
				ThisValue = 0;
				i = Math.abs(rand.nextInt())%(bookList[TempHash.value].moveNum);
				MoveStr = bookList[TempHash.value].moveList[i].location();
				bestMove = new MoveNode(String.copyValueOf(MoveStr));
				return;
			}
		}

		// 2. Initailize Timer and other Counter
		startTimer = System.currentTimeMillis();
		minTimer = startTimer + (properTimer >> 1);
		maxTimer = properTimer << 1;
		if (maxTimer > limitTimer) {
			maxTimer = limitTimer;
		}
		maxTimer += startTimer;
		stop = false;
		startMove = activeBoard.getMoveNum();
		nodes = nullNodes = hashNodes = killerNodes = betaNodes = pvNodes = alphaNodes = mateNodes = leafNodes = 0;
		quiescNullNodes = quiescBetaNodes = quiescPvNodes = quiescAlphaNodes = quiescMateNodes = 0;
		hitBeta = hitPv = hitAlpha = 0;
		pvLineNum = 0;

		// 3. 不合法:主动送将
		if (activeBoard.checked(activeBoard.getOppPlayer())) {
			return;
		}
		ThisValue = activeBoard.isLoop(3);
		if (ThisValue!=0) {
			throw new LostException("不可常捉!");
		}		
		if (activeBoard.getMoveNum() > ActiveBoard.MAX_CONSECUTIVE_MOVES) {
			throw new LostException("最大步数,和棋!");
		}

		// 4. 测试所有应将的着法
		if (activeBoard.lastMove().chk) {
			MoveNum = 0;
			MoveSort.GenMoves(activeBoard, histTab);
			for (i = 0; i < MoveSort.MoveNum; i ++) {
				ThisMove = MoveSort.MoveList[i];
				if (activeBoard.movePiece(ThisMove)) {
					activeBoard.undoMove();
					UniqueMove = ThisMove;
					MoveNum ++;
					if (MoveNum > 1) {
						break;
					}
				}
			}
			if (MoveNum==0) {
				if(log.isDebugEnabled())
					log.debug("score " + -CCEvalue.MaxValue +"\n");
			}
			if (MoveNum == 1) {
				MoveStr = UniqueMove.location();
				if(log.isDebugEnabled())
					log.debug("bestmove " + String.copyValueOf(MoveStr) + "\n");
				bestMove = new MoveNode(String.copyValueOf(MoveStr));
				return;
			}
		}

		// 5. 迭代加深
		if (depth==0) {
			return;
		}
		for (i = 4; i <= depth; i ++) {
			if(log.isDebugEnabled())
				log.debug("info depth " + i +"\n");
			SubKillerTab.moveNum = 0;
			ThisValue = search(SubKillerTab, -CCEvalue.MaxValue, CCEvalue.MaxValue, i);
			popInfo(ThisValue,depth);
			if (stop) {
				break;
			}
			lastScore = ThisValue;

			// 6. Stop thinking if timeout or solved
			if (!ponder && System.currentTimeMillis() > minTimer) {
				break;
			}
			if (ThisValue > CCEvalue.MaxValue - ActiveBoard.MAX_MOVE_NUM / 2 
					|| ThisValue < ActiveBoard.MAX_MOVE_NUM / 2 - CCEvalue.MaxValue) {
				break;
			}
		}

		// 7. 得到最佳着法及其线路
		if (pvLineNum!=0) {
			MoveStr = pvLine[0].location();
			bestMove = new MoveNode(String.copyValueOf(MoveStr));
			if(log.isDebugEnabled())
				log.debug("bestmove: " + String.copyValueOf(MoveStr) + "\n");
			if (pvLineNum > 1) {
				MoveStr = pvLine[1].location();
				if(log.isDebugEnabled())
					log.debug("ponder:" + String.copyValueOf(MoveStr) + "\n");
			}
		} else {
			if(log.isDebugEnabled())
				log.info("score:" + ThisValue);
		}		
	}

//End Control Procedures

	public MoveNode getBestMove() throws LostException{
		control();
		MoveNode retVal = bestMove;
		return bestMove;
	}
	//for test
	public static void main(String[] args) throws IOException {
		long start,end;
		RandomAccessFile testResult;
		log.info("begin search, please wait......");
		start = System.currentTimeMillis();
		int steps = 8;
		ActiveBoard cp= new ActiveBoard();
		String FenStr = "1c1k1abR1/4a4/4b4/6NP1/4P4/2C1n1P2/r5p2/4B4/4A4/2BAK4 w - - 0 20";
		cp.loadFen(FenStr);
		SearchEngine searchMove = new SearchEngine(cp);
		searchMove.loadBook("./data/BOOK.DAT");
		//System.out.println(cp.AllPieces);
		//searchMove.Control(steps,CLOCK_M*2,CLOCK_M*4);
		log.info(FenStr);
		end = System.currentTimeMillis();
		long second=(end - start)/1000;
		long minutes=second/60;
		testResult = new RandomAccessFile("./data/test.log","rw"); 
		Calendar c = Calendar.getInstance();
		String tmpStr = "\n\n********************************************************************\n";
		tmpStr = tmpStr + "[Test Time] "+c.getTime()+"\n";
		tmpStr = tmpStr + "[Fen String] "+ FenStr + "\n"; 
		tmpStr = tmpStr + "   Deep =" + steps+",Used Time:"+ minutes +":" + second%60 + "\n";
		tmpStr = tmpStr + "[Nodes] " + searchMove.nodes+"\n";
		tmpStr = tmpStr + "[AlphaNodes] " + searchMove.alphaNodes+"\n";
		tmpStr = tmpStr + "[BetaNodes] " + searchMove.betaNodes+"\n";
		tmpStr = tmpStr + "[HashNodes] " + searchMove.hashNodes+"\n";
		tmpStr = tmpStr + "[KillerNodes] " + searchMove.killerNodes+"\n";
		tmpStr = tmpStr + "[LeafNodes] " + searchMove.leafNodes+"\n";
		tmpStr = tmpStr + "[NullNodes] " + searchMove.nullNodes+"\n";
		tmpStr = tmpStr + "[QuiescAlphaNodes] " + searchMove.quiescAlphaNodes+"\n";
		tmpStr = tmpStr + "[QuiescBetaNodesNodes] " + searchMove.quiescBetaNodes+"\n";
		tmpStr = tmpStr + "[QuiescMateNodes] " + searchMove.quiescMateNodes+"\n";
		tmpStr = tmpStr + "[QuiescNullNodes] " + searchMove.quiescNullNodes+"\n";
		tmpStr = tmpStr + "[QuiescPvNodes] " + searchMove.quiescPvNodes+"\n";
		tmpStr = tmpStr + "[HitAlpha] " + searchMove.hitAlpha+"\n";
		tmpStr = tmpStr + "[HitBeta] " + searchMove.hitBeta+"\n";
		tmpStr = tmpStr + "[HitPv] " + searchMove.hitPv+"\n";
		
		tmpStr = tmpStr + "[BetaNode] " + searchMove.betaNodes+"\n";
		tmpStr = tmpStr + "[BPS] "+ searchMove.nodes/second;
		int count = 0;
		for (int i=1;i<searchMove.hashList.length;i++){
			if (searchMove.hashList[i].flag!=0) count++;
		}
		tmpStr = tmpStr + "[HashTable] length="+searchMove.hashList.length+", occupied="+count;
		testResult.seek(testResult.length());
		testResult.writeBytes(tmpStr);
		
		testResult.close();
		System.out.println(tmpStr);
		searchMove=null;
		cp=null;
		System.gc();		
	}
}

class BookRecord {
	int moveNum;
	MoveNode[] moveList;//[MaxBookMove];
	public BookRecord(){
		moveList = new MoveNode[SearchEngine.MaxBookMove];
		moveNum=0;
	}
};

class KillerStruct {
	int moveNum;
	MoveNode[] moveList;//[MaxKiller];
	public KillerStruct(){
		moveList = new MoveNode[SearchEngine.MaxKiller];
		for (int i=0;i<SearchEngine.MaxKiller;i++)
			moveList[i]= new MoveNode();
		moveNum=0;
	}
};
class HashRecord {
	public HashRecord(){
		flag=0;
		depth=0;
		value=0;
		zobristLock = 0;
		bestMove = new MoveNode();
	}
	long zobristLock;
	int flag, depth;
	int value;
	MoveNode bestMove;
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -