搜索算法
转载请保留作者信息:
作者:88250
MSN & Gmail & QQ:DL88250@gmail.com
搜索是电脑棋手AI的核心,有效的搜索算法很关键。本文给出了一些常用的搜索算法代码,以及这些算法的改进。例如配合置换表,历史启发表,开局库。算法的深入学习可以参考注释里给出的地址 : )
/*
* @(#)SearchEngine.java
* Author: 88250 , http://blog.csdn.net/DL88250
* Created on May 24, 2008, 10:51:52 AM
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package cn.edu.ynu.sei.chinesechess.infrastructure.search;
import cn.edu.ynu.sei.chinesechess.infrastructure.common.Motion;
import cn.edu.ynu.sei.chinesechess.infrastructure.common.Situation;
import cn.edu.ynu.sei.chinesechess.infrastructure.search.TranspositionTable.NodeType;
import java.util.Collections;
import java.util.List;
/**
* This class descripts some search algorithms of game tree.
* @author 88250 , http://blog.csdn.net/DL88250
* @version 1.1.2.6, Jun 7, 2008
*/
public class SearchEngine {
/**
* value while win a game
*/
public static final int WIN = 54;
/**
* chessboard situation
*/
public Situation situation;
/**
* the best move
*/
public Motion bestMotion;
/**
* situation libaray
*/
private Book book = new Book();
/**
* default search depth
*/
public static int SEARCH_DEPTH = 5;
/**
* For Performance Test.
* @param args should be null
*/
public static void main(String[] args) {
SearchEngine instance;
instance = new SearchEngine(new Situation());
System.out.println("Getting start search!");
long startTime = System.nanoTime();
//instance.basicAlphaBetaSearch(SEARCH_DEPTH, -WIN, WIN);
//instance.alphaBetaWithHistoryHeuristicSearch(SEARCH_DEPTH, -WIN, WIN);
//instance.alphaBetaWithTranspositonSearch(SEARCH_DEPTH, -WIN, WIN);
//instance.principalVariationSearch(SEARCH_DEPTH, -WIN, WIN);
//instance.principalVariationWithHHSearch(SEARCH_DEPTH, -WIN, WIN);
instance.negaScoutWithHHTTSearch(SEARCH_DEPTH, -WIN, WIN);
long estimatedTime = System.nanoTime() - startTime;
System.out.println("Evaluated node count: " + Situation.nodeEvaluatedCount);
System.out.println("TT hit count: " + TranspositionTable.hashHitCount);
System.out.println("Best motion: " + instance.bestMotion.toString());
System.out.println("Elapsed Time: " + estimatedTime / 1000000000.0 + "s");
System.out.println("");
}
/**
* Finds the best move on the specified chessboard situation.
* @param boardSituation the specified chessboard situation
* @return the evaluate value
*/
public int findTheBestMove(int[][] boardSituation) {
TranspositionTable.initHashCode(boardSituation);
return negaScoutWithHHTTSearch(SEARCH_DEPTH, -WIN, WIN);
}
/**
* Search the FEN book for a good move.
* @return if find a move in the book, retusns true
,
* otherwise, returns false
*/
public boolean bookSearch() {
List motions = situation.generatePossibleMoves();
for (Motion motion : motions) {
situation.makeMove(motion.fromX, motion.fromY, motion.toX, motion.toY);
if (book.exists(situation.chessboard)) {
// this situation exists in book!
bestMotion = motion;
situation.unMove();
return true;
}
situation.unMove();
}
return false;
}
/**
* Basic Alpha-Beta search method.
* @param depth depth of search
* @param alpha min value to max value, the "floor"
* @param beta max value to min value, the "ceiling"
* @return if game is over, returns -WIN
, if depth arrived,
* returns evaluat value(leaf node value), otherwise, returns bound(
* determined by cut-off)
*/
final int basicAlphaBetaSearch(int depth, int alpha, int beta) {
if (situation.gameOver() != 0) {
return -WIN;
}
if (depth <= 0) {
return situation.evaluate();
}
List motions = situation.generatePossibleMoves();
for (Motion motion : motions) {
situation.makeMove(motion.fromX, motion.fromY, motion.toX, motion.toY);
int score = -basicAlphaBetaSearch(depth - 1, -beta, -alpha);
situation.unMove();
if (score > alpha) {
alpha = score;
if (depth == SEARCH_DEPTH) {
bestMotion = motion;
}
if (alpha >= beta) {
return beta;
}
}
}
return alpha;
}
/**
* Alpha-Beta with History Heuristic search method.
* @param depth depth of search
* @param alpha min value to max value, the "floor"
* @param beta max value to min value, the "ceiling"
* @return if game is over, returns -WIN
, if depth arrived,
* returns evaluat value(leaf node value), otherwise, returns bound(
* determined by cut-off)
*/
@SuppressWarnings("unchecked")
final int alphaBetaWithHistoryHeuristicSearch(int depth, int alpha, int beta) {
if (situation.gameOver() != 0) {
return -WIN;
}
if (depth <= 0) {
return situation.evaluate();
}
List motions = situation.generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH) {
for (Motion motion : motions) {
motion.value = HistoryHeuristicTable.getValue(motio