知识大全 Java中国象棋博弈程序探秘之搜索算法
Posted 知
篇首语:不飞则已,一飞冲天;不鸣则已,一鸣惊人。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java中国象棋博弈程序探秘之搜索算法相关的知识,希望对你有一定的参考价值。
Java中国象棋博弈程序探秘之搜索算法 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
搜索是电脑棋手AI的核心 有效的搜索算法很关键 本文给出了一些常用的搜索算法代码 以及这些算法的改进 例如配合置换表 历史启发表 开局库 算法的深入学习可以参考注释里给出的地址 : )
view plaincopy to clipboardprint? /*
* @(#)SearchEngine java
* Author: <>
* Created on May : : AM
*
* This program is free sofare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Sofare Foundation; either version 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 Sofare
* Foundation Inc Temple Place Suite Boston MA USA
*/
package cn edu ynu sei chinesechess infrastructure search;
import cn edu ynu sei chinesechesmon Motion;
import cn edu ynu sei chinesechesmon 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 <>
* @version Jun
*/
public class SearchEngine
/**
* value while win a game
*/
public static final int WIN = ;
/**
* 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 = ;
/**
* For Performance Test
* @param args should be <code>null</code>
*/
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 / + 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 <code>true</code>
* otherwise returns <code>false</code>
*/
public boolean bookSearch()
List<Motion> 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 <code> WIN</code> 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() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
for (Motion motion : motions)
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = basicAlphaBetaSearch(depth 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 <code> WIN</code> 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() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH)
for (Motion motion : motions)
motion value = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX motion toY);
// XXX do sort algorithm by myself for performance?
Collections sort(motions);
for (Motion motion : motions)
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = alphaBetaWithHistoryHeuristicSearch(depth beta alpha);
situation unMove();
if (score > alpha)
alpha = score;
HistoryHeuristicTable setValue(motion fromX motion fromY
motion toX motion toY
(HistoryHeuristicTable getValue(
motion fromX
motion fromY
motion toX
motion toY) +
<< depth));
if (depth == SEARCH_DEPTH)
bestMotion = motion;
if (alpha >= beta)
return beta;
return alpha;
/**
* Principal Variation SearchEngine method
* <p>Probably the best of the alpha beta variants this goes by
* several names: <em><b>NegaScout</b></em> <em>Principal Variation SearchEngine</em>
* or <em>PVS</em> for short The idea is that alpha beta search works
* best if the first recursive search is likely to be the one
* with the best score Techniques such as sorting the move list
* or using a best move stored in the hash table make it especially
* likely that the first move is best If it is we can search
* the other moves more quickly by using the assumption that
* they are not likely to be as good So PVS performs that first
* search with a normal window but on subsequent searches uses a
* zero width window to test each successive move against the first
* move Only if the zero width search fails does it do a normal search
* </p>
* <p>
* More detalis please visits:<br>
* <a >
* ICS Winter : Strategy and board game programming</a><br>
* or Read this paper:<br>
* Alexander Reinefild AN IMPROVEMENT TO THE SCOUT TREE SEARCH ALGORITHM
*
* </p>
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
final int principalVariationSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
situation makeMove(motions get( ) fromX motions get( ) fromY
motions get( ) toX motions get( ) toY);
int best = principalVariationSearch(depth beta alpha);
situation unMove();
if (depth == SEARCH_DEPTH)
bestMotion = motions get( );
for (int i = ; i < motions size(); i++)
if (best < beta)
if (best > alpha)
alpha = best;
Motion motion = motions get(i);
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = principalVariationSearch(depth alpha alpha);
if (score > alpha && score < beta)
// fail high re search
best = principalVariationSearch(depth beta score);
if (depth == SEARCH_DEPTH)
bestMotion = motion;
else if (score > best)
best = score;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
situation unMove();
return best;
/**
* Principal Variation with History Heuristic SearchEngine method(fail soft version)
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
@SuppressWarnings( unchecked )
final int principalVariationWithHHSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH)
for (Motion motion : motions)
motion value = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX motion toY);
Collections sort(motions);
Motion motion = motions get( );
situation makeMove(motion fromX motion fromY
motion toX motion toY);
int best = principalVariationWithHHSearch(depth beta alpha);
situation unMove();
if (depth == SEARCH_DEPTH)
bestMotion = motion;
int oldValue = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX
motion toY);
HistoryHeuristicTable setValue(motions get( ) fromX
motions get( ) fromY
motions get( ) toX
motions get( ) toY
(oldValue + << depth));
for (int i = ; i < motions size(); i++)
if (best < beta)
if (best > alpha)
alpha = best;
motion = motions get(i);
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = principalVariationWithHHSearch(depth alpha
alpha);
if (score > alpha && score < beta)
best = principalVariationWithHHSearch(depth beta score);
if (depth == SEARCH_DEPTH)
bestMotion = motion;
else if (score > best)
int oldValue = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX
motion toY);
HistoryHeuristicTable setValue(motion fromX
motion fromY
motion toX
motion toY
(oldValue + << depth));
best = score;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
situation unMove();
return best;
/**
* Alpha Beta with Transposition Table search method
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
final int alphaBetaWithTranspositonSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
// lookup transposition table
int score = TranspositionTable lookup(depth alpha beta);
if (score != )
// hit the target!
return score;
if (depth <= )
score = situation evaluate();
// save the node
TranspositionTable save(NodeType exact depth score);
return score;
NodeType hashItemType = NodeType unknown;
List<Motion> motions = situation generatePossibleMoves();
for (Motion motion : motions)
int toId = situation makeMove(motion fromX motion fromY motion toX
motion toY);
score = alphaBetaWithTranspositonSearch(depth beta alpha);
situation unMove();
if (score > alpha)
alpha = score;
hashItemType = NodeType exact;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
if (alpha >= beta)
TranspositionTable save(NodeType lowerBound depth alpha);
return beta;
if (hashItemType != NodeType unknown)
TranspositionTable save(NodeType exact depth alpha);
else
TranspositionTable save(NodeType upperBound depth alpha);
return alpha;
/**
* NegaScout with History Heuristic and Transposition Table search
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
@SuppressWarnings( unchecked )
final int negaScoutWithHHTTSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
// lookup transpositiont table
int score = TranspositionTable lookup(depth alpha beta);
if (score != )
// hit the target!
return score;
if (depth <= )
score = situation evaluate();
TranspositionTable save(NodeType exact depth score);
return score;
List<Motion> motions = situation generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH)
for (Motion motion : motions)
motion value = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX motion toY);
Collections sort(motions);
int bestmove = ;
int a = alpha;
int b = beta;
int t;
int oldValue;
NodeType hashItemType = NodeType unknown;
for (int i = ; i < motions size(); i++)
Motion motion = motions get(i);
int toId = situation makeMove(motion fromX motion fromY motion toX
motion toY);
t = negaScoutWithHHTTSearch(depth b a);
if (t > a && t < beta && i > )
a = negaScoutWithHHTTSearch(depth beta t);
hashItemType = NodeType exact;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
bestmove = i;
situation unMove();
if (a < t)
hashItemType = NodeType exact;
a = t;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
if (a >= beta)
TranspositionTable save(NodeType lowerBound depth a);
oldValue = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX
motion toY);
HistoryHeuristicTable setValue(motion fromX
motion fromY
motion toX
motion toY
(oldValue + << depth));
return a;
b = a + ; // set a new numm window
oldValue = HistoryHeuristicTable getValue(motions get(bestmove) fromX
motions get(bestmove) fromY
motions get(bestmove) toX
motions get(bestmove) toY);
HistoryHeuristicTable setValue(motions get(bestmove) fromX
motions get(bestmove) fromY
motions get(bestmove) toX
motions get(bestmove) toY
(oldValue + << depth));
if (hashItemType != NodeType unknown)
TranspositionTable save(NodeType exact depth alpha);
else
TranspositionTable save(NodeType upperBound depth alpha);
return a;
/**
* Constructor with parameters
* @param situation the specified situation
*/
public SearchEngine(Situation situation)
this situation = situation;
/*
* @(#)SearchEngine java
* Author: <>
* Created on May : : AM
*
* This program is free sofare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Sofare Foundation; either version 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 Sofare
* Foundation Inc Temple Place Suite Boston MA USA
*/
package cn edu ynu sei chinesechess infrastructure search;
import cn edu ynu sei chinesechesmon Motion;
import cn edu ynu sei chinesechesmon 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 <>
* @version Jun
*/
public class SearchEngine
/**
* value while win a game
*/
public static final int WIN = ;
/**
* 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 = ;
/**
* For Performance Test
* @param args should be <code>null</code>
*/
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 / + 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 <code>true</code>
* otherwise returns <code>false</code>
*/
public boolean bookSearch()
List<Motion> 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 <code> WIN</code> 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() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
for (Motion motion : motions)
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = basicAlphaBetaSearch(depth 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 <code> WIN</code> 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() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH)
for (Motion motion : motions)
motion value = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX motion toY);
// XXX do sort algorithm by myself for performance?
Collections sort(motions);
for (Motion motion : motions)
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = alphaBetaWithHistoryHeuristicSearch(depth beta alpha);
situation unMove();
if (score > alpha)
alpha = score;
HistoryHeuristicTable setValue(motion fromX motion fromY
motion toX motion toY
(HistoryHeuristicTable getValue(
motion fromX
motion fromY
motion toX
motion toY) +
<< depth));
if (depth == SEARCH_DEPTH)
bestMotion = motion;
if (alpha >= beta)
return beta;
return alpha;
/**
* Principal Variation SearchEngine method
* <p>Probably the best of the alpha beta variants this goes by
* several names: <em><b>NegaScout</b></em> <em>Principal Variation SearchEngine</em>
* or <em>PVS</em> for short The idea is that alpha beta search works
* best if the first recursive search is likely to be the one
* with the best score Techniques such as sorting the move list
* or using a best move stored in the hash table make it especially
* likely that the first move is best If it is we can search
* the other moves more quickly by using the assumption that
* they are not likely to be as good So PVS performs that first
* search with a normal window but on subsequent searches uses a
* zero width window to test each successive move against the first
* move Only if the zero width search fails does it do a normal search
* </p>
* <p>
* More detalis please visits:<br>
* <a >
* ICS Winter : Strategy and board game programming</a><br>
* or Read this paper:<br>
* Alexander Reinefild AN IMPROVEMENT TO THE SCOUT TREE SEARCH ALGORITHM
*
* </p>
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
final int principalVariationSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
situation makeMove(motions get( ) fromX motions get( ) fromY
motions get( ) toX motions get( ) toY);
int best = principalVariationSearch(depth beta alpha);
situation unMove();
if (depth == SEARCH_DEPTH)
bestMotion = motions get( );
for (int i = ; i < motions size(); i++)
if (best < beta)
if (best > alpha)
alpha = best;
Motion motion = motions get(i);
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = principalVariationSearch(depth alpha alpha);
if (score > alpha && score < beta)
// fail high re search
best = principalVariationSearch(depth beta score);
if (depth == SEARCH_DEPTH)
bestMotion = motion;
else if (score > best)
best = score;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
situation unMove();
return best;
/**
* Principal Variation with History Heuristic SearchEngine method(fail soft version)
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
@SuppressWarnings( unchecked )
final int principalVariationWithHHSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
if (depth <= )
return situation evaluate();
List<Motion> motions = situation generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH)
for (Motion motion : motions)
motion value = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX motion toY);
Collections sort(motions);
Motion motion = motions get( );
situation makeMove(motion fromX motion fromY
motion toX motion toY);
int best = principalVariationWithHHSearch(depth beta alpha);
situation unMove();
if (depth == SEARCH_DEPTH)
bestMotion = motion;
int oldValue = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX
motion toY);
HistoryHeuristicTable setValue(motions get( ) fromX
motions get( ) fromY
motions get( ) toX
motions get( ) toY
(oldValue + << depth));
for (int i = ; i < motions size(); i++)
if (best < beta)
if (best > alpha)
alpha = best;
motion = motions get(i);
situation makeMove(motion fromX motion fromY motion toX motion toY);
int score = principalVariationWithHHSearch(depth alpha
alpha);
if (score > alpha && score < beta)
best = principalVariationWithHHSearch(depth beta score);
if (depth == SEARCH_DEPTH)
bestMotion = motion;
else if (score > best)
int oldValue = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX
motion toY);
HistoryHeuristicTable setValue(motion fromX
motion fromY
motion toX
motion toY
(oldValue + << depth));
best = score;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
situation unMove();
return best;
/**
* Alpha Beta with Transposition Table search method
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
final int alphaBetaWithTranspositonSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
// lookup transposition table
int score = TranspositionTable lookup(depth alpha beta);
if (score != )
// hit the target!
return score;
if (depth <= )
score = situation evaluate();
// save the node
TranspositionTable save(NodeType exact depth score);
return score;
NodeType hashItemType = NodeType unknown;
List<Motion> motions = situation generatePossibleMoves();
for (Motion motion : motions)
int toId = situation makeMove(motion fromX motion fromY motion toX
motion toY);
score = alphaBetaWithTranspositonSearch(depth beta alpha);
situation unMove();
if (score > alpha)
alpha = score;
hashItemType = NodeType exact;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
if (alpha >= beta)
TranspositionTable save(NodeType lowerBound depth alpha);
return beta;
if (hashItemType != NodeType unknown)
TranspositionTable save(NodeType exact depth alpha);
else
TranspositionTable save(NodeType upperBound depth alpha);
return alpha;
/**
* NegaScout with History Heuristic and Transposition Table search
* @param depth depth 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 <code> WIN</code> if depth arrived
* returns evaluat value(leaf node value) otherwise returns bound(
* determined by cut off)
*/
@SuppressWarnings( unchecked )
final int negaScoutWithHHTTSearch(int depth int alpha int beta)
if (situation gameOver() != )
return WIN;
// lookup transpositiont table
int score = TranspositionTable lookup(depth alpha beta);
if (score != )
// hit the target!
return score;
if (depth <= )
score = situation evaluate();
TranspositionTable save(NodeType exact depth score);
return score;
List<Motion> motions = situation generatePossibleMoves();
// History heuristic
if (depth < SEARCH_DEPTH)
for (Motion motion : motions)
motion value = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX motion toY);
Collections sort(motions);
int bestmove = ;
int a = alpha;
int b = beta;
int t;
int oldValue;
NodeType hashItemType = NodeType unknown;
for (int i = ; i < motions size(); i++)
Motion motion = motions get(i);
int toId = situation makeMove(motion fromX motion fromY motion toX
motion toY);
t = negaScoutWithHHTTSearch(depth b a);
if (t > a && t < beta && i > )
a = negaScoutWithHHTTSearch(depth beta t);
hashItemType = NodeType exact;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
bestmove = i;
situation unMove();
if (a < t)
hashItemType = NodeType exact;
a = t;
if (depth == SEARCH_DEPTH)
bestMotion = motion;
if (a >= beta)
TranspositionTable save(NodeType lowerBound depth a);
oldValue = HistoryHeuristicTable getValue(motion fromX
motion fromY
motion toX
motion toY);
HistoryHeuristicTable setValue(motion fromX
motion fromY
motion toX
motion toY
(oldValue + << depth));
return a;
b = a + ; // set a new numm window
oldValue = HistoryHeuristicTable getValue(motions get(bestmove) fromX
motions get(bestmove) fromY
motions get(bestmove) toX
motions get(bestmove) toY);
HistoryHeuristicTable setValue(motions get(bestmove) fromX
motions get(bestmove) fromY
motions get(bestmove) toX
motions get(bestmove) toY
(oldValue + << depth));
if (hashItemType != NodeType unknown)
TranspositionTable save(NodeType exact depth alpha);
else
TranspositionTable save(NodeType upperBound depth alpha);
return a;
/**
* Constructor with parameters
* @param situation the specified situation
*/
public SearchEngine(Situation situation)
this situation = situation;
view plaincopy to clipboardprint? /*
* @(#)Book java
* Author: <>
* Created on Jun : : PM
*
* This program is free sofare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Sofare Foundation; either version 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 Sofare
* Foundation Inc Temple Place Suite Boston MA USA
*/
package cn edu ynu sei chinesechess infrastructure search;
import cn edu ynu sei chinesechesmon Situation;
import cn edu ynu sei chinesechess infrastructure fen FEN;
import cn edu ynu sei chinesechess infrastructure fen FENAccessor;
import java util HashMap;
import java util List;
import java util Map;
/**
* Opening book endgame book or any chessboard situation book
* Currently this class ONLY can read FEN file
* @author <>
* @version Jun
*/
final public class Book
/**
* book situation hash map
*/
public Map<Integer FEN> hashMap = new HashMap<Integer FEN>();
/**
* Packaged default constructor
*/
Book()
List<FEN> fens = FENAccessor readFile( book_final );
Integer hashCode = ;
for (FEN fen : fens)
hashCode = TranspositionTable calcCurHashCode(fen chessboard);
hashMap put(hashCode fen);
/**
* This book exists the specified chessboard situation?
* @param chessboard the specified chessboard
* @return if exists returns <code>true</code> otherwise
* returns <code>false</code>
*/
final public boolean exists(int[][] chessboard)
FEN f = hashMap get(TranspositionTable calcCurHashCode(chessboard));
if (f != null && f isBlackDone == false)
return true;
return false;
/*
* @(#)Book java
* Author: <>
* Created on Jun : : PM
*
* This program is free sofare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Sofare Foundation; either version 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 Sofare
* Foundation Inc Temple Place Suite Boston MA USA
*/
package cn edu ynu sei chinesechess infrastructure search;
import cn edu ynu sei chinesechesmon Situation;
import cn edu ynu sei chinesechess infrastructure fen FEN;
import cn edu ynu sei chinesechess infrastructure fen FENAccessor;
import java util HashMap;
import java util List;
import java util Map;
/**
* Opening book endgame book or any chessboard situation book
* Currently this class ONLY can read FEN file
* @author <>
* @version Jun
*/
final public class Book
/**
* book situation hash map
*/
public Map<Integer FEN> hashMap = new HashMap<Integer FEN>();
/**
* Packaged default constructor
*/
Book()
List<FEN> fens = FENAccessor readFile( book_final );
Integer hashCode = ;
for (FEN fen : fens)
hashCode = TranspositionTable calcCurHashCode(fen chessboard);
hashMap put(hashCode fen);
/**
* This book exists the specified chessboard situation?
* @param chessboard the specified chessboard
* @return if exists returns <code>true</code> otherwise
* returns <code>false</code>
*/
final public boolean exists(int[][] chessboard)
FEN f = hashMap get(TranspositionTable calcCurHashCode(chessboard));
if (f != null && f isBlackDone == false)
return true;
return false;
view plaincopy to clipboardprint? /*
* @(#)HistoryHeuristicTable java
* Author: <>
* Created on May : : PM
*
* This program is free sofare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Sofare Foundation; either version 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 Sofare
* Foundation Inc Temple Place Suite Boston MA USA
*/
package cn edu ynu sei chinesechess infrastructure search;
/**
* A <em>History Heuristic Table</em> maintains all best motion in
* the past
* (@link cn edu ynu mon Motion#value)
* @author <>
* @version Jun
*/
final class HistoryHeuristicTable
/**
* hold all best moves
*/
static int[][][][] holds = new int[ ][ ][ ][ ];
/**
* singleton
*/
private static HistoryHeuristicTable instance = new HistoryHeuristicTable();
/**
* Gets the single instance of the class
* @return history heuristic instance
*/
final public static HistoryHeuristicTable getInstance()
if (instance == null)
instance = new HistoryHeuristicTable();
return instance;
/**
* Private default constructor
*/
private HistoryHeuristicTable()
/**
* Returns the history motion
* @param fromX x coordinate of which chessman do this move
* @param fromY y coordinate of which chessman do this move
* @param toX x coordinate of which chessman s destination
* @param toY y coordinate of which chessman s destination
* @return this move s value
*/
final static int getValue(int fromX int fromY int toX int toY)
return holds[fromX][fromY][toX][toY];
/**
* Sets the history motion
* @param fromX x coordinate of which chessman do this move
* @param fromY y coordinate of which chessman do this move
* @param toX x coordinate of which chessman s destination
* @param toY y coordinate of which chessman s destination
* @param newValue the new value
*/
final static void setValue(int fromX int fromY int toX int toY int newValue)
holds[fromX][fromY][toX][toY] = newValue;
/*
* @(#)TranspositionTable java
* Author: <>
* Created on Jun : : AM
*
* This program is free sofare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Sofare Foundation; either version 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 Sofare
* Foundation Inc Temple Place Suite Boston MA USA
*/
package cn edu ynu sei chinesechess infrastructure search;
import java util Random;
/**
* A <em>Transpositon Table</em> maintains a mass of node had evaluated
* In the table we use <code>HashTable</code> to store each game tree node
* @author <>
* @version Jun
*/
final public class TranspositionTable
// XXX currently using bits hash code
/**
* transposition table s size
*/
final static int SIZE = * * ;
/**
* holds the chessboard condition<br>
* <ul>
* <li> : kinds of chessman from to </li>
* </li> : * matrics form chessboard
* </ul>
* @see cn edu ynu sei chinesechesmon Constants
* @see cn edu ynu sei chinesechesmon Situation#chessboard
*/
static int[][][] hashCodes = new int[ ][ ][ ];
/**
* the holds [ ] for min value and max value
*/
static HashNode[][] items = new HashNode[ ][SIZE];
/**
* a bits integer acts for current hash code
*/
static int curHashCode;
/**
* Transposition table hit count
*/
public static int hashHitCount = ;
/**
* singleton
*/
private static TranspositionTable instance = new TranspositionTable();
/**
* Gets the single instance
* @return transposition table single instance
*/
public static TranspositionTable getInstance()
if (instance == null)
instance = new TranspositionTable();
return instance;
/**
* Initializes the hash code of the specified chessboard situation
* @param chessboard the specified chessboard situation
*/
final static void initHashCode(int[][] chessboard)
curHashCode = calcCurHashCode(chessboard);
/**
* Private default constructor
*/
private TranspositionTable()
Random random = new Random();
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
for (int k = ; k < ; k++)
hashCodes[i][j][k] = Math abs(random nextInt());
for (int i = ; i < ; i++)
for (int j = ; j < SIZE; j++)
items[i][j] = new HashNode();
/**
* Calculates the hash code for the specified chessboard situation
* @param chessboard the specified chessboar situation
* @return bits hash code
*/
final public static int calcCurHashCode(int[][] chessboard)
int ret = ;
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
ret ^= hashCodes[chessboard[i][j]][i][j];
return ret;
/**
* Save a chessboard situation into transposition table
* @param type type of this hash item
* @param depth depth depth of search
* @param value value of this hash value
*/
final public static void save(NodeType type int depth int value)
// depth % : for max for min
HashNode item = items[depth % ][curHashCode % SIZE];
item depth = depth;
item hashCode = curHashCode;
item type = type;
item value = value;
/**
* Lookup a chessboard situation in transposition table
* @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 find the result returns value otherwise
* returns <code> </code>
*/
final public static int lookup(int depth int alpha int beta)
// depth % : for max for min
HashNode item = items[depth % ][curHashCode % SIZE];
if (item depth == depth && item hashCode == curHashCode)
hashHitCount++;
switch (item type)
case exact:
return item value;
case lowerBound:
if (item value >= beta)
return item value;
else
break;
case upperBound:
if (item value <= alpha)
return item value;
else
break;
// doesn t hit the target
return ;
/**
* Recovery the hash value of a motion had done
* @param fromX x coordinate of which chessman do this move
* @param fromY y coordinate of which chessman do this move
* @param toX x coordinate of which chessman s destination
* @param toY y coordinate of which chessman s destination
* @param chessmanId the target position s chessman
* @param chessboard current chessboard situation
*/
final public static void unMoveHash(int fromX int fromY int toX int toY
int chessmanId int[][] chessboard)
int toId = chessboard[toX][toY];
// retrieves the random number before the motion done
curHashCode ^= hashCodes[toId][fromX][fromY];
// removes chessman which position is toId
curHashCode ^= hashCodes[toId][toX][toY];
if (chessmanId != )
// recovery hash value chessman be eaten
curHashCode ^= hashCodes[chessmanId][toX][toY];
/**
* Generates the hash value of a motion on the current situation
* @param fromX x coordinate of which chessman do this move
* @param fromY y coordinate of which chessman do this move
* @param toX x coordinate of which chessman s destination
* @param toY y coordinate of which chessman s destination
* @param chessboard current chessboard situation
*/
final public static void moveHash(int fromX int fromY int toX int toY
int[][] chessboard)
int fromId toId;
fromId = chessboard[fromX][fromY];
toId = chessboard[toX][toY];
// removes chessman which position is fromId
curHashCode ^= hashCodes[fromId][fromX][fromY];
if (toId != )
// if toId position has a chessman removes it
curHashCode ^= hashCodes[toId][toX][toY];
// retrieves the random number at toId
curHashCode ^= hashCodes[fromId][toX][toY];
/**
* Hash item type description
*/
enum NodeType
/**
* the hash item s value had evaluated
*/
exact
/**
* the hash item s value is low bound
*/
lowerBound
/**
* the hash item s value is upper bound
*/
upperBound
/**
* the hash item s value is unknown
*/
unknown
;
/**
* Hash item description
*/
final class HashNode
/**
* bits hash code
*/
int hashCode;
/**
* item s type
*/
NodeType type = NodeType unknown;
/**
* search depth
*/
int depth;
/**
* item s value
*/
int value;
转载请保留作者信息
作者
Blog
cha138/Article/program/Java/hx/201311/26849相关参考
Java的垃圾回收之算法 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 引言 Java的堆是一
java设计模式之Template(算法的骨架) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
前几天读到google研究员吴军的数学之美系列篇颇有感触而恰好自己前段时间做了个基于统计语言模型的中文切分系统的课程项目于是乎帖出来与大家共同学习 分词技术在搜索引擎信息提取机器翻译等领域的重要
⒉空间复杂度 一个程序的空间复杂度(Spaceplexity)是指程序运行从开始到结束所需的存储量 程序的一次运行是针对所求解的问题的某一特定实例而言的例如求解排序问题的排序算法的每次执行是对
为了解决理解与执行这两者之间的矛盾人们常常使用一种称为伪码语言的描述方法来进行算法描述伪码语言介于高级程序设计语言和自然语言之间它忽略高级程序设计语言中一些严格的语法规则与描述细节因此它比程序设计
JAVA经典算法32题 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 【程序】题目古典问题有一对
读阳光人生的博弈智慧之学会共赢有感作文人生从某两个角度来看,是两个不同的转折点。有的人认为人生是悲剧是凄惨是幸福的结局甚至让自己没有生的希望,又有些人认为人生是新生的小草,湛蓝的海洋,应为他们都具有最
JavaSE6之脚本引擎让程序如虎添翼 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!现在JavaS
自从人类发现有地磁现象存在,就开始探索地磁起源的问题。人类最早、最朴素的想法就是地球是一块大磁体,北极是磁体的n极,南极是磁体的s极。这种想法不但中国古代有,在西方
有人说:对于今天的中国和美国,不再是博弈,而是合作,不再是掰手腕,而应该是握手。这种说法能够成立的依据是
有人说:对于今天的中国和美国,不再是博弈,而是合作,不再是掰手腕,而应该是握手。这种说法能够成立的依据是_____。A、双方没有利益上的冲突B、双方的综合国力水平相当C、双方有着相同的意识形态D、双方