Пример #1
0
int Player1::alphaBeta (int depth, int alpha, int beta, bool MAXplayer)
{
	int heuristic = 0;	bool go = false;
	int temp;			char winner = 'N'; // 'N' for NULL
	
	go = isSolved(winner); // get heur info 

    if (depth == 3 || go ) // or node is a terminal node
	{
		heuristic = getHeuristic(depth, winner, !(MAXplayer));
        return heuristic;// value of the terminal game tree node
	}
	
    if (MAXplayer)	//for each child of node
	{ 
		for (int p = 0; p < 19; p++){
			for (int q = 0; q < 19; q++)
			{
				if (pOneBoard[p][q] == 'E' && playerDetected(p,q))
				{
					pOneBoard[p][q] = 'P';	// make move on board
					temp = alphaBeta(depth+1, alpha, beta, !(MAXplayer)); 

					// total recursive calls
					boardsExamined++; 

// -- maxmax start-
					//if (temp > alpha) alpha = temp; //a = max()
					//pOneBoard[p][q] = 'E'; //unmake move on board
// -- maxmax end---

// -- ab code start-
					if (temp < alpha) alpha = temp; //alpha = max()
					if (beta <= alpha) { pOneBoard[p][q] = 'E';break; } 
					else  pOneBoard[p][q] = 'E';	
// -- ab cod end ---	
				
				}}}

		return alpha; // α
	}
    else	//MINplayer	//for each child of node
	{    
		for (int p = 0; p < 19; p++){
			for (int q = 0; q < 19; q++)
			{
				if (pOneBoard[p][q] == 'E' && playerDetected(p,q))
				{
					pOneBoard[p][q] = 'T'; // make move on board
					temp = alphaBeta(depth+1, alpha, beta, !(MAXplayer)); 

					// total recursive calls
					boardsExamined++;

// -- maxmax start-
					//if (temp > beta) beta = temp; // β := max()
					//pOneBoard[p][q] = 'E'; //unmake move on board
// -- maxmax end---

// -- ab code start- 
					if (temp > beta) beta = temp; // β := min()
					if (beta <= alpha) { pOneBoard[p][q] = 'E'; break; }
					else pOneBoard[p][q] = 'E';		
// -- ab cod end --- 	

				}}}

		return beta;	// β 
	}
}
Пример #2
0
std::pair<int, Move> GameState::alphaBeta(int depth, int alpha, int beta, Player* player, Player* maximizingPlayer)
{
    int bestValue;
    Move bestMove;

    std::vector<Move> moves = getMoves(player);

    if (depth == 0 || moves.size() == 0)
    {
        return std::make_pair(getScore(maximizingPlayer), Move());
    }

    if (player == maximizingPlayer)
    {
        bestValue = -581357;

        for (Move move : moves)
        {
            board->doMove(move);

            std::pair <int, Move> pair = alphaBeta(depth - 1, alpha, beta, player->getOpponent(), maximizingPlayer);

            if (pair.first > bestValue) {
                bestValue = pair.first;
                bestMove = move;

                if (bestValue > alpha) {
                    alpha = bestValue;
                }
            }

            board->undoMove(move);

            if (beta <= alpha) {
                break;
            }
        }
        return std::make_pair(bestValue, bestMove);
    }

    else
    {
        bestValue = 581357;

        for (Move move : moves)
        {
            board->doMove(move);

            std::pair <int, Move> pair = alphaBeta(depth - 1, alpha, beta, player->getOpponent(), maximizingPlayer);

            if (pair.first < bestValue) {
                bestValue = pair.first;
                bestMove = move;

                if (bestValue < beta) {
                    beta = bestValue;
                }
            }

            board->undoMove(move);

            if (beta <= alpha) {
                break;
            }
        }
        return std::make_pair(bestValue, bestMove);
    }
}
Пример #3
0
int Board::alphaBeta(int depthLeft, int alpha, int beta, int doNullMove) {
	int check = 0;
	int oldAlpha = alpha;
	int numSearched = 0;
	int bestMove = 0;
	int hashMove = 0;
	int stage;
	int i = currentState->firstMove;
	int result;

	nodes++;
	nodesUntilUpdate--;
	if(nodesUntilUpdate <= 0) {
		switch(game->interfaceUpdate()) {
			case OUT_OF_TIME:

				abortingSearch = 1;
				return 0;
			break;

			case STOP_SEARCH:
				abortingSearch = 1;
				return 0;
			break;
		}

		nodesUntilUpdate = nodesPerUpdate;
	}



	if(isRepetition()) {
		returnMove = 0;
		return DRAW;
	}


	HashEntry *e;
	e = hash->probe(currentState->hashKey);

	if(e!=NULL) {
		hashHits++;
		//Is it useful for replacing this search - otherwise just find a best move
		hashMove = e->bestMove;
		returnMove = hashMove;

#ifndef DISABLE_HASH
		if(depth > 0 && e->depth >= depthLeft) {
			switch(e->flags & 3) {
				case HASH_EXACT:
					return e->score;
				break;

				case HASH_LOWER:
					if(e->score >= beta) return e->score;
					if(e->score > alpha) alpha = e->score;
				break;

				case HASH_UPPER:
					if(e->score <= alpha) return e->score;
					if(e->score < beta) beta = e->score;
				break;
			}

			if(e->flags & HASH_NO_NULL) {
				doNullMove = 0;
			}
		}
#endif
	}

#ifdef DEBUG_HASH
	if(hashMove > 0 && !testLegality(hashMove)) {
		print();
		cout << "Illegal hash move! ";
		printMove(hashMove);
		cout << endl;
	}
#endif


	if(depthLeft == 0) {
		int value =  quiescence(alpha, beta);
		//hash->store(0, value, 0, HASH_EXACT);
		return value;
	}


	check = inCheck();

/*
	if(doNullMove && !check && !nullRisk() && depth >= 2) {
		int nullDepth = depthLeft - 2;

		makeNullMove();

		if(nullDepth > 0) {
			result = alphaBeta(nullDepth, -beta, -beta+1, NO_NULL_MOVE);
		} else {
			result = quiescence(-beta, -beta+1);
		}

		retractNullMove();

		if(nullDepth > 0 && result >= beta) {
			result = alphaBeta(nullDepth, beta-1, beta, DO_NULL_MOVE);
			numMoves = currentState->firstMove;
		}


		if(result >= beta) {
			returnMove = 0;
			return beta;
		}
	}
*/

	if(!hashMove && depthLeft >= 3) {
		result = alphaBeta(depthLeft - 2, alpha, beta, DO_NULL_MOVE);
		numMoves = currentState->firstMove;

		//Failed low so have to research with new bounds
		if(result <= alpha) result = alphaBeta(depthLeft - 2, -MATE, alpha + 1, DO_NULL_MOVE);
		numMoves = currentState->firstMove;

		hashMove = returnMove;
	}

	if(hashMove > 0) {
		stage = HASH_MOVE;
	}	else {
		stage = ALL_MOVES;
	}

	while(stage != FINISHED) {
		switch(stage) {
			case HASH_MOVE:
				moveStack[numMoves++] = hashMove;
				stage = ALL_MOVES;
			break;
			case  ALL_MOVES:
				if(check) {
					generateCheckEvasions();
					sortNonCaptures(i, hashMove);
					stage = FINISHED;
				} else {
					generateCaptures();
					sortCaptures(i, hashMove);
					stage = NON_CAPTURES;
				}
			break;
			case NON_CAPTURES:
				generateNonCaptures();
				sortNonCaptures(i, hashMove);
				stage = FINISHED;
			break;
		}

	for(; i<numMoves; i++) {
			int move = moveStack[i];
			makeMove(move);

#ifdef DEBUG_BITBOARDS
				if(isMessedUp()) {
					printMoves();
					print();
					cout << "Hash move = "; printMove(hashMove); cout << endl;
					cout << "MakeMove" << endl;
					exit(0);
				}
#endif

			if(isLegal())  {
				numSearched++;

				result = -alphaBeta(depthLeft - 1, -beta, -alpha, DO_NULL_MOVE);
				retractMove(move);

				if(abortingSearch) {
					returnMove = bestMove;
					return result;
				}

				if(result > alpha) {
					if(result >= beta) {
						returnMove = move;
						hash->store(move, result, depthLeft, HASH_LOWER);

#ifdef EXTRA_STATS
						cutoffs++;
						if(i == currentState->firstMove) firstCutoffs++;
#endif
						return result;
					}


/*					if(depth == 0) {
						printMove(move);
						cout << " ";
						printScore(result);
						cout << " hashMove: ";
						printMove(hashMove);
						cout << endl;
					}*/

					alpha = result;
					bestMove = move;
				}


			} else { //Illegal move
				retractMove(move);
			}
#ifdef DEBUG_BITBOARDS
			if(isMessedUp()) {
				printMoves();
				print();
				cout << "Hash move = "; printMove(hashMove); cout << endl;
				cout << "RetractMove" << endl;
				exit(0);
			}
#endif
		}
	}		//While we have moves

		//No legal moves..
	if(numSearched ==0) {
		returnMove = 0;

		if(check)	{
			 return -(MATE - depth);
		} else {
			return DRAW;
		}
	}


	if(alpha == oldAlpha) {
		hash->store(bestMove, alpha, depthLeft, HASH_UPPER);

	} else {
		hash->store(bestMove, alpha, depthLeft, HASH_EXACT);
	}

	returnMove = bestMove;
	return alpha;
}
Пример #4
0
int Search::alphaBeta(bool white_turn, int depth, int alpha, int beta, Board& board, Transposition *tt,
		bool null_move_in_branch, Move (&killers)[32][2], int (&history)[64][64], int ply) {

	// If, mate we do not need search at greater depths
	if (board.b[WHITE][KING] == 0) {
		return -10000;
	} else if (board.b[BLACK][KING] == 0) {
		return 10000;
	}
	if (depth == 0) {
		return capture_quiescence_eval_search(white_turn, alpha, beta, board);
	}
	if (depth == 1) {
		// futility pruning. we do not hope for improving a position more than 300 in one move...
		int static_eval = evaluate(board);
		if (white_turn && (static_eval + 300) < alpha) {
			return capture_quiescence_eval_search(white_turn, alpha, beta, board);
		}
		if (!white_turn && (static_eval - 300) > beta) {
			return capture_quiescence_eval_search(white_turn, alpha, beta, board);
		}
	}
	if (depth == 2) {
		// extended futility pruning. we do not hope for improving a position more than 500 in two plies...
		// not really proven to +ELO but does not worse performance at least
		int static_eval = evaluate(board);
		if ((white_turn && (static_eval + 500) < alpha) || (!white_turn && (static_eval - 500) > beta)) {
			return capture_quiescence_eval_search(white_turn, alpha, beta, board);
		}
	}

	// null move heuristic - we do this despite in check..
	if (!null_move_in_branch && depth > 3) {
		// skip a turn and see if and see if we get a cut-off at shallower depth
		// it assumes:
		// 1. That the disadvantage of forfeiting one's turn is greater than the disadvantage of performing a shallower search.
		// 2. That the beta cut-offs prunes enough branches to be worth the time searching at reduced depth
		int R = 2; // depth reduction
		int res = alphaBeta(!white_turn, depth - 1 - R, alpha, beta, board, tt, true, killers, history, ply + 1);
		if (white_turn && res > alpha) {
			alpha = res;
		} else if (!white_turn && res < beta) {
			beta = res;
		}
		if (beta <= alpha) {
			if (white_turn) {
				return alpha;
			}
			return beta;
		}
	}
	MoveList moves = get_children(board, white_turn);
	if (moves.empty()) {
		return 0;
	}
	Transposition tt_pv = tt[board.hash_key % HASH_SIZE];
	for (auto it = moves.begin(); it != moves.end(); ++it) {
		// sort pv moves first
		if (tt_pv.next_move != 0 && tt_pv.hash == board.hash_key && tt_pv.next_move == it->m) {
			it->sort_score += 1100000;
		}
		// ...then captures in MVVLVA order
		if (!is_capture(it->m)) {
			// killer moves are quite moves that has previously led to a cut-off
			if (killers[ply - 1][0].m == it->m) {
				it->sort_score += 999999;
			} else if (killers[ply - 1][1].m == it->m) {
				it->sort_score += 899999;
			} else {
				// "history heuristics"
				// the rest of the quite moves are sorted based on how often they increase score in the search tree
				it->sort_score += history[from_square(it->m)][to_square(it->m)];
			}
		}
	}
	total_generated_moves += moves.size();

	Transposition t;
	t.hash = board.hash_key;
	int next_move = 0;
	for (unsigned int i = 0; i < moves.size(); ++i) {
		// late move reduction.
		// we assume sort order is good enough to not search later moves as deep as the first 4
		if (depth > 5 && i == 10) {
			depth -= 2;
		}

		pick_next_move(moves, i);
		Move child = moves[i];
		node_count++;
		make_move(board, child);

		int res = alphaBeta(!white_turn, depth - 1, alpha, beta, board, tt, null_move_in_branch, killers, history,
				ply + 1);
		unmake_move(board, child);
		if (res > alpha && res < beta) {
			// only cache exact scores

		}

		if (res > alpha && white_turn) {
			next_move = child.m;
			alpha = res;
			//history heuristics
			if (!is_capture(child.m)) {
				history[from_square(child.m)][to_square(child.m)] += depth;
			}
			// update pv
		}
		if (res < beta && !white_turn) {
			next_move = child.m;
			beta = res;
			//history heuristics
			if (!is_capture(child.m)) {
				history[from_square(child.m)][to_square(child.m)] += depth;
			}
			// update pv
		}
		if (beta <= alpha || time_to_stop()) {
			if (!is_capture(child.m)) {
				if (killers[ply - 1][0].m != child.m) {
					killers[ply - 1][1] = killers[ply - 1][0];
					killers[ply - 1][0] = child;
				}
			}
			break;
		}
	}
	t.next_move = next_move;
	tt[board.hash_key % HASH_SIZE] = t;
	if (white_turn) {
		return alpha;
	}
	return beta;
}
Пример #5
0
void Search::search_best_move(const Board& board, const bool white_turn, list history) {
	start = clock.now();

	Board b2 = board;
	MoveList root_moves = get_children(b2, white_turn);

	for (auto it = root_moves.begin(); it != root_moves.end(); ++it) {
		make_move(b2, *it);
		it->sort_score = evaluate(b2);
		unmake_move(b2, *it);
	}

	int alpha = INT_MIN;
	int beta = INT_MAX;
	int START_WINDOW_SIZE = 32;
	Move killers2[32][2];
	int quites_history[64][64] = { };
	Transposition * tt = new Transposition[HASH_SIZE];
	b2.hash_key = 0;
	for (int depth = 1; depth < 30;) {
		if (!white_turn) {
			for (auto it = root_moves.begin(); it != root_moves.end(); ++it) {
				it->sort_score = -it->sort_score;
			}
		}

		int score = white_turn ? alpha : beta;
		int a = alpha;
		int b = beta;
		MoveList next_iteration_root_moves;
		int pv[depth];
		for (unsigned int i = 0; i < root_moves.size(); i++) {
			// TODO only search best move with alpha, alpha + 1, if fail high/low there is another better move and we have to search all moves
			pick_next_move(root_moves, i);
			Move root_move = root_moves[i];
			if (b > a) { //strict?
				if (is_castling(root_move.m)) {
					Transposition * empty_tt = new Transposition[1000];
					int empty_quites_history[64][64] = { };
					int one_depth_score = alphaBeta(!white_turn, 1, INT_MIN / 2, INT_MAX / 2, b2, empty_tt,
					true, killers2, empty_quites_history, 1);
					delete empty_tt;
					if ((white_turn && one_depth_score < -5000) || (!white_turn && one_depth_score > 5000)) {
						// we are in check and castling is illegal. The move is not copied to the next iteration.
						root_move.sort_score = one_depth_score;
						continue;
					}
				}
				node_count++;
				make_move(b2, root_move);
				int res = -1; // TODO clean up code
				for (auto hit = history.begin(); hit != history.end(); ++hit) {
					if (is_equal(b2, *hit)) {
						// draw by repetition
						res = 0;
					}
				}
				if (res == -1) {
					res = alphaBeta(!white_turn, depth - 1, a, b, b2, tt, false, killers2, quites_history, 1);
				}
				unmake_move(b2, root_move);
				if (res > a && white_turn) {
					score = res;
					a = res;
					// TODO extract method get_pv
					for (int p = 1; p < depth; p++) {
						pv[p] = 0;
					}
					pv[0] = root_move.m;
					int next_pv_move = root_move.m;
					int hash = b2.hash_key;
					for (int p = 1; p < depth - 1; p++) {
						hash ^= next_pv_move;
						Transposition next = tt[hash % HASH_SIZE];
						if (next.hash == hash && next.next_move != 0) {
							pv[p] = next.next_move;
							next_pv_move = next.next_move;
						} else {
							break;
						}
					}
				}
				if (res < b && !white_turn) {
					score = res;
					b = res;
					for (int p = 1; p < depth; p++) {
						pv[p] = 0;
					}
					pv[0] = root_move.m;
					int next_pv_move = root_move.m;
					int hash = b2.hash_key;
					for (int p = 1; p < depth - 1; p++) {
						hash ^= next_pv_move;
						Transposition next = tt[hash % HASH_SIZE];
						if (next.hash == hash && next.next_move != 0) {
							pv[p] = next.next_move;
							next_pv_move = next.next_move;
						} else {
							break;
						}
					}
				}
				root_move.sort_score = res;
			} else {
				// beta fail
				// we just know that the rest of the moves are worse than the best move, or is this un-reachable code?
				root_move.sort_score = white_turn ? a - i : b + i; // keep sort order
			}
			next_iteration_root_moves.push_back(root_move);
		}
		int time_elapsed_last_depth_ms = std::chrono::duration_cast < std::chrono::milliseconds
				> (clock.now() - start).count();
		if (score > alpha && score < beta) {
			std::string pvstring = pvstring_from_stack(pv, depth);
			// uci score is from engine perspective
			int engine_score = white_turn ? score : -score;
			std::cout << "info score cp " << engine_score << " depth " << depth << " time "
					<< time_elapsed_last_depth_ms << " nodes " << node_count << " pv " << pvstring << "\n"
					<< std::flush;

			std::stringstream ss(pvstring);
			getline(ss, best_move, ' ');
		}
		if (time_to_stop()) {
			break;
		}
		// aspiration window based on previous score - use delta to increase if no moves are found...
		int window_size = beta - alpha;
		if (score <= alpha) {
			// failed low, search again at same depth
			alpha = alpha - window_size;
			continue;
		}
		if (score >= beta) {
			// failed high, search again at same depth
			beta = beta + window_size;
			continue;
		}

		root_moves = next_iteration_root_moves;

		// aspiration window size
		alpha = score - START_WINDOW_SIZE / 2;
		beta = score + START_WINDOW_SIZE / 2;

		// if mate is found at this depth, just stop searching for better moves. Cause there are none.. The best move at the last depth will prolong the inevitably as long as possible.
		if ((white_turn && score < -5000) || (!white_turn && score > 5000)) {
			// we are mated...
			break;
		}
		if (abs(score) > 5000) {
			// deliver mate
			break;
		}

		// save some time for next move
		if ((4 * time_elapsed_last_depth_ms) > max_think_time_ms) {
			break;
		}
		depth++;
	}
	delete tt;
	std::cout << "bestmove " << best_move << std::endl << std::flush;
	return;
}
Пример #6
0
/* Performs an alpha-beta search from the given board and returns the number of nodes visited */
int getAlphaBetaTreeSize(rep_t rep, int side, int depth, heuristics_t heuristic , int budget) {
  numNodes = termCount = 0; // reset node and terminal node counts
  alphaBeta(rep , 0, depth, side, _DOM->min_wins, _DOM->max_wins, heuristic, budget, id); // run specified alpha-beta search
  return numNodes; // return number of nodes expanded (updated by call to alphaBeta above)
}
Пример #7
0
/* Perform alpha-beta search from given board position, and make the best move
   The set of bestMoves is returned via parameter bestMoves[] */
