Welcome, Guest. Please Login or Register.
Nov 22nd, 2024, 12:14pm

Home Home Help Help Search Search Members Members Login Login Register Register
Arimaa Forum « Qsearch in Clueless »


   Arimaa Forum
   Arimaa
   Bot Development
(Moderator: supersamu)
   Qsearch in Clueless
« Previous topic | Next topic »
Pages: 1  Reply Reply Notify of replies Notify of replies Send Topic Send Topic Print Print
   Author  Topic: Qsearch in Clueless  (Read 1142 times)
jdb
Forum Guru
*****



Arimaa player #214

   


Gender: male
Posts: 682
Qsearch in Clueless
« on: Mar 9th, 2009, 3:45pm »
Quote Quote Modify Modify

This is the Qsearch for clueless 2009.
 
It is only called at the start of a turn. In the main search, if there is a capture threat or a goal threat, with less than 4 steps left, the search is extended to complete the turn.
 
Code:

 private int Quiesce(int ply, int depth, int alpha, int beta, GameState gs) throws AbortSearchException {
 
  // Always need to have full turn available
  assert (gs.getStepsRemaining() == 4);
 
  // Check for abort search
  if (abort_search) {
   throw new AbortSearchException();
  }
 
  // Get a gamestate to work with
  GameState new_gs = gs_stack[ply];
 
  // Keep track of how many nodes we have searched
  q_nodes_searched++;
 
  // Test for a goal on first step
  goal_calls++;
  if (goal.test(gs)) {
   goal_hits++;
   return SCORE_MATE - (depth >>> 2);
  }
 
  // If we do nothing, can opponent goal?
  if (use_qdefend_search) {
 
   // There is no point in calling this recursively
   // The Qsearch will just stand pat
   if (depth == max_qsearch_depth) {
    // 8 ply goal search
    new_gs.playPASS(gs);
    goal_calls++;
    if (goal.test(new_gs)) {
     // SearchTrace(ply, "QS: Goal Threat");
 
     // Opponent can goal, OMG, look for a defence
     if (!QuiesceDefendGoal(ply, gs)) {
      // SearchTrace(ply, "QS: No Defence to goal threat");
      return -SCORE_MATE + 1 + (depth >> 2);
     }
     // SearchTrace(ply, "QS: Defence found");
 
    }
 
   }
  }
 
  // Get a stand pat score
  int score = eval.Evaluate(gs, false);
 
  // Limit depth of q search
  if (depth <= 0) {
   return score;
  }
 
  // SearchTrace(ply, "QStand pat score: " + score);
 
  if (score > alpha) {
   if (score >= beta) {
    return score;
   }
   alpha = score;
  }
 
  // Iterate thru all capture moves
  for (long move = qsms[ply].getFirstMove(gs); move != NEW_NO_STEP; move = qsms[ply].getNextMove(gs)) {
   int steps = new_gs.play(move, gs);
 
   if (show_alphabeta_search_trace) {
    // SearchTrace(ply, -1, alpha, beta, move);
   }
 
   if (new_gs.isGameOver()) {
    // Note must search rest of possible moves!!!
    score = new_gs.getGameResult();
   } else {
    // Game is NOT over, so we search
    int new_ply = ply + steps;
    score = -Quiesce(new_ply, depth - 1, -beta, -alpha, new_gs);
   }
 
   if (score > alpha) {
    if (score >= beta) {
     return score;
    }
    alpha = score;
   }
  }
 
  return alpha;
 
 }
 
 /**
  * Opponent has a goal threat, looks for a defence
  *  
  * @param ply
  * @param steps_available
  * @param gs
  * @return TRUE iff there is a defence to the goal threat
  */
 public boolean QuiesceDefendGoal(int ply, GameState gs) throws AbortSearchException {
  assert (gs.getStepsRemaining() == 4);
 
  // Best defence is to goal our own rabbit!
  if (goal.test(gs)) {
   // QSearchTrace(ply, "QDefend: Defender can goal");
   return true;
  }
 
  // Try qdefend killer moves
  GameState new_gs = gs_stack[ply];
  for (long move : qdefend_killers[ply]) {
   // QSearchTrace(ply, "QDEFKILLER: " + GameState.move_toString(move));
   if (new_gs.isLegalMove(move, gs)) {
    new_gs.play(move, gs);
 
    // Check if move ends the game
    if (new_gs.isGameOver()) {
     int score = new_gs.getGameResult();
     // We created a win for the enemy, not good
     if (score == -SCORE_MATE) {
      continue;
     }
     // We created a win for ourself, great
     if (score == SCORE_MATE) {
      return true;
     }
    }
 
    assert (new_gs.isFirstStep());
    if (!goal.test(new_gs)) {
     // QSearchTrace(ply, "QDefend: Killer move " + GameState.move_toString(move));
     return true;
    }
   }
  }
 
  // No known defence, so we must search
  // Use iterative deepening, in case there is an easy defence
  for (int def_depth = 1; def_depth <= 4; def_depth++) {
   // QSearchTrace(ply, "QDefend Starting depth: " + def_depth);
   if (QuiesceDefendInternal(ply, def_depth, gs, 0)) {
    // QSearchTrace(ply, "QDefend: Searched Defence found " + GameState.move_toString(qdefend_killers[ply][0]));
    return true;
   }
  }
 
  return false;
 }
 
 /**
  * Internal quiesce defend  
  * Handles the recursive defence search
  *  
  * @param ply
  * @param depth
  * @param gs
  * @param partial_move
  * @return
  */
 private boolean QuiesceDefendInternal(int ply, int depth, GameState gs, long partial_move)
   throws AbortSearchException {
 
  // Check for abort search
  if (abort_search) {
   throw new AbortSearchException();
  }
 
  GameState new_gs = gs_stack[ply];
  long moves[] = qmove_list_stack[ply];
  moves[0] = 0;
  long steps_available = gs.getStepsRemaining();
 
  // Probe hash table
  long probe_result = probeQHash(gs.getZobristPositionHash(), depth, q_hash_defend_table);
  if (probe_result == QHASH_DEFEND_WIN) {
   return true;
  }
  if (probe_result == QHASH_DEFEND_LOSS) {
   return false;
  }
 
  for (long move = qdms[ply].getFirstMove(gs); move != NEW_NO_STEP; move = qdms[ply].getNextMove(gs)) {
 
   // QSearchTrace(ply, depth, move);
   q_defence_nodes_searched++;
 
   int steps = new_gs.play(move, gs);
   int new_ply = ply + steps;
   int new_depth = depth - steps;
   long new_partial_move = partial_move | (move << (16 * (4 - steps_available)));
 
   if (new_depth <= 0) {
    // Complete the player's turn
    if (new_gs.getStepsRemaining() != 4) {
     new_partial_move |= (NEW_PASS_MOVE << (16 * (4 - new_gs.getStepsRemaining())));
     new_gs.playPASS(new_gs);
    }
 
    // Check if move ends the game
    if (new_gs.isGameOver()) {
     int score = new_gs.getGameResult();
     // We created a win for the enemy, not good
     if (score == -SCORE_MATE) {
      continue;
     }
     // We created a win for ourself, great
     if (score == SCORE_MATE) {
      record_qdefend_move(ply, new_partial_move);
      return true;
     }
    }
 
    // Check if move prevents an enemy goal
    if (!goal.test(new_gs)) {
     record_qdefend_move(ply, new_partial_move);
     return true;
    }
   }
 
   // depth remains, so search deeper
   else {
    boolean result = QuiesceDefendInternal(new_ply, new_depth, new_gs, new_partial_move);
    if (result) {
     return true;
    }
   }
  }
 
  // Store search result in hash table
  storeQHash(gs.getZobristPositionHash(), depth, QHASH_DEFEND_LOSS, q_hash_defend_table);
  return false;
 }
 
 
IP Logged
99of9
Forum Guru
*****




Gnobby's creator (player #314)

  toby_hudson  


Gender: male
Posts: 1413
Re: Qsearch in Clueless
« Reply #1 on: Mar 9th, 2009, 3:48pm »
Quote Quote Modify Modify

Wow, that's very kind of you!
IP Logged
Pages: 1  Reply Reply Notify of replies Notify of replies Send Topic Send Topic Print Print

« Previous topic | Next topic »

Arimaa Forum » Powered by YaBB 1 Gold - SP 1.3.1!
YaBB © 2000-2003. All Rights Reserved.