Exemplo n.º 1
0
int QuiesceChecks(POS *p, int ply, int alpha, int beta, int *pv)
{
  int stand_pat, best, score, move, new_pv[MAX_PLY];
  int is_pv = (beta > alpha + 1);
  MOVES m[1];
  UNDO u[1];

  if (InCheck(p)) return QuiesceFlee(p, ply, alpha, beta, pv);

  nodes++;
  CheckTimeout();
  if (abort_search) return 0;
  *pv = 0;
  
  if (IsDraw(p)) return DrawScore(p);

  if (ply >= MAX_PLY - 1)
    return Eval.Return(p, 1);

  best = stand_pat = Eval.Return(p, 1);

  if (best >= beta) return best;
  if (best > alpha) alpha = best;

  if (TransRetrieve(p->hash_key, &move, &score, alpha, beta, 0, ply))
     return score;

  InitCaptures(p, m);
  while ((move = NextCaptureOrCheck(m))) {

    p->DoMove(move, u);
    if (Illegal(p)) { p->UndoMove(move, u); continue; }

    score = -Quiesce(p, ply + 1, -beta, -alpha, new_pv);

    p->UndoMove(move, u);
    if (abort_search) return 0;

    if (score >= beta) {
      TransStore(p->hash_key, move, score, LOWER, 0, ply);
        return score;
    }

    if (score > best) {
      best = score;
      if (score > alpha) {
        alpha = score;
        BuildPv(pv, new_pv, move);
      }
    }
  }

  if (*pv) TransStore(p->hash_key, *pv, best, EXACT, 0, ply);
  else     TransStore(p->hash_key, 0, best, UPPER, 0, ply);

  return best;
}
void CTicTacView::CheckForGameOver()
{
	int nWinner;

	//그리드에 세 개의 연속 X나 O가 있으면 승자를 선언하고 새로 게임을 시작
	if( nWinner = IsWinner ())
	{
		CString string = (nWinner == EX) ? _T("X wins!") : _T("O Win!");

		MessageBox(string, _T("Game Over"), MB_ICONEXCLAMATION | MB_OK);

		ResetGame();
	}

	// 그리드가 가득차면 새 게임을 시작
	else if( IsDraw() )
	{
		MessageBox(_T("It's a draw!"), _T("Game Over"), 
			MB_ICONEXCLAMATION | MB_OK);

		ResetGame();
	}
}
Exemplo n.º 3
0
//verifica se o jogo acabou
int GameOver(int hash[HASH_DIMENSION][HASH_DIMENSION])
{
    return IsWinner(hash, COMPUTER) || IsWinner(hash, PLAYER) || IsDraw(hash);
}
Exemplo n.º 4
0
int Quiesce(POS *p, int ply, int alpha, int beta, int *pv) {

  int best, score, move, new_pv[MAX_PLY];
  MOVES m[1];
  UNDO u[1];
  int op = Opp(p->side);

  // Statistics and attempt at quick exit

  if (InCheck(p)) return QuiesceFlee(p, ply, alpha, beta, pv);

  nodes++;
  CheckTimeout();
  if (abort_search) return 0;
  *pv = 0;
  if (IsDraw(p)) return DrawScore(p);
  if (ply >= MAX_PLY - 1) return Eval.Return(p, 1);

  // Get a stand-pat score and adjust bounds
  // (exiting if eval exceeds beta)

  best = Eval.Return(p, 1);
  if (best >= beta) return best;
  if (best > alpha) alpha = best;

#ifdef USE_QS_HASH
  // Transposition table read

  if (TransRetrieve(p->hash_key, &move, &score, alpha, beta, 0, ply))
    return score;
#endif

  InitCaptures(p, m);

  // Main loop

  while ((move = NextCapture(m))) {

    // Pruning in quiescence search 
	// (not applicable if we are capturing last enemy piece)

	if (p->cnt[op][N] + p->cnt[op][B] + p->cnt[op][R] + p->cnt[op][Q] > 1) {

      // 1. Delta pruning

      if (best + tp_value[TpOnSq(p, Tsq(move))] + 300 < alpha) continue;

      // 2. SEE-based pruning of bad captures

      if (BadCapture(p, move)) continue;
	}

    p->DoMove(move, u);
    if (Illegal(p)) { p->UndoMove(move, u); continue; }

    score = -Quiesce(p, ply + 1, -beta, -alpha, new_pv);

    p->UndoMove(move, u);
    if (abort_search) return 0;

  // Beta cutoff

  if (score >= beta) {
#ifdef USE_QS_HASH
    TransStore(p->hash_key, *pv, best, LOWER, 0, ply);
#endif
    return score;
  }

  // Adjust alpha and score

    if (score > best) {
      best = score;
      if (score > alpha) {
        alpha = score;
        BuildPv(pv, new_pv, move);
      }
    }
  }

#ifdef USE_QS_HASH
  if (*pv) TransStore(p->hash_key, *pv, best, EXACT, 0, ply);
  else     TransStore(p->hash_key,   0, best, UPPER, 0, ply);
#endif

  return best;
}
Exemplo n.º 5
0
int QuiesceFlee(POS *p, int ply, int alpha, int beta, int *pv) {

  int best, score, move, new_pv[MAX_PLY];
  int fl_check, mv_type;
  int is_pv = (beta > alpha + 1);

  MOVES m[1];
  UNDO u[1];

  // Periodically check for timeout, ponderhit or stop command

  nodes++;
  CheckTimeout();

  // Quick exit on a timeout or on a statically detected draw

  if (abort_search) return 0;
  if (ply) *pv = 0;
  if (IsDraw(p) ) return DrawScore(p);

  // Retrieving data from transposition table. We hope for a cutoff
  // or at least for a move to improve move ordering.

  move = 0;
  if (TransRetrieve(p->hash_key, &move, &score, alpha, beta, 0, ply))
    return score;

  // Safeguard against exceeding ply limit

  if (ply >= MAX_PLY - 1)
    return Eval.Return(p, 1);

  // Are we in check? Knowing that is useful when it comes 
  // to pruning/reduction decisions

  fl_check = InCheck(p);

  // Init moves and variables before entering main loop

  best = -INF;
  InitMoves(p, m, move, -1, ply);

  // Main loop

  while ((move = NextMove(m, &mv_type))) {
    p->DoMove(move, u);
    if (Illegal(p)) { p->UndoMove(move, u); continue; }
    
    score = -Quiesce(p, ply, -beta, -alpha, new_pv);

    
    p->UndoMove(move, u);
    if (abort_search) return 0;

    // Beta cutoff

    if (score >= beta) {
      TransStore(p->hash_key, move, score, LOWER, 0, ply);
      return score;
    }

    // Updating score and alpha

    if (score > best) {
      best = score;
      if (score > alpha) {
        alpha = score;
        BuildPv(pv, new_pv, move);
      }
    }

  } // end of the main loop

  // Return correct checkmate/stalemate score

  if (best == -INF)
    return InCheck(p) ? -MATE + ply : DrawScore(p);

  // Save score in the transposition table

  if (*pv) TransStore(p->hash_key, *pv, best, EXACT, 0, ply);
  else     TransStore(p->hash_key, 0, best, UPPER, 0, ply);

  return best;
}
Exemplo n.º 6
0
int Search(POS *p, int ply, int alpha, int beta, int depth, int was_null, int last_move, int last_capt_sq, int *pv) {

  int best, score, null_score, move, new_depth, new_pv[MAX_PLY];
  int fl_check, fl_prunable_node, fl_prunable_move, mv_type, reduction;
  int is_pv = (beta > alpha + 1);
  int mv_tried = 0, quiet_tried = 0, fl_futility = 0;

  int mv_played[MAX_MOVES];
  int mv_hist_score;
  int victim, last_capt;

  MOVES m[1];
  UNDO u[1];

  assert(ply > 0);

  // Quiescence search entry point

  if (depth <= 0)
    return QuiesceChecks(p, ply, alpha, beta, pv);

  // Periodically check for timeout, ponderhit or stop command

  nodes++;
  CheckTimeout();

  // Quick exit on a timeout or on a statically detected draw
  
  if (abort_search) return 0;
  if (ply) *pv = 0;
  if (IsDraw(p)) return DrawScore(p);

  // Mate distance pruning

  int checkmatingScore = MATE - ply;
  if (checkmatingScore < beta) {
    beta = checkmatingScore;
    if (alpha >= checkmatingScore)
    return alpha;
  }

  int checkmatedScore = -MATE + ply;
  if (checkmatedScore > alpha) {
    alpha = checkmatedScore;
    if (beta <= checkmatedScore)
    return beta;
  }

  // Retrieving data from transposition table. We hope for a cutoff
  // or at least for a move to improve move ordering.

  move = 0;
  if (TransRetrieve(p->hash_key, &move, &score, alpha, beta, depth, ply)) {
    
    // For move ordering purposes, a cutoff from hash is treated
    // exactly like a cutoff from search

    if (score >= beta) UpdateHistory(p, last_move, move, depth, ply);

    // In pv nodes only exact scores are returned. This is done because
    // there is much more pruning and reductions in zero-window nodes,
    // so retrieving such scores in pv nodes works like retrieving scores
    // from slightly lower depth.

    if (!is_pv || (score > alpha && score < beta))
      return score;
  }

  // Safeguard against exceeding ply limit
  
  if (ply >= MAX_PLY - 1)
    return Eval.Return(p, 1);

  // Are we in check? Knowing that is useful when it comes 
  // to pruning/reduction decisions

  fl_check = InCheck(p);

  // INTERNAL ITERATIVE DEEPENING - we try to get a hash move to improve move ordering

  if (!move && is_pv && depth >= 6 && !fl_check) {
    Search(p, ply, alpha, beta, depth - 2, 0, 0, -1, new_pv);
    if (abort_search) return 0;
    TransRetrieve(p->hash_key, &move, &score, alpha, beta, depth, ply);
  }

  // Can we prune this node?

  fl_prunable_node = !fl_check 
                   && !is_pv 
                   && alpha > -MAX_EVAL
                   && beta < MAX_EVAL;

  // Beta pruning / static null move

  if (use_beta_pruning
  && fl_prunable_node
  && depth <= 3
  && !was_null) {
    int sc = Eval.Return(p, 1) - 120 * depth; // TODO: Tune me!
    if (sc > beta) return sc;
  }

  // Null move

  if (use_nullmove
  && fl_prunable_node
  && depth > 1
  && !was_null
  && MayNull(p)
  ) {
    int eval = Eval.Return(p, 1);
    if (eval > beta) {

      new_depth = depth - ((823 + 67 * depth) / 256); // simplified Stockfish formula

      // omit null move search if normal search to the same depth wouldn't exceed beta
      // (sometimes we can check it for free via hash table)

      if (TransRetrieve(p->hash_key, &move, &null_score, alpha, beta, new_depth, ply)) {
        if (null_score < beta) goto avoid_null;
      }

      p->DoNull(u);
      if (new_depth > 0) score = -Search(p, ply + 1, -beta, -beta + 1, new_depth, 1, 0, -1, new_pv);
      else               score = -QuiesceChecks(p, ply + 1, -beta, -beta + 1, new_pv);
      p->UndoNull(u);

      // Verification search (nb. immediate null move within it is prohibited)

      if (new_depth > 6 && score >= beta && use_null_verification)
         score = Search(p, ply, alpha, beta, new_depth - 5, 1, move, -1, new_pv);

      if (abort_search ) return 0;
      if (score >= beta) return score;
    }
  } 
  
  avoid_null:

  // end of null move code

  // Razoring based on Toga II 3.0

  if (use_razoring
  && fl_prunable_node
  && !move
  && !was_null
  && !(p->Pawns(p->side) & bbRelRank[p->side][RANK_7]) // no pawns to promote in one move
  && depth <= 3) {
    int threshold = beta - razor_margin[depth];
    int eval = Eval.Return(p, 1);

    if (eval < threshold) {
      score = QuiesceChecks(p, ply, alpha, beta, pv);
      if (score < threshold) return score;
    }
  }

  // end of razoring code 

  // Init moves and variables before entering main loop
  
  best = -INF;
  InitMoves(p, m, move, Refutation(last_move), ply);
  
  // Main loop
  
  while ((move = NextMove(m, &mv_type))) {

    // Gather data about the move

    mv_hist_score = history[p->pc[Fsq(move)]][Tsq(move)];
	victim = TpOnSq(p, Tsq(move));
	if (victim != NO_TP) last_capt = Tsq(move);
	else last_capt = -1;

    // Set futility pruning flag before the first applicable move is tried

    if (mv_type == MV_NORMAL && quiet_tried == 0) {
      if (use_futility
      && fl_prunable_node
      && depth <= 6) {
        if (Eval.Return(p, 1) + fut_margin[depth] < beta) fl_futility = 1;
      }
    }

    p->DoMove(move, u);
    if (Illegal(p)) { p->UndoMove(move, u); continue; }

  // Update move statistics 
  // (needed for reduction/pruning decisions and for updating history score)

  mv_played[mv_tried] = move;
  mv_tried++;
  if (mv_type == MV_NORMAL) quiet_tried++;

  // Can we prune this move?

  fl_prunable_move = !InCheck(p)
                  && (mv_type == MV_NORMAL)
                  && (mv_hist_score < hist_limit);

  // Set new search depth

  new_depth = depth - 1;

  // Check extension (pv node or low depth)

  if (is_pv || depth < 9) {
	  new_depth += InCheck(p);
	  if (is_pv && Tsq(move) == last_capt_sq) new_depth += 1;
  }

  // Futility pruning

  if (fl_futility
  &&  fl_prunable_move
  &&  mv_tried > 1) {
    p->UndoMove(move, u); continue;
  }

  // Late move pruning

  if (use_lmp
  && fl_prunable_node
  && fl_prunable_move
  && quiet_tried > lmp_limit[depth]
  && depth <= 3
  && MoveType(move) != CASTLE ) {
    p->UndoMove(move, u); continue;
  }

  // Late move reduction

  reduction = 0;

  if (use_lmr 
  && depth >= 2
  && mv_tried > 3
  && alpha > -MAX_EVAL && beta < MAX_EVAL
  && !fl_check 
  &&  fl_prunable_move
  && lmr_size[is_pv][depth][mv_tried] > 0
  && MoveType(move) != CASTLE ) {
    
    // read reduction size from the table

    reduction = lmr_size[is_pv][depth][mv_tried];

    // increase reduction on bad history score

    if (mv_hist_score < 0
    && new_depth - reduction > 2
    && lmr_hist_adjustement)
       reduction++;

    // reduce search depth

    new_depth -= reduction;
  }

  // a place to come back if reduction looks suspect

  re_search:
   
  // PVS

  if (best == -INF)
    score = -Search(p, ply + 1, -beta, -alpha, new_depth, 0, move, last_capt, new_pv);
  else {
    score = -Search(p, ply + 1, -alpha - 1, -alpha, new_depth, 0, move, last_capt, new_pv);
    if (!abort_search && score > alpha && score < beta)
      score = -Search(p, ply + 1, -beta, -alpha, new_depth, 0, move, last_capt, new_pv);
  }

  // Reduced move scored above alpha - we need to re-search it

  if (reduction
  && score > alpha) {
    new_depth += reduction;
    reduction = 0;
    goto re_search;
  }

  // Undo move

  p->UndoMove(move, u);
  if (abort_search) return 0;

  // Beta cutoff

    if (score >= beta) {
      if (!fl_check) {
        UpdateHistory(p, last_move, move, depth, ply);
        for (int mv = 0; mv < mv_tried; mv++)
          DecreaseHistory(p, mv_played[mv], depth);
      }
      TransStore(p->hash_key, move, score, LOWER, depth, ply);

      return score;
    }

  // Updating score and alpha

    if (score > best) {
      best = score;
      if (score > alpha) {
        alpha = score;
        BuildPv(pv, new_pv, move);
      }
    }

  } // end of the main loop

  // Return correct checkmate/stalemate score

  if (best == -INF)
    return InCheck(p) ? -MATE + ply : DrawScore(p);

  // Save score in the transposition table

  if (*pv) {
    if (!fl_check) {
      UpdateHistory(p, last_move, *pv, depth, ply);
      for (int mv = 0; mv < mv_tried; mv++)
        DecreaseHistory(p, mv_played[mv], depth);
    }
    TransStore(p->hash_key, *pv, best, EXACT, depth, ply);
  } else
    TransStore(p->hash_key, 0, best, UPPER, depth, ply);

  return best;
}