int makeMinmaxMove(rep_t rep, int* side, int depth, heuristics_t heuristic, int budget, int randomTieBreaks, int noisyMM, int* bestMoves, int* numBestMoves, double* termPercentage, double *moveVals) {
  int i;
  rep_t dummyRep;
  double val;
  int bestMove = NULL_MOVE;
  int secondBestMove = NULL_MOVE;
  double bestScore;
  double secondBestScore = -INF;
  int origSide = *side;
  double scores[_DOM->getNumOfChildren(rep, origSide)];
  double die;

  numNodes = 0; // reset node count
  *numBestMoves = 0; // reset number of best moves
  termCount = 0; // reset terminal nodes count
  
  for (i = 1; i < _DOM->getNumOfChildren(rep, origSide); i++) { // iterate over all possible moves
    *side = origSide;
    if (!_DOM->isValidChild(rep,*side,i))
	continue;
   dummyRep = _DOM->cloneRep(rep);// clone starting board so it can be restored on next pass through loop
   _DOM->makeMove(dummyRep,side,i);// generate i^th child

    // Compute MM-(k-1) value of i^th child (since the children are already at depth 1 from the root node,
    // and we do a search from each child)
    val = alphaBeta(dummyRep , 1, depth, *side, _DOM->min_wins, _DOM->max_wins, heuristic, budget, id);
    _DOM->destructRep(dummyRep);
    // If this was min's move, negate the utility value (this makes things a little cleaner
    // as we can then always take the max of the children, since min(s1,s2,...) = -max(-s1,-s2,...))    
    scores[i] = (origSide == min) ? -val : val;

    if (moveVals != 0)
      moveVals[i-1] = val;
    
    // If this is either the first child, or the best scoring child, store it
    if ((*numBestMoves == 0) || (scores[i] > bestScore)) {
      bestMoves[0] = i;
      bestScore = scores[i];
      *numBestMoves = 1;
    }
    // If this child ties with the best scoring child, and random tie-breaking is enabled, store it
    else if ((scores[i] == bestScore) && (randomTieBreaks))
      bestMoves[(*numBestMoves)++] = i;

    if (verbose)
      printf("Move # %d -- Value %f\n", i, val);
  }
  *side = origSide;
  bestMove = bestMoves[random() % *numBestMoves]; // pick a best move at random among the set of best moves

  if (verbose)
    printf("Value of root node: %f\n", (origSide == min) ? -bestScore : bestScore);

  // Find second best move -- note that the score of the second best move must be within 3 of the best move
  // In case there is no such second best move, the index remains set to its initial value of NULL_MOVE
  for (i = 1; i < _DOM->getNumOfChildren(rep,*side); i++) {
    if (!_DOM->isValidChild(rep,*side,i))
	continue;
    if (scores[i] != bestScore) {
      if ((bestScore - scores[i] <= 3.0) && (scores[i] > secondBestScore)) {
	secondBestScore = scores[i];
	secondBestMove = i;
      }
    }
  }

  if (verbose)
    printf("Best move: %d \t Second best move: %d\n", bestMove, secondBestMove);

  // If 'noisy MM' option was selected at command-line and there is a candidate second-best move,
  // flip a coin and determine whether to pick that over the best move
  if ((secondBestMove != NULL_MOVE) && (noisyMM)) {
    assert(heuristic != (heuristics_t)_DOM->hFunctions.h3); // could mess up if using playouts to estimate leaves, so flag for now
    die = (double)(random() % 10000) / (double)(10000 - 1);
    if (die <= EPSILON)
      bestMove = secondBestMove;
  }

  if (verbose)
    printf("Examined %d nodes\n", numNodes);

  *termPercentage = (double)termCount / (double)numNodes; // compute percentage of nodes in tree that were terminal

  return bestMove;
}
Пример #8
0
////////////////////////////////////////////////////////////////////////////////
// alphaBeta 
////////////////////////////////////////////////////////////////////////////////
int Game::alphaBeta(ChessBoard *board, const int depth, int alpha, const int beta) 
{
	if(m_evalCount % 1000 == 0)
	{
		if(timeUp())
			m_bInterrupted = true;
	}
	if(m_bInterrupted){
		return alpha; //
	}
	int value = 0;

	// 50 move rule and repetition check
	if(board->checkEnded()){
		return ChessBoard::VALUATION_DRAW;
        }
	board->scoreMovesPV(m_arrPVMoves[m_searchDepth - depth]);
	
	int best = (-ChessBoard::VALUATION_MATE)-1;
	int move = 0;
	ChessBoard *nextBoard = m_boardFactory[depth];
	
	while (board->hasMoreMoves()) 
	{
		move = board->getNextScoredMove();
		board->makeMove(move, nextBoard);

                // self check is illegal!
                if(nextBoard->checkInSelfCheck()){
			// not valid, remove this move and continue
			//DEBUG_PRINT("#", 0);
			board->removeMoveElementAt();
			continue;
		}

		// generate the moves for this next board in order to validate the board
		nextBoard->genMoves();
		
		if(nextBoard->checkInCheck()){
                        //DEBUG_PRINT("+", 0);

			nextBoard->setMyMoveCheck();
			move = Move_setCheck(move);
		}
		// ok valid move

#if DEBUG_LEVEL & 1
	char buf[20];
	Move::toDbgString(move, buf);
	DEBUG_PRINT("\n%d %s > ", depth, buf);	
#endif

                // at depth one is at the leaves, so call quiescent search
		if(depth == 1)
		{
			value = -quiesce(nextBoard, QUIESCE_DEPTH, -beta, -alpha);
                    
		}
		else  
		{
			value = -alphaBeta(nextBoard, depth-1,-beta,-alpha);
		}

		if(value > best)
		{
			best = value;
                        m_arrPVMoves[m_searchDepth - depth] = move;
		}
		
		if(best > alpha)
		{
#if DEBUG_LEVEL & 1
	DEBUG_PRINT("$ best > alpha %d > %d ", best, alpha);	
#endif

                    alpha = best;
		}
		
		if(best >= beta){
#if DEBUG_LEVEL & 1
	DEBUG_PRINT("$ best >= beta break, %d > %d\n", best, beta);
#endif


			break;
                }
		
	}
	// no valid moves, so mate or stalemate
	if(board->getNumMoves() == 0){
		//DEBUG_PRINT("@", 0);
		if(Move_isCheck(board->getMyMove())){
                    #if DEBUG_LEVEL & 1
                        DEBUG_PRINT("\nMate #\n", 0);
                    #endif
                    return (-ChessBoard::VALUATION_MATE);
		}
                #if DEBUG_LEVEL & 1
                    DEBUG_PRINT("\nStalemate\n", 0);
                #endif
		return ChessBoard::VALUATION_DRAW;
	}

        #if DEBUG_LEVEL & 4
            DEBUG_PRINT("\n==> alphaBeta #moves: %d\n", board->getNumMoves());
        #endif


	return best;
}
Пример #9
0
/* Recursively compute the minimax value of a given node, with alpha-beta pruning. The search is cutoff
   at a maximum depth given by depth. searchDepth keeps track of how deep we already are in the tree */ 
