예제 #1
0
void
full_learn_public_game( int length, int *moves, int cutoff,
			int deviation_depth, int exact, int wld ) {
  int i;
  int dummy;
  int side_to_move;
  FILE *stream;

  stream = fopen( LEARN_LOG_FILE_NAME, "a" );
  if ( stream != NULL ) {  /* Write the game learned to a log file. */
    for ( i = 0; i < length; i++ )
      fprintf( stream, "%c%c", TO_SQUARE( moves[i] ) );
    fputs( "\n", stream );
    fclose( stream );
  }

  clear_panic_abort();
  toggle_abort_check( FALSE );

  /* Copy the move list from the caller as it is modified below. */

  for ( i = 0; i < length; i++ )
    game_move[i] = moves[i];

  /* Determine side to move for all positions */

  game_init( NULL, &dummy );
  side_to_move = BLACKSQ;
  for ( i = 0; i < length; i++ ) {
    generate_all( side_to_move );
    if ( move_count[disks_played] == 0 ) {
      side_to_move = OPP( side_to_move );
      generate_all( side_to_move );
    }
    (void) make_move( side_to_move, game_move[i], TRUE );
    if ( side_to_move == WHITESQ )
      game_move[i] = -game_move[i];
    side_to_move = OPP( side_to_move );
  }

  /* Let the learning sub-routine in osfbook update the opening
     book and the dump it to file. */

  set_search_depth( deviation_depth );
  add_new_game( length, game_move, cutoff, exact, wld, TRUE, FALSE );
  if ( binary_database )
    write_binary_database( database_name );
  else
    write_text_database( database_name );

  toggle_abort_check( TRUE );
}
예제 #2
0
 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
   if (all) {
     generate_all();
   } else {
     generate_initial();
   }
 }
예제 #3
0
 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
   if (all) {
     generate_all();
   } else {
     generate_initial();
   }
   __ flush_bundle(); // Insurance
   __ flush();
 }
