import SearchEngine from '../SearchEngine' ; import Board from '../../common/Board' ; import Move from '../../common/Move' ; export default class AlphaBetaMiniMax extends SearchEngine { constructor ( ) { super ( ) ; } ; searchAGoodMove ( board , timeLimit ) { let timeCount = ( new Date ( ) ) . getTime ( ) ; this . bestMove = null ; this . currentBoard = board . clone ( ) ; let score = this . alphabeta ( this . maxDepth , this . evaluator . LOST , this . evaluator . WIN ) ; this . setStatus ( score ) ; console . log ( this . currentBoard . toString ( ) ) ; console . log ( "score:" + score ) ; console . log ( ( new Date ( ) . getTime ( ) - timeCount ) . toString ( ) + "ms" ) ; console . log ( "time limit:" + timeLimit + "ms" ) ; return this . bestMove ; } private alphabeta ( depth , alpha , beta ) { let layer = this . maxDepth - depth ; let isMaxLayer = ( layer % 2 == 0 ) ; let score = this . quickEvaluate ( layer ) ; if ( score != 0 ) return isMaxLayer ? score : - score ; if ( depth == 0 ) { score = this . evaluator . evaluate ( this . currentBoard ) ; return isMaxLayer ? score : - score ; } let possible = this . generator . getPossibleMoves ( this . currentBoard ) ; if ( possible . length == 0 ) { score = this . stalemate ( this . maxDepth - depth ) ; return isMaxLayer ? score : - score ; } if ( isMaxLayer ) { for ( let move of possible ) { this . doMove ( move ) ; score = this . alphabeta ( depth - 1 , alpha , beta ) ; this . undoMove ( ) ; if ( score > alpha ) { alpha = score ; if ( depth === this . maxDepth ) { this . bestMove = move . clone ( ) ; } } if ( alpha >= beta ) return beta ; } return alpha ; } else { for ( let move of possible ) { this . doMove ( move ) ; score = this . alphabeta ( depth - 1 , alpha , beta ) ; this . undoMove ( ) ; if ( score < beta ) { beta = score ; } if ( alpha >= beta ) return alpha ; } return beta ; } } } ;