static double alphaBeta(rep_t rep, int searchDepth, int depth, int side, double alpha, 
			double beta,heuristics_t heuristic,
		       	int budget,
			int currentNodeId) {
  double val1, val2;
  int i;
  int origSide = side;
  rep_t dummyRep;
  numNodes++; // track number of nodes expanded
  
  // Hit terminal node -- return value is one of {MAX_WINS, MIN_WINS, DRAW}
  if ((val1 = _DOM->getGameStatus(rep)) != _DOM->incomplete) {
    termCount++; // update terminal node count
    if (dotFormat)
      printf("n%d [color=\"red\"];", currentNodeId); // terminal nodes are colored red
      
    if (_DOM->dom_name == GGP && heuristic == _DOM->hFunctions.h2)
      val1 /= _DOM->max_wins;
    
    return val1;
  }

  // Hit search depth cutoff -- apply the chosen heuristic function to this node and return that value
  if (searchDepth >= depth) {

    val1 = heuristic(rep, side, budget);

    // Ensure that the heuristic value is always bounded by the values assigned to terminal nodes (i.e. true win/loss
    // positions)
    assert ((val1 <= _DOM->max_wins) && (val1 >= _DOM->min_wins));

    return val1;
  }

  // Otherwise, recurse
  if (side == max) { // at a Max node
    val1 = alpha;
    for (i = 1; i < _DOM->getNumOfChildren(rep, side); i++) { // iterate over all possible moves
      side = origSide;
      if (!_DOM->isValidChild(rep,side,i))
	      continue;
      dummyRep = _DOM->cloneRep(rep);// clone starting board so it can be restored on next pass through loop
      _DOM->makeMove(dummyRep,&side,i);// generate i^th child
      // About to visit a new node, so add the edge to the graph
      if (dotFormat)
	printf("n%d -> n%d;\n", currentNodeId, ++id);
      val2 = alphaBeta(dummyRep , searchDepth+1, depth, side, val1, beta, heuristic, budget, id); // compute minimax value of this child
      _DOM->destructRep(dummyRep);
      val1 = (val2 > val1) ? val2 : val1; // we have tightened our alpha bound
      if (val1 >= beta) // we have a beta-cutoff 
	return beta;
    }
  }
  else { // at a Min node
    val1 = beta;
    for (i = 1; i < _DOM->getNumOfChildren(rep, side); i++) { // iterate over all possible moves
      side = origSide;
      if (!_DOM->isValidChild(rep,side,i))
	continue;
      dummyRep = _DOM->cloneRep(rep);// clone starting board so it can be restored on next pass through loop
      _DOM->makeMove(dummyRep,&side,i);// generate i^th child
      // About to visit a new node, so add the edge to the graph
      if (dotFormat)
	printf("n%d -> n%d;\n", currentNodeId, ++id);
      val2 = alphaBeta(dummyRep, searchDepth+1, depth, side, alpha, val1, heuristic, budget, id); // compute minimax value of this child
      _DOM->destructRep(dummyRep);
      val1 = (val2 < val1) ? val2 : val1; // we have tightened our beta bound
      if (val1 <= alpha) // we have an alpha-cutoff
	return alpha;
    }
  }

  return val1;
}
Пример #10
0
int alphaBeta(vertex Node,int alpha, int beta,int player,int depth,int maxdepth,linked_list (*create_children)(int *gameMatrix, int player,int *error),int* error){
	int aboveAlpha=alpha,aboveBeta=beta;
	int temp,childError;
	vertex child;
	element run;
	linked_list new_children;
	
	/* end-cases, return a score for some leaf */
	if (depth>=maxdepth || Node->edges->head==NULL){
		temp= Node->score;
		if(depth>1){
			remove_tree(Node,0,0);
		}
		*error=0;
		return temp;
	}
	
	if (player==ENUM_PLAYER_1){
		/* for every node */
		for (run = Node->edges->head;run != NULL; run = run->next){
			child=run->node;
			if (depth<maxdepth-1){
				int create_childrenError=0;
				/*create a new level of children*/
				new_children=create_children(child->game_state, player*-1,&create_childrenError);
				if(create_childrenError==-1){
					printf("ERROR: can't create children\n");
					*error=-1;
					return 0;
				}
				child->edges=new_children;
			}
			/* continue this process on the next level */
			temp=alphaBeta(child,alpha,beta,player*-1,depth+1,maxdepth,create_children,&childError);
			if (childError==-1){
				*error=-1;
				return 0;
			}
			/* we now have a score from the subtreee*/
			if(aboveAlpha < temp){
				aboveAlpha=temp;
			}
			/* perfom pruning on this level */
			if (aboveBeta<=aboveAlpha){
				for ( run = run->next;run != NULL; run = run->next){
					child=run->node;
					if(depth>0){
						remove_tree(child,0,0);
					}
				}
				break;
			}
			
		}
		/* taking max */
		Node->score=aboveAlpha;
		if(depth>1){
			remove_tree(Node,0,0);
		}
		*error=0;
		/*return some score*/
		return aboveAlpha;
	}
	/* perform the same process with roles reversed */
	else {
		for (run = Node->edges->head;run != NULL; run = run->next){
			child=run->node;
			if (depth<maxdepth-1){
				int create_childrenError=0;
				new_children=create_children(child->game_state, player*-1,&create_childrenError);			// add children
				if(create_childrenError==-1){
					printf("ERROR: can't create children\n");
					*error=-1;
					return 0;
				}
				child->edges=new_children;
			}
			temp=alphaBeta(child,alpha,beta,player*-1,depth+1,maxdepth,create_children,&childError);
			if (childError==-1){
				*error=-1;
				return 0;
			}
			if(aboveBeta > temp){
				aboveBeta=temp;
			}
			if (aboveBeta<=aboveAlpha){
				for ( run = run->next;run != NULL; run = run->next){
					child=run->node;
					if(depth>0){
						remove_tree(child,0,0);
					}
				}
				break;
			}
		}
		Node->score=aboveBeta;
		if(depth>1){
			remove_tree(Node,0,0);
		}
		*error=0;
		return aboveBeta;
	}
}
Пример #11
0
boolean Game::alphaBetaRoot(const int depth, int alpha, const int beta)
{

	if(m_bInterrupted){
		return false; //
	}
	int value = 0;

	
	m_board->scoreMovesPV(m_arrPVMoves[m_searchDepth - depth]);

	int best = (-ChessBoard::VALUATION_MATE)-1;
	int move = 0, bestMove = 0;
	ChessBoard *nextBoard = m_boardFactory[depth];

	while (m_board->hasMoreMoves())
	{
		move = m_board->getNextScoredMove();
		m_board->makeMove(move, nextBoard);
                // self check is illegal!
		if(nextBoard->checkInSelfCheck()){
			// not valid, remove this move and continue
			//DEBUG_PRINT("#", 0);
			m_board->removeMoveElementAt();
			continue;
		}

		// generate the moves for this next board in order to validate the board
		nextBoard->genMoves();

#if DEBUG_LEVEL & 1
    //char bbuf[2048];
    //nextBoard->printB(bbuf);
    //DEBUG_PRINT("\n%s\n", bbuf);
#endif          
		if(nextBoard->checkInCheck()){
#if DEBUG_LEVEL & 1
    DEBUG_PRINT("!", 0);
#endif
			nextBoard->setMyMoveCheck();
			move = Move_setCheck(move);
		}
		// ok valid move

#if DEBUG_LEVEL & 1
	char buf[20];
	Move::toDbgString(move, buf);
	DEBUG_PRINT("\n====== %s [ > ", buf);
#endif

                // at depth one is at the leaves, so call quiescent search
		if(depth == 1)
		{
			value = -quiesce(nextBoard, QUIESCE_DEPTH, -beta, -alpha);
		}
		else
		{
                    // if not PV then narrow search window
                    
			value = -alphaBeta(nextBoard, depth-1,-beta,-alpha);
		}

        
#if DEBUG_LEVEL & 1
	DEBUG_PRINT(":: %d ", value);
#endif
		if(value > best)
		{
			best = value;
			bestMove = move;
                        m_arrPVMoves[m_searchDepth - depth] = move;
		}

		if(best > alpha)
		{
			//co.pl(" a= " + best);
			alpha = best;
		}

		if(best >= beta){

#if DEBUG_LEVEL & 1
	DEBUG_PRINT("\nBreak out main loop %d\n", best);
#endif
                    break;
                }

	}


#if DEBUG_LEVEL & 1
	DEBUG_PRINT("]",0);
#endif

        // we're interrupted, no move and no value!
        if(m_bInterrupted)
            return false;

        m_bestMove = bestMove;
        m_bestValue = best;

        if(m_board->getNumMoves() <= 1){
            if(m_board->getNumMoves() == 0){
                DEBUG_PRINT("NO moves in aphaBetaRoot!", 0);
            }

#if DEBUG_LEVEL & 1
    DEBUG_PRINT("\n==> alphaBetaRoot NO continuation %d\n", m_board->getNumMoves());
#endif

            // do not contine, so return false
            return false;
	}
#if DEBUG_LEVEL & 1
    DEBUG_PRINT("\n==> alphaBetaRoot continue %d\n", m_board->getNumMoves());
#endif

        return true;
}
Пример #12
0
const SEARCH_RETURN AI::alphaBeta(Board& board, EXPECTED_VALUE alpha, EXPECTED_VALUE beta, int depth)
{
#ifdef DEBUG
  string merp(board.toString());
  cout<<endl<<endl;
  for(Uint8 space = 6 - depth; space > 0; space--)
    cout<<' ';
  cout<<"  0 1 2 3 4 5 6 7 8 9"<<endl<<endl;  
  for(Uint8 y = 0; y < board.getDim().y(); y++)
  {
    for(Uint8 space = 6 - depth; space > 0; space--)
      cout<<' ';
    cout<<char('A'+y)<<' ';
    for(Uint8 x=0; merp[y*20+x] != '\n'; x++)
    {
      cout<<merp[y*20+x];
    }
    cout<<endl;
  }
  for(Uint8 space = 6 - depth; space > 0; space--)
    cout<<' ';
  cout<<"Value for current game: "<<evaluate(board)<<endl;
#endif
  
  if(depth == 0 || board.won() != NULL)
  {
    return SEARCH_RETURN(quiEvaluate(board) - depth, Move(NULL, NULL, NULL));
    //return quiesce(n);
  }
  
  EXPECTED_VALUE score, bestScore = -10000000;
  Move ret(NULL, NULL, NULL);
  
  //BoardNode next {n.b, n.depth, NULL, NULL, n.b.nextIn(n.b.whosTurn())==NULL? -n.beta:n.alpha, n.b.nextIn(n.b.whosTurn())==NULL? -n.alpha:n.beta};
  vector<Piece> &pieces = board.getPieceList(board.whosTurn());
  
  Move next(NULL, NULL, &board);
  
  for(auto i = pieces.begin(); i != pieces.end(); i++)
  {
    if(next.setPiece(board.nextIn(board.whosTurn())))
    {
      if(next.getPiece() != &*i)
        continue;
    }
    auto validLocations = board.getValid(&*i);
    for(auto c = validLocations.begin(); c != validLocations.end(); c++)
    {
      next.setPiece(&*i);
      next.setCell(*c);
      if(!next.doMove())
	continue;
      if(board.nextIn(board.whosTurn()))
      {
	score = alphaBeta(board, alpha, beta, depth-1).val;
      }
      else
      {
	score = -alphaBeta(board, -beta, -alpha, depth-1).val;
      }
      
      next.undoMove();
      
#ifdef DEBUG
  if(merp != string(board.toString()))
  {
    for(Uint8 fucksGiven = 99; fucksGiven > 0; fucksGiven--)
      cout<<"YOU F****D UP! ";
    cout<<endl<<"I guess you really don't give a f**k"<<endl;
    merp = board.toString();
    for(Uint8 space = 6 - depth; space > 0; space--)
      cout<<' ';
    cout<<"  0 1 2 3 4 5 6 7 8 9"<<endl<<endl;  
    for(Uint8 y = 0; y < board.getDim().y(); y++)
    {
      for(Uint8 space = 6 - depth; space > 0; space--)
        cout<<' ';
      cout<<char('A'+y)<<' ';
      for(Uint8 x=0; merp[y*20+x] != '\n'; x++)
      {
        cout<<merp[y*20+x];
      }
      cout<<endl;
    }
    for(Uint8 space = 6 - depth; space > 0; space--)
      cout<<' ';
    cout<<"Value for current game: "<<evaluate(board)<<endl;
    while(getchar() != '\n');
  }
  
  for(Uint8 space = 6 - depth; space > 0; space--)
    cout<<' ';
  cout<<"  0 1 2 3 4 5 6 7 8 9"<<endl<<endl;  
  for(Uint8 y = 0; y < board.getDim().y(); y++)
  {
    for(Uint8 space = 6 - depth; space > 0; space--)
      cout<<' ';
    cout<<char('A'+y)<<' ';
    for(Uint8 x=0; merp[y*20+x] != '\n'; x++)
    {
      cout<<merp[y*20+x];
    }
    cout<<endl;
  }
  for(Uint8 space = 6 - depth; space > 0; space--)
    cout<<' ';
  cout<<"Value for current game: "<<evaluate(board)<<endl;
#endif
      
      if(score >= beta)
	return SEARCH_RETURN(beta, next);
      
      if(score > bestScore)
      {
	bestScore = score;
	if(score > alpha)
	  alpha = score;
	ret = next;
      }
      
    }
  }
  
  return SEARCH_RETURN(bestScore, ret);
}
Пример #13
0
	std::pair<int, int> algorithm(const Board& board, int depth, bool whiteOnTurn)
	{
		Move currentBestMove = { 0, 0, 0 }; // Container for best value and the move to get there

		int a = MIN; // Alpha
		int b = MAX; // Beta
		currentBestMove.value = (whiteOnTurn) ? a : b;

		// 1. Get number of threads that system can manage
		unsigned int num_of_threads = THREADS;
		std::srand((int)std::time(0));

		// 2. Get all possible moves and divide them as tasks to threads
		std::vector<Move> possibleMoves = getAllPossibleMoves(board, whiteOnTurn);
		// In other cases can proceed to dividing tasks for threads
		taskVectors.clear(); // Must be cleared so it's empty on start
		taskVectors = divideForThreads(possibleMoves, (int)num_of_threads);

		// 3. Create threadpool and run tasks with threads
		std::vector<std::thread> threads;

		// Lambda
		auto lambda = [depth, whiteOnTurn](Board board, int i, int la, int lb)
		{
			// This is what the thread does to its tasks 
			// This also works as 1st level of algorithm (because of alphaBeta structure)
			std::srand((int)std::time(0)); // Use current time as a seed for random
			
			// Copy taskVektor so it can be used
			threadMutex.lock();
			std::vector<Move> tasks = taskVectors[i];
			threadMutex.unlock();
			Move bestThreadMove = { 0, 0, 0};
			bestThreadMove.value = (whiteOnTurn) ? la : lb;

			for (auto move : tasks) {
				move.value = (whiteOnTurn) ? la : lb; // For white turn=>MIN black=>MAX
				Board new_board = board;
				new_board.movePiece(move.origin, move.destination);
				new_board.updateState(move.destination, 1);

				int temp = alphaBeta(new_board, depth - 1, la, lb, !whiteOnTurn);

				// Recursive part depth needs to decrease now depth at its maximum
				if (whiteOnTurn) {
					if ((bestThreadMove.value < temp) || (bestThreadMove.value == temp && (rand() % 8 == 1))) {
						bestThreadMove = move;
						bestThreadMove.value = temp;
					}
					la = std::max(la, bestThreadMove.value);
				} else {
					if ((bestThreadMove.value > temp) || (bestThreadMove.value == temp && (rand() % 8 == 1))) {
						bestThreadMove = move;
						bestThreadMove.value = temp;
					}
					lb = std::min(lb, bestThreadMove.value);
				}

				if (lb <= la)
				{
					break; // Cut off bad branch
				}

				// Randomly pick if as good as current

			}

			threadMutex.lock(); // Must be logged so that threads wont do this same time
			{
				taskVectors[i].clear();
				taskVectors[i].push_back(bestThreadMove);
			}
			threadMutex.unlock();
		};

		// Create threads and push them in vector
		for (unsigned int i = 0; i < taskVectors.size(); i++) {
			// Some magic with lambda functions
			threads.push_back(std::thread(lambda, board, i, a, b));
			//std::cout << "Started thread number " << i + 1 << std::endl;
		}

		//int i = 1; //This is for the cout below
		// 4. Wait threads to finish
		for (auto thread = threads.begin(); thread != threads.end(); thread++)
		{
			//std::cout << "Waiting for thread number " << i << " to finish." << std::endl;
			thread->join();
			//std::cout << "Thread number " << i++ << " finished." << std::endl;

		}

		// 5. Choose best value
		for (auto list : taskVectors) {
			for (auto move : list) {
				// White turn
				if (move.value > currentBestMove.value && whiteOnTurn) {
					currentBestMove = move; // Replace with better one
				}
				// Black turn
				else if (move.value < currentBestMove.value && !whiteOnTurn) {
					// To have some random factor if same values
					currentBestMove = move;
				}
				else if (move.value == currentBestMove.value && (rand() % 8 == 1)) {
					currentBestMove = move;
				}
			}
		}
		if (currentBestMove.origin == 0 && currentBestMove.destination == 0) {
			std::cout << "Illegal move [0,0]" << std::endl;
		}
		//std::cout << "Returning with move [" << currentBestMove.origin << "," << currentBestMove.destination <<  "]" << ", its value is " << currentBestMove.value << std::endl;

		return std::make_pair(currentBestMove.origin ,currentBestMove.destination);
	}