예제 #4
0
void
learn_game( int game_length, int private_game, int save_database ) {
  int i;
  int dummy;
  int side_to_move;
  int full_solve, wld_solve;

  clear_panic_abort();
  toggle_abort_check( FALSE );

  full_solve = get_earliest_full_solve();
  wld_solve = get_earliest_wld_solve();

  game_init( NULL, &dummy );
  side_to_move = BLACKSQ;
  for ( i = 0; i < game_length; i++ ) {
    generate_all( side_to_move );
    if ( move_count[disks_played] == 0 ) {
      side_to_move = OPP( side_to_move );
      generate_all( side_to_move );
    }
    (void) make_move( side_to_move, game_move[i], TRUE );
    if ( side_to_move == WHITESQ )
      game_move[i] = -game_move[i];
    side_to_move = OPP( side_to_move );
  }

  set_search_depth( learn_depth );
  add_new_game( game_length, game_move, cutoff_empty, full_solve,
		wld_solve, TRUE, private_game );

  if ( save_database ) {
    if ( binary_database )
      write_binary_database( database_name );
    else
      write_text_database( database_name );
  }

  toggle_abort_check( TRUE );
}
예제 #5
0
// Obtain a sorted move list.
static int get_sortable_move_list(searchNode *node, sortable_move_t * move_list,
                         int hash_table_move) {
  // number of moves in list
  int num_of_moves = generate_all(&(node->position), move_list, false);

  color_t fake_color_to_move = color_to_move_of(&(node->position));

  move_t killer_a = killer[KMT(node->ply, 0)];
  move_t killer_b = killer[KMT(node->ply, 1)];

  for (int mv_index = 0; mv_index < num_of_moves; mv_index++) {
    move_t mv = move_list[mv_index];   // don't use get_move. assumes generate_all doesn't bungle up high bits
    if (mv == hash_table_move) {
      set_sort_key(&move_list[mv_index], SORT_MASK);
    } else if (mv == killer_a) {
      set_sort_key(&move_list[mv_index], SORT_MASK - 1);
    } else if (mv == killer_b) {
      set_sort_key(&move_list[mv_index], SORT_MASK - 2);
    } else {
      ptype_t  pce = ptype_mv_of(mv);
      rot_t    ro  = rot_of(mv);   // rotation
      square_t fs  = from_square(mv);
      int      ot  = ORI_MASK & (ori_of(node->position.board[fs]) + ro);
      square_t ts  = to_square(mv);

      set_sort_key(&move_list[mv_index],
                   best_move_history[BMH(fake_color_to_move, pce, ts, ot)]);
    }
    sortable_move_t insert = move_list[mv_index];
    // TODO: enable this optimization for final since node counts change
    // if (insert > SORT_MASK) {
      int hole = mv_index;
      while (hole > 0 && insert > move_list[hole-1]) {
        move_list[hole] = move_list[hole-1];
        hole--;
      }
      move_list[hole] = insert;
    // }
  }
  return num_of_moves;
}
예제 #6
0
void _droidzebra_redo_turn(int *side_to_move) {
    int target_disks_played = 0;
    int curr_move;

    if (!_droidzebra_can_redo()) return;

    target_disks_played = _droidzebra_undo_stack_pop();
    droidzebra_message_debug("redo: score_sheet_row %d, disks_played %d, new_disks_played %d",
                             score_sheet_row, disks_played, target_disks_played);
    while (disks_played < target_disks_played) {
        generate_all(*side_to_move);

        if (move_count[disks_played] > 0) {
            curr_move = get_stored_move(disks_played);
            if (curr_move == ILLEGAL || !valid_move(curr_move, *side_to_move)) {
                fatal_error("Invalid move %c%c in redo sequence", TO_SQUARE(curr_move));
            }
            (void) make_move(*side_to_move, curr_move, TRUE);
        } else {
            curr_move = PASS;
        }

        droidzebra_message_debug(
                "redo: score_sheet_row %d, curr_move %d, side_to_move %d, disks_played %d",
                score_sheet_row, curr_move, *side_to_move, disks_played);

        if (*side_to_move == BLACKSQ)
            black_moves[score_sheet_row] = curr_move;
        else {
            white_moves[score_sheet_row] = curr_move;
        }

        *side_to_move = OPP(*side_to_move);

        if (*side_to_move == BLACKSQ)
            score_sheet_row++;
    }
}
예제 #7
0
InterpreterGenerator::InterpreterGenerator(StubQueue* code)
 : CppInterpreterGenerator(code) {
   generate_all();
}
InterpreterGenerator::InterpreterGenerator(StubQueue* code)
 : CppInterpreterGenerator(code) {
   generate_all(); // down here so it can be "virtual"
}
예제 #9
0
int
extended_compute_move( int side_to_move, int book_only,
		       int book, int mid, int exact, int wld ) {
  int i, j;
  int index;
  int changed;
  int this_move;
  int disc_diff, corrected_diff;
  int best_move, temp_move;
  int best_score;
  int best_pv_depth;
  int stored_echo;
  int shallow_eval;
  int empties;
  int current_mid, current_exact, current_wld;
  int first_iteration;
  int unsearched;
  int unsearched_count;
  int unsearched_move[61];
  int best_pv[60];
  unsigned int transform1[60], transform2[60];
  CandidateMove book_move;
  EvaluatedMove temp;
  EvaluationType book_eval_info;
  EvalResult res;

  /* Disable all time control mechanisms and randomization */

  toggle_abort_check( FALSE );
  toggle_midgame_abort_check( FALSE );
  toggle_perturbation_usage( FALSE );
  start_move( 0, 0, disc_count( BLACKSQ ) + disc_count( WHITESQ ) );
  clear_ponder_times();
  determine_hash_values( side_to_move, board );

  empties = 60 - disks_played;

  best_move = 0;
  game_evaluated_count = 0;

  reset_counter( &nodes );

  generate_all( side_to_move );

  if ( book_only || book ) {  /* Evaluations for database moves */
    int flags = 0;

    if ( empties <= exact )
      flags = FULL_SOLVED;
    else if ( empties <= wld )
      flags = WLD_SOLVED;

    fill_move_alternatives( side_to_move, flags );

    game_evaluated_count = get_candidate_count();
    for ( i = 0; i < game_evaluated_count; i++ ) {
      int child_flags;

      book_move = get_candidate( i );
      evaluated_list[i].side_to_move = side_to_move;
      evaluated_list[i].move = book_move.move;
      evaluated_list[i].pv_depth = 1;
      evaluated_list[i].pv[0] = book_move.move;
      evaluated_list[i].eval =
	create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
			  book_move.score, 0.0, 0, TRUE );
      child_flags = book_move.flags & book_move.parent_flags;
      if ( child_flags & (FULL_SOLVED | WLD_SOLVED) ) {
	if ( child_flags & FULL_SOLVED )
	  evaluated_list[i].eval.type = EXACT_EVAL;
	else
	  evaluated_list[i].eval.type = WLD_EVAL;
	if ( book_move.score > 0 ) {
	  evaluated_list[i].eval.res = WON_POSITION;
	  /* Normalize the scores so that e.g. 33-31 becomes +256 */
	  evaluated_list[i].eval.score -= CONFIRMED_WIN;
	  evaluated_list[i].eval.score *= 128;
	}
	else if ( book_move.score == 0 )
	  evaluated_list[i].eval.res = DRAWN_POSITION;
	else {  /* score < 0 */
	  evaluated_list[i].eval.res = LOST_POSITION;
	  /* Normalize the scores so that e.g. 30-34 becomes -512 */
	  evaluated_list[i].eval.score += CONFIRMED_WIN;
	  evaluated_list[i].eval.score *= 128;
	}
      }
      else
	  evaluated_list[i].eval.type = MIDGAME_EVAL;
    }
  }
  if ( book_only ) {  /* Only book moves are to be considered */
    if ( game_evaluated_count > 0 ) {
      best_move = get_book_move( side_to_move, FALSE, &book_eval_info );
      set_current_eval( book_eval_info );
    }
    else {
      pv_depth[0] = 0;
      best_move = PASS;
      book_eval_info = create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
					 0, 0.0, 0, FALSE );
      set_current_eval( book_eval_info );
    }
  }
  else {  /* Make searches for moves not in the database */
    int shallow_depth;
    int empties = 60 - disks_played;

    book = FALSE;

    best_score = -INFINITE_EVAL;
    if ( game_evaluated_count > 0 ) {  /* Book PV available */
      best_score = evaluated_list[0].eval.score;
      best_move = evaluated_list[0].move;
    }

    negate_current_eval( TRUE );

    /* Store the available moves, clear their evaluations and sort
       them on shallow evaluation. */

    if ( empties < 12 )
      shallow_depth = 1;
    else {
      int max_depth = MAX( mid, MAX( exact, wld ) );
      if ( max_depth >= 16 )
	shallow_depth = 6;
      else
      shallow_depth = 4;
    }

    unsearched_count = 0;
    for ( i = 0; i < move_count[disks_played]; i++ ) {
      this_move = move_list[disks_played][i];
      unsearched = TRUE;
      for ( j = 0; j < game_evaluated_count; j++ )
	if ( evaluated_list[j].move == this_move )
	  unsearched = FALSE;
      if ( !unsearched )
	continue;
      unsearched_move[unsearched_count] = this_move;
      unsearched_count++;
      (void) make_move( side_to_move, this_move, TRUE );
      if ( shallow_depth == 1 )  /* Compute move doesn't allow depth 0 */
	shallow_eval = -static_evaluation( OPP( side_to_move ) );
      else {
	EvaluationType shallow_info;

	(void) compute_move( OPP( side_to_move ), FALSE, 0, 0, FALSE, book,
			     shallow_depth - 1, 0, 0, TRUE, &shallow_info );

	if ( shallow_info.type == PASS_EVAL ) {
	  /* Don't allow pass */
	  (void) compute_move( side_to_move, FALSE, 0, 0, FALSE, book,
			       shallow_depth - 1, 0, 0, TRUE, &shallow_info );
	  if ( shallow_info.type == PASS_EVAL ) {  /* Game over */
	    disc_diff =
	      disc_count( side_to_move ) - disc_count( OPP( side_to_move ) );
	    if ( disc_diff > 0 )
	      corrected_diff = 64 - 2 * disc_count( OPP( side_to_move) );
	    else if ( disc_diff == 0 )
	      corrected_diff = 0;
	    else
	      corrected_diff = 2 * disc_count( side_to_move ) - 64;
	    shallow_eval = 128 * corrected_diff;
	  }
	  else
	    shallow_eval = shallow_info.score;
	}
	else  /* Sign-correct the score produced */
	  shallow_eval = -shallow_info.score;
      }

      unmake_move( side_to_move, this_move );
      evals[disks_played][this_move] = shallow_eval;
    }

    do {
      changed = FALSE;
      for ( i = 0; i < unsearched_count - 1; i++ )
	if ( evals[disks_played][unsearched_move[i]] <
	     evals[disks_played][unsearched_move[i + 1]] ) {
	  temp_move = unsearched_move[i];
	  unsearched_move[i] = unsearched_move[i + 1];
	  unsearched_move[i + 1] = temp_move;
	  changed = TRUE;
	}
    } while ( changed );

    /* Initialize the entire list as being empty */

    for ( i = 0, index = game_evaluated_count; i < unsearched_count;
	  i++, index++ ) {
      evaluated_list[index].side_to_move = side_to_move;
      evaluated_list[index].move = unsearched_move[i];
      evaluated_list[index].eval =
	create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
			  0, 0.0, 0, FALSE );
      evaluated_list[index].pv_depth = 1;
      evaluated_list[index].pv[0] = unsearched_move[i];

      if ( empties > MAX( wld, exact ) ) {
	transform1[i] = abs( my_random() );
	transform2[i] = abs( my_random() );
      }
      else {
	transform1[i] = 0;
	transform2[i] = 0;
      }
    }

    stored_echo = echo;
    echo = FALSE;
    best_pv_depth = 0;
    if ( mid == 1 ) {  /* compute_move won't be called */
      pv_depth[0] = 0;
      piece_count[BLACKSQ][disks_played] = disc_count( BLACKSQ );
      piece_count[WHITESQ][disks_played] = disc_count( WHITESQ );
    }

    /* Perform iterative deepening if the search depth is large enough */

