/// <summary> /// alpha beta algorithm /// boardcoordlist- each item in this map contains a new board (representing a new state) and a list of 2 coords representing the move that brought to this new state /// mapBoardSrcDestCap- each item in this map contains the new board and source- dest coords (like above) and a list of captured coordinate (in case the new board is a result of a capture) /// </summary> /// <param name="board"></param> /// <param name="depth"></param> /// <param name="alpha"></param> /// <param name="beta"></param> /// <param name="player"></param> /// <param name="maxplayer"></param> /// <param name="srcCoord"></param> /// <param name="destCoord"></param> /// <param name="updateBoard"></param> /// <param name="captures"></param> /// <returns></returns> public int AlphaBeta(Board board, int depth, int alpha, int beta, Player player, bool maxplayer, ref Coordinate srcCoord, ref Coordinate destCoord, ref Board updateBoard, ref IList<Coordinate> captures) { var robj = new Rules(); if (depth == 0 || rule.IsBoardLeaf(player, board)) // is node a terminal node { var obj = new HeuristicFunction(); return obj.Evaluate(board, player); //return Heurisitic value of node } //Finds if there are any captures IDictionary<IList<Coordinate>, IList<Coordinate>> capturesAvailable = robj.FindCaptures(board, player); IDictionary<Board, IList<Coordinate>> boardCoordsList; //Calculating board according to current state (with or without captures) if (capturesAvailable.Count > 0) { boardCoordsList = robj.CreateNewBoards(board, capturesAvailable); } else { boardCoordsList = robj.CalculateNewBoardsFromCoordinates(board, player); } //values which save capture list , source, detination on the chosen move var minsrcCoord = new Coordinate(); var mindestCoord = new Coordinate(); var maxsrcCoord = new Coordinate(); var maxdestCoord = new Coordinate(); var maxCapturesList = new List<Coordinate>(); var minCapturesList = new List<Coordinate>(); var minBoard = new Board(); var maxBoard = new Board(); //player if (maxplayer) { foreach (var newState in boardCoordsList) { Coordinate newSrcCoord = newState.Value[0]; Coordinate newDestCoord = newState.Value[1]; IList<Coordinate> capturesList = robj.MapContainsCoords(capturesAvailable, newSrcCoord, newDestCoord); IList<Coordinate> tempCapList = new List<Coordinate>(); int res = AlphaBeta(newState.Key, depth - 1, alpha, beta, board.GetOpponent(player), !maxplayer, ref newSrcCoord, ref newDestCoord, ref updateBoard, ref tempCapList); if (res > alpha) { alpha = res; maxsrcCoord = newState.Value[0]; maxdestCoord = newState.Value[1]; maxBoard = newState.Key.Copy(); maxCapturesList = new List<Coordinate>(capturesList); } if (beta <= alpha) { break; } if (capturesList.Count > 0) { capturesAvailable.Remove(capturesList); } } srcCoord = maxsrcCoord; destCoord = maxdestCoord; updateBoard = maxBoard.Copy(); captures = maxCapturesList; return alpha; } //opponent else { foreach (var newState in boardCoordsList) { Coordinate newSrcCoord = newState.Value[0]; Coordinate newDestCoord = newState.Value[1]; IList<Coordinate> capturesList = robj.MapContainsCoords(capturesAvailable, newSrcCoord, newDestCoord); IList<Coordinate> tempCapList = new List<Coordinate>(); int res = AlphaBeta(newState.Key, depth - 1, alpha, beta, board.GetOpponent(player), !maxplayer, ref newSrcCoord, ref newDestCoord, ref updateBoard, ref tempCapList); if (res < beta) { beta = res; minsrcCoord = newState.Value[0]; mindestCoord = newState.Value[1]; minBoard = newState.Key.Copy(); minCapturesList = new List<Coordinate>(capturesList); } if (beta <= alpha) { break; } if (capturesList.Count > 0) { capturesAvailable.Remove(capturesList); } } srcCoord = minsrcCoord; destCoord = mindestCoord; updateBoard = minBoard.Copy(); captures = minCapturesList; return beta; } }