Пример #14
0
	int alphaBeta(const Board& board, int depth, int a, int b, bool maximizingPlayer)
	{
		if( depth == 0 )  // Check if the algorithm has reached it's depth
		{
			if(board.isStaleMate(maximizingPlayer))  //before evaluation see if it's stalemate or checkmate
			{
				// Do some stuff to end the game
				if(board.isCheck(maximizingPlayer))
				{
					if(maximizingPlayer)
						return MIN + 100;
					else
						return MAX - 100;
				}
				else
				{
					return 0;
				}
			}
			return evaluate(board);
		}
		// Find all own pieces
		if (maximizingPlayer) // White players turn
		{

			int v = MIN; // Smallest int
			for(int i = 0; i < 64; i++)// Iterate through the board
			{
				if(board.getBoard()[i]%2 == 1)// If piece is white
				{	
					for(auto j:board.possibleMoves(i))
					{
						Board newboard = board;
						newboard.movePiece(i, j);// Supposing possibleMoves doesn't return origin
						newboard.updateState(j, 1);
						v = std::max(v, alphaBeta(newboard, depth-1, a, b, false)); // Call alphabeta for black player
						a = std::max(a, v);
						if (b <= a)
						{
							break; // Cut off
						}
					}
				}
			}
			if(v == MIN) // Has not chosen a move -> possiblemoves must be empty
			{
				if(board.isCheck(maximizingPlayer))
				{
					return (MIN+100-depth);	// If it's check it's also checkmate
				}
				else // Otherwise it must be stalemate
				{
					return 0;
				}
			}
			return v;
		}

		else // Black players turn
		{
			int v = MAX;
			for(int i = 0; i < 64; i++)
			{
				if(board.getBoard()[i]%2 == 0 && board.getBoard()[i] != 0)
				{
					for(auto j:board.possibleMoves(i))
					{
						Board newboard = board;
						newboard.movePiece(i, j);
						newboard.updateState(j, 1);
						v = std::min(v, alphaBeta(newboard, depth-1, a, b, true));
						b = std::min(b,v);
						if(b<=a)
						{
							break; // Cut off
						}
					}
				}
			}
			if(v == MAX) // Has not chosen a move -> possiblemoves must be empty
			{
				if(board.isCheck(maximizingPlayer)) // If it's check it's also checkmate
				{
					return (MAX-100+depth);
				}
				else // Otherwise it must be stalemate
				{
					return 0;
				}
			}
			return v;
		}

	}