#define ID_STEP 2

    if ( exact > empties )
      exact = empties;
    if ( (exact < 12) || (empties > exact) )
      current_exact = exact;
    else
      current_exact = (8 + (exact % 2)) - ID_STEP;

    if ( wld > empties )
      wld = empties;
    if ( (wld < 14) || (empties > wld) )
      current_wld = wld;
    else
      current_wld = (10 + (wld % 2)) - ID_STEP;

    if ( ((empties == exact) || (empties == wld)) &&
	 (empties > 16) && (mid < empties - 12) )
      mid = empties - 12;
    if ( mid < 10 )
      current_mid = mid;
    else
      current_mid = (6 + (mid % 2)) - ID_STEP;

    first_iteration = TRUE;

    do {
      if ( current_mid < mid ) {
	current_mid += ID_STEP;

	/* Avoid performing deep midgame searches if the endgame
	   is reached anyway. */

	if ( (empties <= wld) && (current_mid + 7 >= empties) ) {
	  current_wld = wld;
	  current_mid = mid;
	}
	if ( (empties <= exact) && (current_mid + 7 >= empties) ) {
	  current_exact = exact;
	  current_mid = mid;
	}
      }
      else if ( current_wld < wld )
	current_wld = wld;
      else
	current_exact = exact;

      for ( i = 0; (i < unsearched_count) && !force_return; i++ ) {
	EvaluationType this_eval;

	this_move = unsearched_move[i];

	/* Locate the current move in the list.  This has to be done
	   because the moves might have been reordered during the
	   iterative deepening. */

	index = 0;
	while ( evaluated_list[index].move != this_move )
	  index++;

	/* To avoid strange effects when browsing back and forth through
	   a game during the midgame, rehash the hash transformation masks
	   for each move unless the endgame is reached */

	set_hash_transformation( transform1[i], transform2[i] );

	/* Determine the score for the ith move */

	prefix_move = this_move;
	(void) make_move( side_to_move, this_move, TRUE );
	if ( current_mid == 1 ) {
	  /* compute_move doesn't like 0-ply searches */
	  shallow_eval = static_evaluation( OPP( side_to_move ) );
	  this_eval =
	    create_eval_info( MIDGAME_EVAL, UNSOLVED_POSITION,
			      shallow_eval, 0.0, 0, FALSE );
	}
	else
	  (void) compute_move( OPP( side_to_move ), FALSE, 0, 0, FALSE, book,
			       current_mid - 1, current_exact - 1,
			       current_wld - 1, TRUE,
			       &this_eval );
	if ( force_return ) {  /* Clear eval and exit search immediately */
	  this_eval =
	    create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
			      0, 0.0, 0, FALSE );
	  unmake_move( side_to_move, this_move );
	  break;
	}

	if ( this_eval.type == PASS_EVAL ) {
	  /* Don't allow pass */
	  if ( current_mid == 1 ) {
	    /* compute_move doesn't like 0-ply searches */
	    shallow_eval = static_evaluation( side_to_move );
	    this_eval = 
	      create_eval_info( MIDGAME_EVAL, UNSOLVED_POSITION,
				shallow_eval, 0.0, 0, FALSE );
	  }
	  else
	    (void) compute_move( side_to_move, FALSE, 0, 0, FALSE, book,
				 current_mid - 1, current_exact - 1,
				 current_wld - 1, TRUE,
				 &this_eval );
	  if ( this_eval.type == PASS_EVAL ) {  /* Game over */
	    disc_diff =
	      disc_count( side_to_move ) - disc_count( OPP( side_to_move ) );
	    if ( disc_diff > 0 ) {
	      corrected_diff = 64 - 2 * disc_count( OPP( side_to_move) );
	      res = WON_POSITION;
	    }
	    else if ( disc_diff == 0 ) {
	      corrected_diff = 0;
	      res = DRAWN_POSITION;
	    }
	    else {
	      corrected_diff = 2 * disc_count( side_to_move ) - 64;
	      res = LOST_POSITION;
	    }
	    this_eval =
	      create_eval_info( EXACT_EVAL, res, 128 * corrected_diff,
				0.0, 60 - disks_played, FALSE );
	  }
	}
	else {  /* Sign-correct the score produced */
	  this_eval.score =
	    -this_eval.score;
	  if ( this_eval.res == WON_POSITION )
	    this_eval.res = LOST_POSITION;
	  else if ( this_eval.res == LOST_POSITION )
	    this_eval.res = WON_POSITION;
	}

	if ( force_return )
	  break;
	else
	  evaluated_list[index].eval = this_eval;

	/* Store the PV corresponding to the move */

	evaluated_list[index].pv_depth = pv_depth[0] + 1;
	evaluated_list[index].pv[0] = this_move;
	for ( j = 0; j < pv_depth[0]; j++ )
	  evaluated_list[index].pv[j + 1] = pv[0][j];

	/* Store the PV corresponding to the best move */

	if ( evaluated_list[index].eval.score > best_score ) {
	  best_score = evaluated_list[index].eval.score;
	  best_move = this_move;
	  best_pv_depth = pv_depth[0];
	  for ( j = 0; j < best_pv_depth; j++ )
	    best_pv[j] = pv[0][j];
	}
	unmake_move( side_to_move, this_move );

	/* Sort the moves evaluated */

	if ( first_iteration )
	  game_evaluated_count++;
	if ( !force_return )
	  do {
	    changed = FALSE;
	    for ( j = 0; j < game_evaluated_count - 1; j++ )
	      if ( compare_eval( evaluated_list[j].eval,
				 evaluated_list[j + 1].eval ) < 0 ) {
		changed = TRUE;
		temp = evaluated_list[j];
		evaluated_list[j] = evaluated_list[j + 1];
		evaluated_list[j + 1] = temp;
	      }
	  } while ( changed );
	  display_status(stdout, FALSE);
      }

      first_iteration = FALSE;

      /* Reorder the moves after each iteration.  Each move is moved to
	 the front of the list, starting with the bad moves and ending
	 with the best move.  This ensures that unsearched_move will be
	 sorted w.r.t. the order in evaluated_list. */

      for ( i = game_evaluated_count - 1; i >= 0; i-- ) {
	int this_move = evaluated_list[i].move;

	j = 0;
	while ( (j != unsearched_count) && (unsearched_move[j] != this_move) )
	  j++;

	if ( j == unsearched_count )  /* Must be book move, skip */
	  continue;

	/* Move the move to the front of the list. */

	while ( j >= 1 ) {
	  unsearched_move[j] = unsearched_move[j - 1];
	  j--;
	}
	unsearched_move[0] = this_move;
      }
    } while ( !force_return &&
	      ((current_mid != mid) ||
	       (current_exact != exact) || (current_wld != wld)) );

    echo = stored_echo;

    game_evaluated_count = move_count[disks_played];
    
    /* Make sure that the PV and the score correspond to the best move */
    
    pv_depth[0] = best_pv_depth + 1;
    pv[0][0] = best_move;
    for ( i = 0; i < best_pv_depth; i++ )
      pv[0][i + 1] = best_pv[i];

    negate_current_eval( FALSE );
    if ( move_count[disks_played] > 0 )
      set_current_eval( evaluated_list[0].eval );
  }

  /* Reset the hash transformation masks prior to leaving */

  set_hash_transformation( 0, 0 );

  /* Don't forget to enable the time control mechanisms when leaving */

  toggle_abort_check( TRUE );
  toggle_midgame_abort_check( TRUE );
  toggle_perturbation_usage( TRUE );

  max_depth_reached++;
  prefix_move = 0;

  return best_move;
}
예제 #10
0
int
compute_move( int side_to_move,
	      int update_all,
	      int my_time,
	      int my_incr,
	      int timed_depth,
	      int book,
	      int mid,
	      int exact,
	      int wld,
	      int search_forced,
	      EvaluationType *eval_info ) {
  FILE *log_file;
  EvaluationType book_eval_info, mid_eval_info, end_eval_info;
  char *eval_str;
  double midgame_diff;
  enum { INTERRUPTED_MOVE, BOOK_MOVE, MIDGAME_MOVE, ENDGAME_MOVE } move_type;
  int i;
  int curr_move, midgame_move;
  int empties;
  int midgame_depth, interrupted_depth, max_depth;
  int book_move_found;
  int endgame_reached;
  int offset;

  log_file = NULL;
  if ( use_log_file )
    log_file = fopen( log_file_path, "a" );

  if ( log_file )
    display_board( log_file, board, side_to_move, FALSE, FALSE, FALSE );

  /* Initialize various components of the move system */

  piece_count[BLACKSQ][disks_played] = disc_count( BLACKSQ );
  piece_count[WHITESQ][disks_played] = disc_count( WHITESQ );
  init_moves();
  generate_all( side_to_move );
  determine_hash_values( side_to_move, board );

  calculate_perturbation();

  if ( log_file ) {
    fprintf( log_file, "%d %s: ", move_count[disks_played], MOVE_GEN_TEXT );
    for ( i = 0; i < move_count[disks_played]; i++ )
      fprintf( log_file, "%c%c ", TO_SQUARE( move_list[disks_played][i] ) );
    fputs( "\n", log_file );
  }

  if ( update_all ) {
    reset_counter( &evaluations );
    reset_counter( &nodes );
  }

  for ( i = 0; i < 100; i++ )
    evals[disks_played][i] = 0;
  max_depth_reached = 1;
  empties = 60 - disks_played;
  reset_buffer_display();

  determine_move_time( my_time, my_incr, disks_played + 4 );
  if ( !get_ponder_move() )
    clear_ponder_times();

  remove_coeffs( disks_played );

  /* No feasible moves? */

  if ( move_count[disks_played] == 0 ) {
    *eval_info = create_eval_info( PASS_EVAL, UNSOLVED_POSITION,
				   0.0, 0.0, 0, FALSE );
    set_current_eval( *eval_info );
    if ( echo ) {
      eval_str = produce_eval_text( *eval_info, FALSE );
      send_status( "-->         " );
      send_status( "%-8s  ", eval_str );
      display_status( stdout, FALSE );
      free( eval_str );
    }
    if ( log_file ) {
      fprintf( log_file, "%s: %s\n", BEST_MOVE_TEXT, PASS_TEXT );
      fclose( log_file );
    }
    last_time_used = 0.0;
    clear_pv();
    return PASS;
  }

  /* If there is only one move available:
     Don't waste any time, unless told so or very close to the end,
     searching the position. */
   	
  if ( (empties > DISABLE_FORCED_MOVES) &&
       (move_count[disks_played] == 1) &&
       !search_forced ) {  /* Forced move */
    *eval_info = create_eval_info( FORCED_EVAL, UNSOLVED_POSITION,
				   0.0, 0.0, 0, FALSE );
    set_current_eval( *eval_info );
    if ( echo ) {
      eval_str = produce_eval_text( *eval_info, FALSE );
      send_status( "-->         " );
      send_status( "%-8s  ", eval_str );
      free( eval_str );
      send_status( "%c%c ", TO_SQUARE( move_list[disks_played][0] ) );
      display_status( stdout, FALSE );
    }
    if ( log_file ) {
      fprintf( log_file, "%s: %c%c  (%s)\n", BEST_MOVE_TEXT,
	       TO_SQUARE(move_list[disks_played][0]), FORCED_TEXT );
      fclose( log_file );
    }
    last_time_used = 0.0;
    return move_list[disks_played][0];
  }

  /* Mark the search as interrupted until a successful search
     has been performed. */

  move_type = INTERRUPTED_MOVE;
  interrupted_depth = 0;
  curr_move = move_list[disks_played][0];

  /* Check the opening book for midgame moves */

  book_move_found = FALSE;
  midgame_move = PASS;

  if ( forced_opening != NULL ) {
    /* Check if the position fits the currently forced opening */
    curr_move = check_forced_opening( side_to_move, forced_opening );
    if ( curr_move != PASS ) {
      book_eval_info = create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
					 0, 0.0, 0, TRUE );
      midgame_move = curr_move;
      book_move_found = TRUE;
      move_type = BOOK_MOVE;
      if ( echo ) {
	send_status( "-->   Forced opening move        " );
	if ( get_ponder_move() )
	  send_status( "{%c%c} ", TO_SQUARE( get_ponder_move() ) );
	send_status( "%c%c", TO_SQUARE( curr_move ) );
	display_status( stdout, FALSE );
      }
      clear_pv();
      pv_depth[0] = 1;
      pv[0][0] = curr_move;
    }
  }

  if ( !book_move_found && play_thor_match_openings ) {

    /* Optionally use the Thor database as opening book. */

    int threshold = 2;
    database_search( board, side_to_move );
    if ( get_match_count() >= threshold ) {
      int game_index = (my_random() >> 8) % get_match_count();
      curr_move = get_thor_game_move( game_index, disks_played );

      if ( valid_move( curr_move, side_to_move ) ) {
	book_eval_info = create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
					   0, 0.0, 0, TRUE );
	midgame_move = curr_move;
	book_move_found = TRUE;
	move_type = BOOK_MOVE;
	if ( echo ) {
	  send_status( "-->   %s        ", THOR_TEXT );
	  if ( get_ponder_move() )
	    send_status( "{%c%c} ", TO_SQUARE( get_ponder_move() ) );
	  send_status( "%c%c", TO_SQUARE( curr_move ) );
	  display_status( stdout, FALSE );
	}
	clear_pv();
	pv_depth[0] = 1;
	pv[0][0] = curr_move;
      }
      else
	fatal_error( "Thor book move %d is invalid!", curr_move );
    }