Пример #15
0
Board AIEngine::alphaBeta(Board board, char curpawn, int stopper, bool once, pair<int, int> node, int a, int b)	//1 = max, 0 = min
{
	int alpha = a;
	int beta = b;
	char pawn = curpawn;
	Board current = board;
	/*CHECKS FOR VICTORY OR DEFEAT*/
	if (stopper <= 0)
		return board;

	if (board.checkVictory() == 1 && pawn != curpawn)
	{
		board.score -= 1000;
		return board;
	}
	if (board.checkVictory() == 1 && pawn == curpawn)
	{
		board.score += 1000;
		return board;
	}
	if (board.checkVictory() == 2 && pawn != curpawn)
	{
		board.score -= 1000;
		return board;
	}
	if (board.checkVictory() == 2 && pawn == curpawn)
	{
		board.score += 1000;
		return board;
	}

	/*GET THE NEXT PAWN*/
	char nextPawn;
	if (curpawn == 'X')
		nextPawn = 'O';
	else
		nextPawn = 'X';

	/*FIND AVAILABLE PAWNS (NODES) TO MOVE FOR THE CURRENT PAWN TYPE ONLY DONE ONCE*/
	if (once)
	{
		board.score = 0;
		int bestScore = INT_MIN;
		Board best;
		char savePawn = pawn;
		pawn = curpawn;
		vector<pair<int, int>> peices;
		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
				if (isValidPiece(i, j))
				{
					peices.push_back(pair<int, int>(i, j));
				}
			}
		}
		pawn = savePawn;

		for (int i = 0; i < peices.size(); i++)
		{
			node = peices[i];
			Board temp = bestMove(board, curpawn, stopper, false, node);
			if (temp.score > bestScore)
			{
				best = temp;
				bestScore = best.score;
			}
		}
		return best;
	}

	/*Check on the possible moves for the one node pawn, and evaluate them DONE IF THE FUNCTION WAS CALLED RECURSIVELY*/
	if (!once)
	{
		current = board;
		char savePawn = pawn;
		pawn = curpawn;
		vector<pair<int, int>> validMoves = getValidMoves(node);

		pawn = savePawn;
		/*ERROR CHECKING*/
		/*cout << "Stopper: " << stopper << endl;
		cout << "Node: " << get<0>(node) << get<1>(node) << endl;
		cout << "Valid moves: ";
		for (int i = 0; i < validMoves.size(); i++)
		{
		cout << get<0>(validMoves[i]) << get<1>(validMoves[i]) << " ";
		}
		cout << endl;*/
		/*END OF ERROR CHECKING*/

		Board best;
		Board temp = board;
		Board temp2;
		int baseline;
		if (curpawn == pieceType)
		{
			baseline = INT_MIN;
		}
		else
		{
			baseline = INT_MAX;
		}
		int v;
		for (int i = 0; i < validMoves.size(); i++)
		{
			temp = board;
			/*SCORING THE MOVE*/
			if (curpawn == pieceType)
			{
				if (temp.getIndex(get<0>(validMoves[i]), get<1>(validMoves[i])) == nextPawn)
				{
					temp.score += 5;
				}
				else
				{
					temp.score += 1;
				}
			}
			else
			{
				if (temp.getIndex(get<0>(validMoves[i]), get<1>(validMoves[i])) == pieceType)
				{
					temp.score -= 4;
				}
				else
				{
					temp.score += 0;
				}
			}
			temp.setIndex(get<0>(node), get<1>(node), '\0');
			temp.setIndex(get<0>(validMoves[i]), get<1>(validMoves[i]), curpawn);

			//IF AI WINS
			if (get<0>(validMoves[i]) == 7 && curpawn == pawn)
			{
				temp.score = INT_MAX;
				return temp;
			}

			if (curpawn == pieceType)
			{
				/*Maximize*/
				temp2 = alphaBeta(temp, nextPawn, stopper - 1, false, validMoves[i], alpha, beta);
			/*	if (temp2.score > baseline)
				{
					baseline = temp2.score;
					best = temp;
					best.score = baseline;
				}*/
				if (temp2.score > baseline)
					v = temp2.score;
				else
					v = baseline;

				if (alpha < v)
					alpha = alpha;
				else
					alpha = v;

				if (beta <= alpha)
					return temp;
			}
			else
			{
				/*Minimize*/
				pawn = nextPawn;
				vector<pair<int, int>> peices;
				for (int j = 0; j < 8; j++)
				{
					for (int k = 0; k < 8; k++)
					{
						if (isValidPiece(j, k))
						{
							peices.push_back(pair<int, int>(j, k));
						}
					}
				}
				pawn = savePawn;
				for (int j = 0; j < peices.size(); j++)
				{
					temp2 = alphaBeta(temp, nextPawn, stopper - 1, false, peices[j], alpha, beta);
					/*if (temp2.score < baseline)
					{
						baseline = temp2.score;
						best = temp;
						best.score = baseline;
					}*/
					if (temp2.score < baseline)
						v = temp2.score;
					else
						v = baseline;

					if (beta > v)
						beta = beta;
					else
						beta = v;

					if (beta <= alpha)
						return temp;
				}
			}
		}
		return best;
	}
}
Пример #16
0
void genmove(char **board,int sizeBoard,int position[2][2],int walls[2],int depth,int maxPL,int maxPlayer){
    MOVE bestMove;
    int rows = 2*sizeBoard;
    int columns = 4* sizeBoard;
    int winningRow,flag=0,i;
    double alpha,beta;
    const int initialDepth = depth;
    alpha = -INFINITY;
    beta = INFINITY;
    if (maxPL)
        winningRow = 1;
    else
        winningRow = 2*sizeBoard -1;

    /*Checks if there is an immediate move that makes the player win.If there is,there is no need to run alphaBeta.*/
    for (i=0;i<12;i++){
        if (moves[i][4] == 0){
            if(position[maxPL][0] != moves[i][2] && position[maxPL][1] != moves[i][3] &&
               (check_Legal_Move(board,rows,columns,position[maxPL][0] + moves[i][0],position[maxPL][1] + moves[i][1],position[maxPL][0],position[maxPL][1])) &&
                        position[maxPL][0] + moves[i][0] == winningRow ){

                        flag = 1;
                        break;
            }
        }
        else if (moves[i][4] == 1){
            if((position[maxPL][0]*moves[i][5] > moves[i][2]*moves[i][5])&&(position[maxPL][1]*moves[i][6] > moves[i][3]*moves[i][6])&&
               (check_Legal_Move(board,rows,columns,position[maxPL][0] + moves[i][0],position[maxPL][1] + moves[i][1],position[maxPL][0],position[maxPL][1])) &&
                        position[maxPL][0] + moves[i][0] == winningRow){

                        flag = 1;
                        break;
            }
        }
    }




    if (flag == 1){
        bestMove.isMove =1;
        bestMove.row = position[maxPL][0] + moves[i][0];
        bestMove.col = position[maxPL][1] + moves[i][1];
    }
    else
        bestMove = alphaBeta(board,sizeBoard,position,walls,depth,initialDepth,maxPL,1,alpha,beta,maxPL);

    if(bestMove.isMove == 1){
        simpleMove(board,maxPL,rows,bestMove.row,bestMove.col,position);
        insertMove(maxPL,0,bestMove.row,bestMove.col,-1);
        printf("= %c%d\n\n",(position[maxPL][1]-2)/4 + 'a',(rows - position[maxPL][0] + 1)/2);
        fflush(stdout);
    }
    else if (bestMove.isMove == 0){
        simpleWall(board,bestMove.ori,rows,bestMove.row,bestMove.col);
        insertMove(maxPL,1,bestMove.row,bestMove.col,bestMove.ori);
        if (bestMove.ori == 0){
            printf("= %c%d vertical\n\n",(bestMove.col-2)/4 + 'a',(rows - bestMove.row + 1)/2);
            fflush(stdout);
        }
        else{
            printf("= %c%d horizontal\n\n",(bestMove.col-2)/4 + 'a',(rows - bestMove.row + 1)/2);
            fflush(stdout);
        }
        walls[maxPL]--;
    }
    else printf("TO THE NOPEVILLE!!!! \n\n");

}