예제 #11
0
JNIEXPORT void
JNIFn(zebra, ZebraEngine, zePlay)(JNIEnv *env, jobject thiz, jint providedMoveCount,
                                  jbyteArray providedMoves) {
    EvaluationType eval_info;
    const char *black_name;
    const char *white_name;
    const char *opening_name;
    const char *op;
    double move_start, move_stop;
    int i;
    int side_to_move;
    int curr_move;
    int timed_search;
    int black_hash1, black_hash2, white_hash1, white_hash2;
    ui_event_t evt;
    int provided_move_count;
    int provided_move_index;
    int provided_move[65];
    int silent = FALSE;
    int use_book = s_use_book;

    DROIDZEBRA_JNI_SETUP;

    force_exit = 0;

    if (skill[BLACKSQ] < 0 || skill[WHITESQ] < 0) {
        fatal_error("Set Player Info first");
    }

    /* copy provided moves */
    provided_move_index = 0;
    provided_move_count = 0;
    if (providedMoveCount > 0 && providedMoves) {
        jbyte *providedMovesJNI;
        provided_move_count = providedMoveCount;
        i = (*env)->GetArrayLength(env, providedMoves);
        if (provided_move_count > i)
            fatal_error("Provided move count is greater than array size %d>%d", provided_move_count,
                        i);
        if (provided_move_count > 64)
            fatal_error("Provided move count is greater that 64: %d", provided_move_count);
        providedMovesJNI = (*env)->GetByteArrayElements(env, providedMoves, 0);
        if (!providedMovesJNI)
            fatal_error("failed to get provide moves (jni)");
        for (i = 0; i < provided_move_count; i++) {
            provided_move[i] = providedMovesJNI[i];
        }
        (*env)->ReleaseByteArrayElements(env, providedMoves, providedMovesJNI, 0);
    }

    /* Set up the position and the search engine */
    game_init(NULL, &side_to_move);
    setup_hash(TRUE);
    clear_stored_game();
    set_slack(floor(s_slack * 128.0));
    set_perturbation(floor(s_perturbation * 128.0));
    toggle_human_openings(s_human_opening);
    set_forced_opening(s_forced_opening_seq);
    opening_name = NULL;

    reset_book_search();
    set_deviation_value(0, 0, 0.0);

    if (skill[BLACKSQ] == 0)
        black_name = "Player";
    else
        black_name = "Zebra";

    if (skill[WHITESQ] == 0)
        white_name = "Player";
    else
        white_name = "Zebra";

    set_names(black_name, white_name);
    set_move_list(black_moves, white_moves, score_sheet_row);
    set_evals(0.0, 0.0);

    for (i = 0; i < 60; i++) {
        black_moves[i] = PASS;
        white_moves[i] = PASS;
    }

    black_hash1 = my_random();
    black_hash2 = my_random();
    white_hash1 = my_random();
    white_hash2 = my_random();

    droidzebra_msg_game_start();

    AGAIN:
    curr_move = PASS;
    while (game_in_progress() && !force_exit) {
        force_return = 0;
        silent = (provided_move_index < provided_move_count);

        droidzebra_enable_messaging(!silent);

        droidzebra_msg_move_start(side_to_move);

        remove_coeffs(disks_played);
        clear_evaluated();

        if (SEPARATE_TABLES) {  /* Computer players won't share hash tables */
            if (side_to_move == BLACKSQ) {
                hash1 ^= black_hash1;
                hash2 ^= black_hash2;
            } else {
                hash1 ^= white_hash1;
                hash2 ^= white_hash2;
            }
        }

        generate_all(side_to_move);

        if (side_to_move == BLACKSQ)
            score_sheet_row++;

        // echo
        droidzebra_msg_candidate_moves();
        set_move_list(black_moves, white_moves, score_sheet_row);
        set_times(floor(player_time[BLACKSQ]),
                  floor(player_time[WHITESQ]));
        op = find_opening_name();
        if (op != NULL && (!opening_name || strcmp(op, opening_name))) {
            opening_name = op;
        }
        droidzebra_msg_opening_name(opening_name);
        droidzebra_msg_last_move(disks_played > 0 ? get_stored_move(disks_played - 1) : PASS);
        display_board(stdout, board, side_to_move, TRUE, TRUE, TRUE);
        // echo

        if (move_count[disks_played] != 0) {
            move_start = get_real_timer();
            clear_panic_abort();

            if (provided_move_index >= provided_move_count) {
                if (skill[side_to_move] == 0) {
                    curr_move = -1;

                    if (auto_make_forced_moves && move_count[disks_played] == 1) {
                        curr_move = move_list[disks_played][0];
                    } else {
                        // compute evaluations
                        if (s_practice_mode) {
                            _droidzebra_compute_evals(side_to_move);
                            if (force_exit) break;
                            if (force_return) force_return = 0; // interrupted by user input
                        }

                        // wait for user event
                        droidzebra_msg_get_user_input(side_to_move, &evt);
                        if (evt.type == UI_EVENT_EXIT) {
                            force_exit = 1;
                            break;
                        } else if (evt.type == UI_EVENT_MOVE) {
                            curr_move = evt.evt_move.move;
                            _droidzebra_undo_stack_clear(); // once player makes the move undo info is stale
                        } else if (evt.type == UI_EVENT_UNDO) {
                            _droidzebra_undo_turn(&side_to_move);
                            // adjust for increment at the beginning of the game loop
                            if (side_to_move == BLACKSQ)
                                score_sheet_row--;
                            continue;
                        } else if (evt.type == UI_EVENT_REDO) {
                            _droidzebra_redo_turn(&side_to_move);
                            // adjust for increment at the beginning of the game loop
                            if (side_to_move == BLACKSQ)
                                score_sheet_row--;
                            continue;
                        } else if (evt.type == UI_EVENT_SETTINGS_CHANGE) {
                            _droidzebra_on_settings_change();
                            // repeat move on settings change
                            if (side_to_move == BLACKSQ)
                                score_sheet_row--; // adjust for increment at the beginning of the game loop
                            continue;
                        } else {
                            fatal_error("Unsupported UI event: %d", evt.type);
                        }
                    }
                    assert(curr_move >= 0);
                } else {
                    start_move(player_time[side_to_move],
                               player_increment[side_to_move],
                               disks_played + 4);
                    determine_move_time(player_time[side_to_move],
                                        player_increment[side_to_move],
                                        disks_played + 4);
                    timed_search = (skill[side_to_move] >= 60);
                    toggle_experimental(FALSE);

                    curr_move =
                            compute_move(side_to_move, TRUE, player_time[side_to_move],
                                         player_increment[side_to_move], timed_search,
                                         use_book, skill[side_to_move],
                                         exact_skill[side_to_move], wld_skill[side_to_move],
                                         FALSE, &eval_info);
                    if (side_to_move == BLACKSQ)
                        set_evals(produce_compact_eval(eval_info), 0.0);
                    else
                        set_evals(0.0, produce_compact_eval(eval_info));
                }
            } else {
                curr_move = provided_move[provided_move_index];
                if (!valid_move(curr_move, side_to_move))
                    fatal_error("Invalid move %c%c in move sequence", TO_SQUARE(curr_move));
            }

            move_stop = get_real_timer();
            if (player_time[side_to_move] != INFINIT_TIME)
                player_time[side_to_move] -= (move_stop - move_start);

            store_move(disks_played, curr_move);

            (void) make_move(side_to_move, curr_move, TRUE);
            if (side_to_move == BLACKSQ)
                black_moves[score_sheet_row] = curr_move;
            else {
                white_moves[score_sheet_row] = curr_move;
            }
        } else {
            // this is where we pass
            if (side_to_move == BLACKSQ)
                black_moves[score_sheet_row] = PASS;
            else
                white_moves[score_sheet_row] = PASS;
            if (!auto_make_forced_moves && skill[side_to_move] == 0) {
                droidzebra_msg_pass();
            }
        }

        droidzebra_msg_move_end(side_to_move);

        side_to_move = OPP(side_to_move);

        provided_move_index++;
    }

    droidzebra_enable_messaging(TRUE);

    if (side_to_move == BLACKSQ)
        score_sheet_row++;

    set_move_list(black_moves, white_moves, score_sheet_row);
    set_times(floor(player_time[BLACKSQ]), floor(player_time[WHITESQ]));
    droidzebra_msg_opening_name(opening_name);
    display_board(stdout, board, side_to_move, TRUE, TRUE, TRUE);

    /*
    double node_val, eval_val;
    adjust_counter( &total_nodes );
    node_val = counter_value( &total_nodes );
    adjust_counter( &total_evaluations );
    eval_val = counter_value( &total_evaluations );
    printf( "\nBlack: %d   White: %d\n", disc_count( BLACKSQ ),
            disc_count( WHITESQ ) );
    printf( "Nodes searched:        %-10.0f\n", node_val );

    printf( "Positions evaluated:   %-10.0f\n", eval_val );

    printf( "Total time: %.1f s\n", total_time );
    */

    if (!force_exit)
        droidzebra_msg_game_over();

    // loop here until we are told to exit so the user has a chance to undo
    while (!force_exit) {
        droidzebra_msg_get_user_input(side_to_move, &evt);
        if (evt.type == UI_EVENT_EXIT) {
            force_exit = 1;
            break;
        } else if (evt.type == UI_EVENT_UNDO) {
            _droidzebra_undo_turn(&side_to_move);
            // adjust for increment at the beginning of the game loop
            if (side_to_move == BLACKSQ)
                score_sheet_row--;
            goto AGAIN;
        } else if (evt.type == UI_EVENT_SETTINGS_CHANGE) {
            _droidzebra_on_settings_change();
        }
    }

    DROIDZEBRA_JNI_CLEAN;
}
예제 #12
0
CppInterpreterGenerator::CppInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) {
  generate_all();
}