Exemple #1
0
void tron_state_ai(tron_state_t* state, tron_bike_t* bike) {
    if ( state->player == NULL ) {
        return;
    }

    int their_x = bike->x;
    int their_y = bike->y;
    int my_x = state->player->x;
    int my_y = state->player->y;
    int a = -1000000;
    int b = 1000000;
    p2move = 0;

    p1score = 0;
    p2score = 0;
    p1dist = NULL;
    p2dist = NULL;

    negamax(state, their_x, their_y, my_x, my_y, 6, a, b);

    free(p1dist);
    free(p2dist);

    bike->dir = p2move;
}
Exemple #2
0
int computer_move(int board[9], int human) {
	int computer = human * -1;
	int diff = difficulty();

	// start at random
	if (empty_board(board)) return (rand() % 9);

	// check if there is winning move
	int i;
	for (i=0; i<9; i++) { // for all the positions
		if (board[i]==0) { // if the position is empty
			board[i] = computer; // try the move
			if (iswon(board) == computer) {
				board[i] = 0;
				return i;
			}
			board[i] = 0;
		}
	}

	// for medium difficulty, check if there is blocking move
	if (diff >= 1) {
		for (i=0; i<9; i++) {
			if (board[i] == 0) {
				board[i] = human;
				if (iswon(board) == human) {
					board[i] = 0;
					return i;
				}
				board[i] = 0;
			}
		}
	}

	// for hard difficulty, make the computer unbeatable
	int bestMove, best = -2;
	if (diff >= 2) {
		for (i=0; i<9; i++) {
			if (board[i]==0) {
				board[i] = computer;
				int score = -negamax(board, human);
				board[i] = 0;

				if (score > best) {
					best = score;
					bestMove = i;
				}
			}
		}
		return bestMove;
	}

	// or place anywhere in the blank spot
	int blank[9] = {0,0,0,0,0,0,0,0,0};
	int blank_count = 0;
	for (i=0; i<9; i++)
		if (board[i] == 0)
			blank[blank_count++] = i;
	return blank[rand() % blank_count];
}
Exemple #3
0
unsigned int negamax(tron_state_t* state, int my_x, int my_y,
                                          int their_x, int their_y,
                                          int depth, int a, int b) {

    if ( depth == 0) {
        free(p1dist);
        free(p2dist);

        unsigned int res = evaluate_pos(state, my_x, my_y, their_x, their_y);

        return res;
    }

    int bestmove = 0;
    int bestaltmove = 0;

    for ( int move = 0; move < 4; move++ ) {
        int x = my_x + dx[move];
        int y = my_y + dy[move];

        if ( _filled(state, x, y) ) {
            continue;
        }

        state->grid[POS(x, y)].color = 1;

        int* _p1 = p1dist;
        int* _p2 = p2dist;
        int _p1s = p1score;
        int _p2s = p2score;

        int score = -negamax(state, their_x, their_y, my_x, my_y, depth - 1, b, a);

        state->grid[POS(x, y)].bike = 0;

        if ( score >= a ) {
            a = score;
            bestmove = move;
            bestaltmove = p2move;

            if ( a >= b ) {
                break;
            }
        }
        else {
            free(p1dist);
            free(p2dist);

            p1dist = _p1;
            p1score = _p1s;
            p2dist = _p2;
            p2score = _p2s;
        }
    }

    p2move = bestmove;
    return a;
}
Exemple #4
0
int main(int argc, char **argv) {
    int reps = 1;
    if (argc > 0)
        reps = atoi(argv[1]);
    volatile int j;
    for (int i = 0; i < reps; i++) {
        asm("cpuid" ::: "rax", "rbx", "rcx", "rdx");
        j = negamax(1, board);
    }
    printf("%d\n", j);
    return 0;
}
Exemple #5
0
int negamax(int board[9], int player) {
	// check if terminal node
	if (iswon(board)) return iswon(board)*player;
	else if (filled(board) && !iswon(board)) return 0;

	int best = -2;
	int i;
	for (i=0; i<9; i++) {
		if (board[i] == 0) {
			board[i] = player;
			int score = -negamax(board, player*-1);
			board[i] = 0;

			best = maximum(best, score);
		}
	}

	return best;
}
Exemple #6
0
int negamax(int onmove, int board[3][3]) {
  int v = gamevalue(onmove, board);
  if (v != -2)
    /* game is over */
    return v;
  v = -1;
  for (int r = 0; r < 3; r++) {
    for (int c = 0; c < 3; c++) {
      if (board[r][c] == 0) {
        board[r][c] = onmove;
        int v0 = -negamax(-onmove, board);
        if (v0 > v)
          v = v0;
        board[r][c] = 0;
      }
    }
  }
  return v;
}
Exemple #7
0
struct search_result
search(const struct position *root_pos,
	enum player debug_player_to_move,
	struct search_description sd,
	volatile bool *run_flag,
	const move *prev_pv)
{
	struct node *nodes;
	struct nodes_common_data common;
	struct node *root_node;
	struct pv_store *pv_store;

	pv_store = xmalloc(sizeof(*pv_store));
	pv_store->count = 0;

	nodes = xaligned_calloc(pos_alignment,
	    sizeof(nodes[0]), node_array_length);
	memset(&common, 0, sizeof common);
	common.run_flag = run_flag;
	common.sd = sd;
	common.debug_root_player_to_move = debug_player_to_move;
	setup_node_array(node_array_length, nodes, sd, &common, prev_pv);
	root_node = setup_root_node(nodes, root_pos);

	if (setjmp(common.terminate_jmp_buf) == 0) {
		negamax(root_node);
		extract_pv(pv_store, &common.result, root_node);
		common.result.value = root_node->value;
		common.result.best_move = root_node->best_move;
		common.result.selective_depth = find_selective_depth(nodes);
		common.result.qdepth = find_qdepth(nodes);
	}
	else {
		common.result.is_terminated = true;
	}

	xaligned_free(nodes);
	free(pv_store);
	return common.result;
}
Exemple #8
0
int AI::negamax(const t_flag& team, const int& profondeur) {
    int max;
    int tmp;

    max = eval();
    if (profondeur == 0 || verifWin() != 0)
        return max;
    for (int y = 0; y != 19; y++) {
        for (int x = 0; x != 19; x++) {
            if (_mapRule[y][x] == FREE) {
                _mapRule[y][x] = team;
                
                tmp = negamax(invertTeam(team), profondeur - 1);

                if ((tmp > max))
                    max = tmp;
                _mapRule[y][x] = FREE;
            }
        }
    }
    return max;
}
	Board search_move(Board board, bool output){
		board.scorefunc = scorefunc;

		Board children[288];
		int numchildren = board.getchildren(children, true);
		depths[maxdepth] = numchildren;

		int best = 0; //index to element in children with the highest score
		int ret;
		int alpha = 2000000000;

	//can only choose one best move, because all after it also claim to be best, even if they're not
		for(int i = 0; i < numchildren; i++){
			ret = negamax(children[i], maxdepth, -2000000000, alpha);

			if(alpha > ret){
				alpha = ret;
				best = i;
			}
		}

		return children[best];
	}
Exemple #10
0
int AI::minMax(const t_flag& team) {
    int max = -1000000000;
    int tmp, maxY = 0, maxX = 0;
    int profondeur = 1;
    
    for (int y = 0; y != 19; y++) {
        for (int x = 0; x != 19; x++) {
            if (_mapRule[y][x] == FREE) {
                _mapRule[y][x] = team;
                
                tmp = negamax(invertTeam(team), profondeur - 1);
                
                if (tmp > max) {
                    max = tmp;
                    maxY = y;
                    maxX = x;
                }                
                _mapRule[y][x] = FREE;
            }
        }
    }
    return (maxY * 19) + maxX;
}
Exemple #11
0
static int
negamax_child(struct node *node)
{
	if (node[1].beta < - mate_value && node[1].beta > - max_value)
		node[1].beta--;
	if (node[1].alpha < - mate_value && node[1].alpha > - max_value)
		node[1].alpha--;
	if (node[1].beta > mate_value && node[1].beta < max_value)
		node[1].beta++;
	if (node[1].alpha > mate_value && node[1].alpha < max_value)
		node[1].alpha++;

	negamax(node + 1);

	if (node->forced_pv == 0)
		node[1].forced_pv = 0;

	int value = -node[1].value;

	if (node->common->sd.settings.use_strict_repetition_check) {
		node->repetition_affected_any = max(
		    node->repetition_affected_any,
		    node[1].repetition_affected_best - 1);
	}

	/*
	 * Decrement a mate value each time it is passed down towards root,
	 * so represent that "mate in 5" is better than "mate in 6" --> the
	 * closer to the root the checkmate is, the better is is.
	 */
	if (value > mate_value)
		return value - 1;
	else if (value < - mate_value)
		return value + 1;
	else
		return value;
}
Exemple #12
0
	bool Medium::move()
	{
		srand((unsigned)time(0));
		int rnd=rand()%2;

		if(rnd==0)
		{
			ReversiBoard* b=ReversiBoard::getBoardInstance();
			std::vector<std::pair<int, std::vector<std::pair<int, int>>>> moves=b->GetMoves(BLACK);

			if(moves.empty())
				return false;

			srand((unsigned)time(0));
			int rnd=(int)((moves.size()*rand())/(RAND_MAX+1.0));

			b->MakeMove(moves[rnd].first/8,moves[rnd].first%8,BLACK,moves[rnd].second);

			return true;
		}
		else
		{
			ReversiBoard* b=ReversiBoard::getBoardInstance();
			int x = negamax(BLACK, 3);
			std::vector<std::pair<int, std::vector<std::pair<int, int>>>> moves=b->GetMoves(BLACK);
			for(auto it=moves.begin(); it != moves.end(); it++) 
			{
				if(x==((*it).first)) 
				{
					b->MakeMove(x/8, x%8, BLACK, (*it).second);
					return true;
				}
			}

			return false;
		}
	}
Exemple #13
0
//https://en.wikipedia.org/wiki/Negamax#Negamax_with_alpha_beta_pruning
int negamax(Game *game, int alpha, int beta, int depth, int *best) {
	int j; //current column
	int cut = 0; //did we get a CUT at some point?
	int best_score = DEFEAT; //best score we've seen so far
	int one_decision = 0; //have we ever taken a real decision?
	if (!depth)
		return CUT; //the search space is often way too large
	for (j=0; j<game->cols; j++) {
		if (can_play(game, j)) {
			play(game, j); {
				int v;
				if (victory(game, j)) //this has to be done here
					v = VICTORY; //since the last move is unknown...
				else {
					int trash; //we don't care about the next move
					v = -negamax(game, -beta, -alpha, depth-1, &trash);
				}
				if (-v == CUT) //check the original return value
					cut = 1;
				else {
					v /= 2; //so, longer paths are less interesting
					one_decision = 1;
					//update best* variables
					if (best_score < v) {
						best_score = v;
						*best = j;
					}
					alpha = MAX(alpha, v);
				}
			} undo(game, j);
			if (alpha >= beta)
				break; //prune
		}
	}
	return (!one_decision && cut) ? CUT : best_score;
}
Exemple #14
0
///
/// Returns struct move {slot, value}, where slot is the index of the move on the game grid which yields the best value.
///
struct move negamax(int game_grid[], int player) {
	// To start with, we have to check if the game is still on.
	int situation = check_situation(game_grid);
	int max = -1;
	move best_move = {-1, -1};

	// check_situation() returns 0 if the game hasn't ended yet.
	if (situation == 0) {
		// For each legal move on the board, find the one which maximizes the minimum gain.
		int i;
		for(i = 0; i < GRID_SIZE; i++) {
			if (game_grid[i] == 0) {
				int* temp_grid = malloc(sizeof(int)*GRID_SIZE);
				if (temp_grid != NULL) {
					int n;
					for (n = 0; n < GRID_SIZE; n++) {
						temp_grid[n] = game_grid[n];
					}
					int current_slot = i;
					temp_grid[i] = player;

					move x = negamax(temp_grid, ((player%2)+1));
					if (-(x.max) > max) {
						best_move.max = -(x.max);
						best_move.slot = current_slot;
						max = -(x.max);
					}
					free(temp_grid);
				}
				else {
					printf("I CAN HAS NO MEMORY!!1\n");
					exit(EXIT_FAILURE);
				}
			}
		}
	}
	// Now, if the game has indeed ended, check_situation() returns:
	// 1 if X has won
	// -1 if O has won
	// 10 if the end result was a tie.
	else if (situation == 1) {
		if (player == 1) {
			best_move.max = 1;
		}
		else
			best_move.max = -1;
	}
	else if (situation == -1) {
		if (player == 2) {
			best_move.max = 1;
		}
		else
			best_move.max = -1;
	}
	else if (situation == 10) {
		best_move.max = 0;
	}
	else {
		printf("An unknown error has occured.\n");
		exit(EXIT_FAILURE);
	}
		
	return best_move;
}
Exemple #15
0
int main(int argc, char *argv[]) {
	Game *game = create_game(ROWS, COLS);
	if (argc==3 && !strcmp(argv[1], "display")) {
		char *p = argv[2];
		char *err;
		while (*p) {
			int col = *p - '0';
			if (col>=0 && col<COLS) {
				if (can_play(game, col)) {
					play(game, col);
					if (victory(game, col))
						printf("victory!\n");
				}
				else {
					err = "illegal move";
					goto err_handler;
				}
			}
			else {
				int i;
				err = "unknown move syntax";
err_handler:
				fprintf(stderr, "error: %s.\n%s\n", err, argv[2]);
				for (i=0; i<p-argv[2]; i++)
					fprintf(stderr, " ");
				fprintf(stderr, "^\n");
				return 2;
			}
			p++;
		}
		print_board(game);
	}
	else if ((argc==2 || argc==3) && !strcmp(argv[1], "play")) {
		int j;
		if (argc==3 && !strcmp(argv[2], "red"))
			goto red;
		while (1) {
			print_board(game);
			do {
				printf("Your move: ");
				if (scanf("%d", &j) != 1) {
					printf("\n");
					goto out;
				}
			} while (!can_play(game, j));
			play(game, j);
			if (victory(game, j)) {
				printf("You've won!\n");
				break;
			}
			else {
				int ret = negamax(game, DEFEAT, VICTORY, 12, &j);
red:
				if (ret == CUT)
					printf("I've got no idea what to do...\n"
						"I'm gonna try %d.\n", j);
				else
					printf("I'll play %d (score %d)\n", j, ret);
				play(game, j);
				if (victory(game, j)) {
					printf("You've lost!\n");
					break;
				}
			}
		}
		print_board(game);
	}
	else {
		fprintf(stderr, "usage:\t%s display moves\n", argv[0]);
		fprintf(stderr, "\t%s play [yellow|red]\n", argv[0]);
		fprintf(stderr, "try:\t%s display 01221\n", argv[0]);
		fprintf(stderr, "\t%s play\n", argv[0]);
		return 1;
	}
out:
	destroy_game(game);
	return 0;
}
Exemple #16
0
//=================================================================
// Negamax Function.
//=================================================================
static s32bit
negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta)
{
  Move   movelist[MAXMOVES], best;
  s32bit whos_turn = whos_turn_t & PLAYER_MASK;
  s32bit opponent  = whos_turn_t ^ PLAYER_MASK;
  s32bit value;
  s32bit init_alpha = alpha, init_beta = beta;
  u32bit start_nodes = g_num_nodes;
  Move   forcefirst;
  s32bit who_wins_value;

  s32bit stage = 0, state = 0, true_count, i = 0, num_moves = 1;

#ifdef DYNAMIC_POSITION_VALUES
  s32bit dyn_set;
#endif

  // increment a couple of stats
  g_num_nodes++;
#ifdef COLLECT_STATS
  stat_nodes[starting_depth - depth_remaining]++;
#endif

  // if no depth remaining stop search.
  if( depth_remaining <= 0 ){
    s32bit a = 0, b = 0;

    if( (a = does_next_player_win(whos_turn, 0)) > 0 ) {
      // current player wins.
      return 5000;
    }

    if( (b = does_who_just_moved_win(opponent, 0)) >= 0 ) {
      // opponent wins.
      return -5000;
    }
  
    return a - b;
  }
  

  //------------------------------------------
  // Can we determine a winner yet (simple check).
  //------------------------------------------

  // does current player win
  if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){
#ifdef COLLECT_STATS
    cut1++;
#endif
    return 5000;
  }
  
  // does opponent win
  if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){
#ifdef COLLECT_STATS
    cut2++;
#endif
    return -5000;
  }


  //------------------------------------------
  // check transposition table
  //------------------------------------------

  forcefirst.array_index = -1;
  if(hashlookup(&value, &alpha, &beta, depth_remaining,
                &forcefirst, whos_turn))
    return value;
  // since we aren't using iter deep not interested in forcefirst.
  forcefirst.array_index = -1;
  

  //------------------------------------------
  // Can we determine a winner yet (look harder).
  //------------------------------------------

  // does current player win
  if( (who_wins_value = does_next_player_win(whos_turn, 0)) > 0 ) {

#ifdef DEBUG_NEGAMAX
    if(random() % 1000000 == -1){
      does_next_player_win(whos_turn, 1);
      print_board(whos_turn);
    }
#endif

#ifdef COLLECT_STATS
    cut3++;
#endif
    return 5000;
  }
    
  // does opponent win
  if( (who_wins_value = does_who_just_moved_win(opponent, 0)) >= 0 ) {

#ifdef DEBUG_NEGAMAX
    if(who_wins_value < 3){ // && random() % 500 == -1){
      does_who_just_moved_win(opponent, 1);
      //  print_board(opponent);
    }
#endif  

#ifdef COLLECT_STATS
    cut4++;
#endif
    return -5000;
  }

#if 0
  {
    s32bit num;
    num = move_generator_stage1(movelist, whos_turn);
    num = move_generator_stage2(movelist, num, whos_turn);
    if(move_generator(movelist, whos_turn) != num)
      fatal_error(1, "NOPE\n");
  }
#endif


  //------------------------------------------
  // Generate child nodes and examine them.
  //------------------------------------------

  // initialize a few variables. (some of them don't really need to be.)
  stage = state = true_count = i = 0;
  num_moves = 1;

#ifdef TWO_STAGE_GENERATION
  true_count = move_generator_stage1(movelist, whos_turn);
  if(true_count == 0){
    true_count = move_generator_stage2(movelist, 0, whos_turn);
    stage = 1;
    if(true_count == 0) fatal_error(1, "Should always have a move.\n");
  }
#else
  true_count = move_generator(movelist, whos_turn);
  stage = 1;
  if(true_count == 0)   fatal_error(1, "Should always have a move.\n");
#endif
  
  // score all the moves and move the best to the front.
  score_and_get_first(movelist, true_count, whos_turn, forcefirst);
  
  best = movelist[0];
  
  // need to sort moves and generate more moves in certain situations.
  while(state < 3){
    if(state == 0) {
      state = 1;
    } else if(state == 1){
      sort_moves(movelist, 1, true_count);
      num_moves = true_count;
      if(stage == 0) state = 2;
      else           state = 3;
    } else {
      num_moves = move_generator_stage2(movelist, num_moves, whos_turn);
      state = 3;
    }
    
    // Iterate through all the moves.
    for(; i < num_moves; i++){

      // A few statistics
      g_move_number[starting_depth - depth_remaining] = i;
#ifdef RECORD_MOVES
      g_move_player[starting_depth - depth_remaining] = whos_turn;
      g_move_position[starting_depth - depth_remaining] = movelist[i];
#endif

      // make move.
      g_empty_squares -= 2;
      toggle_move(movelist[i], whos_turn);
      toggle_hash_code
    (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
#ifdef DYNAMIC_POSITION_VALUES
      dyn_set = set_move_value(movelist[i], whos_turn);
#endif
      
      // recurse.
      value = -negamax(depth_remaining-1,whos_turn^PLAYER_MASK,
                       -beta, -alpha);
      
      // undo move.
      g_empty_squares += 2;
      toggle_move(movelist[i], whos_turn);
      toggle_hash_code
    (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
#ifdef DYNAMIC_POSITION_VALUES
      if(dyn_set != 0) unset_move_value(movelist[i], whos_turn);
#endif

#if 0
      if(starting_depth - depth_remaining == 8) {
        s32bit g;
        
        printf("goof:");
        
        for(g = 0; g < 8; g++){
          printf(" :%c:%d(%d,%d)", 
                 (g_move_player[g] == VERTICAL) ? 'V' : 'H',
                 g_move_number[g],
                 g_move_position[g].array_index - 1,
                 g_move_position[g].mask_index - 1);
        }
        printf("\n");
      }
#endif

      // If this is a cutoff, break.
      if(value >= beta){
        alpha = value;
        best  = movelist[i];
        
#ifdef COLLECT_STATS
        stat_cutoffs[starting_depth - depth_remaining]++;
        if(i < 5) stat_nth_try[starting_depth - depth_remaining][i]++;
        else      stat_nth_try[starting_depth - depth_remaining][5]++;
#endif
        break;
      }
      
      // If the current value is greater than alpha, increase alpha.
      if(value > alpha) {
        alpha = value;
        best  = movelist[i];
      }
    }

    // If we have broken out of previous FOR loop make sure we break out
    //   of this loop as well.
    if(value >= beta) break;
  }
  
  // save the position in the hashtable
  hashstore(alpha, init_alpha, init_beta, (g_num_nodes - start_nodes) >> 5,
            depth_remaining, best, whos_turn);
  
  return alpha;
}
Exemple #17
0
//=================================================================
// Search for move function. (Negamax Driver)
//=================================================================
extern s32bit
search_for_move(char dir, s32bit *row, s32bit *col, u64bit *nodes)
{
  s32bit  d, i, value = 0, num_moves;
  Move    movelist[MAXMOVES];
  s32bit  whos_turn;
  Move    forcefirst;
    
  // Set who's turn it is.
  if(toupper(dir) == 'V')      whos_turn = VERTICAL;
  else if(toupper(dir) == 'H') whos_turn = HORIZONTAL;
  else { fatal_error(1, "Invalid player.\n"); exit(1); }
  
  // initialize the number of empty squares.
  g_empty_squares = 0;
  for(i = 0; i < g_board_size[0]; i++)
    g_empty_squares += countbits32( (~g_board[0][i+1]) );
  
  // zero out all the statistics variables.
  init_stats();
  
  // Can we already determine a winner?
  {
    s32bit opponent = whos_turn ^ PLAYER_MASK;
    
    // stop search if game over.
    if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){
      // current player wins.
      *col = *row = -1;
      *nodes = 0;
      return 5000;
    }
    
    if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){
      // opponent wins.
      *col = *row = -1;
      *nodes = 0;
      return -5000;
    }
  }
  
  // generate all possible moves for current player given current position.
  num_moves = move_generator(movelist, whos_turn);

  // This should never happen.
  if(num_moves == 0) fatal_error(1, "No moves");

  // should possibly sort the whole list instead of just get first.
  forcefirst.array_index = -1;
  score_and_get_first(movelist, num_moves, whos_turn, forcefirst);
  sort_moves(movelist, 1, num_moves);

  // Really this is for iterative deepening.
  for(d = 1; d < 50; d += 44){

    // Initialize alpha and beta.
    s32bit alpha = -5000, beta = 5000;

    // Re-initialize the statistics for each iteration.
    g_num_nodes = 0;
    init_stats();

    // set what the starting max depth is.
    starting_depth = d;
        
    // iterate through all the possible moves.
    for(i = 0; i < num_moves; i++){

#ifdef DYNAMIC_POSITION_VALUES
      init_move_value();
      set_move_value(movelist[i], whos_turn);
#else
      set_position_values();
#endif
      
      g_move_number[0] = i;
#ifdef RECORD_MOVES
      g_move_player[0] = whos_turn;
      g_move_position[0] = movelist[i];
#endif
      
      g_empty_squares -= 2;
      toggle_move(movelist[i], whos_turn);
      toggle_hash_code
    (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
      check_hash_code_sanity();
      
      value = -negamax(d-1, whos_turn^PLAYER_MASK, -beta, -alpha);
      
#ifdef DYNAMIC_POSITION_VALUES
      unset_move_value(movelist[i], whos_turn);
#endif

      g_empty_squares += 2;
      toggle_move(movelist[i], whos_turn);
      toggle_hash_code
    (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
      check_hash_code_sanity();

      printf("Move (%d,%d), value %d: %s.\n",
             movelist[i].array_index, movelist[i].mask_index,
             value, u64bit_to_string(g_num_nodes));
      printf("alpha %d, beta %d.\n", alpha, beta);

      movelist[i].info = value;

      if(value >= beta){
        alpha = value;
        break;
      }
      if(value > alpha) {
        alpha = value;
      }
    }

    if(value >= 5000){
      printf("Winner found: %d.\n", value);
      if(whos_turn == HORIZONTAL){
        *row = movelist[i].array_index;
        *col = movelist[i].mask_index;
      } else if(whos_turn == VERTICAL){
        *col = movelist[i].array_index;
        *row = movelist[i].mask_index;
      } else {
        fatal_error(1, "oops.");
      }
      
      *nodes = g_num_nodes;

      print_stats();
      
      return value;
    }

    // remove lossing moves from movelist.
    {
      s32bit rem = 0;
      for(i = 0; i < num_moves; i++){
        if(movelist[i].info <= -5000) rem++;
        else if(rem > 0) movelist[i-rem] = movelist[i];
      }
      num_moves -= rem;
      /*
      for(i = 0; i < num_moves; i++){
        printf("(%d,%d): %d.\n",
               movelist[i].array_index, movelist[i].mask_index,
               movelist[i].info);
      }
      */
    }

    print_stats();
    
    if(num_moves == 0){
      break;
    }
    
    // use a stable sort algorithm
    {
      Move swp;
      s32bit max, index, j;
      
      for(i=0; i<num_moves; i++) {
        max = movelist[i].info;
        index = i;
        
        for(j=i+1; j < num_moves; j++)
          if(movelist[j].info > max){
            max = movelist[j].info;
            index = j;
          }
    
        if(index != i){
          swp = movelist[index];
          //          printf("%d %d\n", index, i);
          for(j = index; j != i; j--){
            movelist[j] = movelist[j-1];
          }
          movelist[i] = swp;
        }
      }
    }
    
    printf("The value is %d at a depth of %d.\n", value, d);
    printf("Nodes: %u.\n", (u32bit)g_num_nodes);
  }

  *col = *row = -1;
  *nodes = g_num_nodes;

  return value;
}
Exemple #18
0
void iterate(
        dict *d, lin_dict *ko_ld,
        node_value *base_nodes, node_value *pass_nodes, node_value *ko_nodes, value_t *leaf_nodes,
        state *s, size_t key_min, int japanese_rules
    ) {
    state child_;
    state *child = &child_;

    size_t num_states = num_keys(d);

    int changed = 1;
    while (changed) {
        changed = 0;
        size_t key = key_min;
        for (size_t i = 0; i < 2 * num_states + ko_ld->num_keys; i++) {
            if (i < 2 * num_states) {
                assert(from_key(s, key));
                if (i % 2 == 1) {
                    s->passes = 1;
                }
            }
            else {
                key = ko_ld->keys[i - 2 * num_states];
                size_t ko_pos = key % STATE_SIZE;
                key /= STATE_SIZE;
                assert(from_key(s, key));
                s->ko = 1UL << ko_pos;
            }
            node_value new_v = (node_value) {VALUE_MIN, VALUE_MIN, DISTANCE_MAX, 0};
            for (int j = -1; j < STATE_SIZE; j++) {
                size_t child_key;
                node_value child_v;
                *child = *s;
                stones_t move;
                if (j == -1){
                    move = 0;
                }
                else {
                    move = 1UL << j;
                }
                if (make_move(child, move)) {
                    canonize(child);
                    child_key = to_key(child);
                    if (child->passes == 2){
                        value_t score = leaf_nodes[key_index(d, child_key)];
                        child_v = (node_value) {score, score, 0, 0};
                    }
                    else if (child->passes == 1) {
                        child_v = pass_nodes[key_index(d, child_key)];
                    }
                    else if (child->ko) {
                        child_key = child_key * STATE_SIZE + bitscan(child->ko);
                        child_v = ko_nodes[lin_key_index(ko_ld, child_key)];
                    }
                    else {
                        child_v = base_nodes[key_index(d, child_key)];
                    }
                    if (japanese_rules) {
                        int prisoners = (popcount(s->opponent) - popcount(child->player)) * PRISONER_VALUE;
                        if (child_v.low > VALUE_MIN) {
                            child_v.low = child_v.low - prisoners;
                        }
                        if (child_v.high < VALUE_MAX) {
                            child_v.high = child_v.high - prisoners;
                        }
                    }
                    new_v = negamax(new_v, child_v);
                }
            }
            assert(new_v.high_distance > 0);
            if (i < 2 * num_states) {
                if (i % 2 == 0) {
                    assert(new_v.low_distance > 1);
                    assert(new_v.high_distance > 1);
                    assert(new_v.low >= base_nodes[i / 2].low);
                    assert(new_v.high <= base_nodes[i / 2].high);
                    changed = changed || !equal(base_nodes[i / 2], new_v);
                    base_nodes[i / 2] = new_v;
                }
                else {
                    changed = changed || !equal(pass_nodes[i / 2], new_v);
                    pass_nodes[i / 2] = new_v;
                    key = next_key(d, key);
                }
            }
            else {
                changed = changed || !equal(ko_nodes[i - 2 * num_states], new_v);
                ko_nodes[i - 2 * num_states] = new_v;
            }
        }
        print_node(base_nodes[0]);
    }
    for (size_t i = 0; i < ko_ld->num_keys; i++) {
        assert(ko_nodes[i].low_distance > 2);
        assert(ko_nodes[i].high_distance > 2);
    }

    for (size_t i = 0; i < num_states; i++) {
        assert(base_nodes[i].low_distance > 1);
        assert(base_nodes[i].high_distance > 1);
        assert(pass_nodes[i].low_distance > 0);
        assert(pass_nodes[i].high_distance > 0);
    }
}
Exemple #19
0
static void
extract_pv(struct pv_store *pv_store,
		struct search_result *result, struct node *root)
{
	int pv_len = 0;
	int iteration = 0;

#ifndef NDEBUG
	char debug_move_stack[0x1000];
	char *c;
#endif

	int extension_location = -1;
next_iteration:

	pv_len = 0;

#ifndef NDEBUG
	c = debug_move_stack;
#endif

	while (root->pv[pv_len] != 0) {
#ifndef NDEBUG
		*c++ = ' ';
		c = print_coor_move(root->pv[pv_len], c,
		    ((pv_len % 2)
		    ? opponent_of(root->debug_player_to_move)
		    : (int)root->debug_player_to_move));
#endif
		result->pv[pv_len] = root->pv[pv_len];
		root[pv_len].forced_pv = root->pv[pv_len];
		pv_store->pvs[pv_store->count][pv_len] = root->pv[pv_len];
		++pv_len;
	}

	result->pv[pv_len] = 0;

	if (!root->common->sd.settings.use_pv_cleanup)
		return;

	pv_store->pvs[pv_store->count][pv_len] = 0;

	if (++iteration > 98)
		return;

	if (root->depth < 3 * PLY)
		return;

	if (pv_len == 0)
		return;

	if (has_same_pv_in_pv_store(pv_store, root->pv)) {
		if (extension_location == 1)
			return;

		if (extension_location != -1)
			root[extension_location].forced_extension = 0;

		int new_ext = find_common_prefix_length(pv_store) - 1;
		if (new_ext < 1)
			return;

		if (extension_location == -1 || new_ext < extension_location)
			extension_location = new_ext;
		else
			--extension_location;
		root[extension_location].forced_extension = 1;

		pv_store->pvs[0][0] = root->best_move;
		pv_store->pvs[0][1] = 0;
		pv_store->count = 1;
		goto next_iteration;
	}

	pv_store->count++;

	for (int i = pv_len; i < node_array_length - 1; ++i)
		root[i].forced_pv = 0;

	if (root->value == 0)
		return;

	if (root->value <= -mate_value || root->value >= mate_value)
		return;

	if (pv_len >= root->depth / PLY - 1)
		return;

	root->alpha = -max_value;
	root->beta = max_value;
	root->expected_type = PV_node;
	negamax(root);

	goto next_iteration;
}
Exemple #20
0
/* Calculate the power of left and right motors */
void DetermineMouseAction(double *lPow, double *rPow, int *, RobotMap *map,externalRobot *robots)
{
    static int counter=0;


    static float  left; //value of frontal left sonar sensor
    static float right; //value of frontal rigth sonar sensor
    static float center; //value of frontal center sonar sensor
    static bool   Collision;// collision sensor
    static float Compass = 0; //compass sensor
    static float X = -1; // GPS x value
    static float Y = -1; //GPS yvalue


  // SENSORS ACCESS

    /*Access to values from Sensors - Only ReadSensors() gets new values */
    if(IsObstacleReady(LEFT))
        left=     GetObstacleSensor(LEFT);
    if(IsObstacleReady(RIGHT))
        right=    GetObstacleSensor(RIGHT);
    if(IsObstacleReady(CENTER))
        center=   GetObstacleSensor(CENTER);

    if(IsBumperReady())
        Collision= GetBumperSensor();
    if(IsCompassReady()){
        Compass= GetCompassSensor();
        //printf("orientation %f\n", Compass);
    }
    if(IsGPSReady()){
        if(X < 0 || Y < 0){
            map->setOffset(GetX(),GetY());
        }
        X= GetX();
        Y= GetY();
    }



    float multiplier[8] = {1,1,1,1,1,1,1,1};


    if(center>3.0 || right> 4.0 || left>4.0 || Collision) { /* Close Obstacle - Rotate */
        if(right < left) {
              *lPow=0.06;
               *rPow=-0.06;
        }  else {
               *lPow=-0.06;
               *rPow=0.06;
        }

    } else {
        if(left > 1.0){
            //give a penalty on score if theres an obstacle on the left side
            multiplier[side_frontleft] = multiplier[side_left] = multiplier[side_backleft] = 1/left;
        }
        if(right > 1.0){
            //give a penalty on score if theres an obstacle on the right side
            multiplier[side_frontright] = multiplier[side_right] = multiplier[side_backright] = 1/right;
        }
        if(center > 1.0){
            //give a penalty on score if theres an obstacle on the front
            multiplier[side_frontright] = multiplier[side_frontleft] = multiplier[side_front] = 1.25/right;
        }

        //always favor going to front to avoid slowing down
        multiplier[side_frontright] *= 1.25;
        multiplier[side_frontleft] *= 1.25;
        multiplier[side_front] *= 1.25;





        float orientations[8] = {Compass,Compass + 45,Compass + 90,Compass + 135,Compass + 180,
                Compass - 135,Compass - 90,Compass - 45};

        float distance = 2;

        float score[8];

        float maxScore = 0;
        int maxScoreSide = 0;


        for(int i=0;i<8;++i){
            float x= X + distance * cos(M_PI * orientations[i] / 180);
            float y= Y + distance * sin(M_PI * orientations[i] / 180);

            if(i == side_front){
                double val = map->getValue(x,y);
                if(center < 2.0){
                    val += 0.2;
                    map->setValue(x,y,(val > 1.0)?1.0:val);
                } else {
                    val -= 0.2;
                    map->setValue(x,y,(val < 0.0)?0.0:val);
                }
            } else if(i == side_frontleft){
                double val = map->getValue(x,y);
                if(left < 2.0){
                    val += 0.2;
                    map->setValue(x,y,(val > 1.0)?1.0:val);
                } else {
                    val -= 0.2;
                    map->setValue(x,y,(val < 0.0)?0.0:val);
                }
            }else if(i == side_frontright){
                double val = map->getValue(x,y);
                if(right < 2.0){
                    val += 0.2;
                    map->setValue(x,y,(val > 1.0)?1.0:val);
                } else {
                    val -= 0.2;
                    map->setValue(x,y,(val < 0.0)?0.0:val);
                }
            }

            float points = 0;
            for(int j=0;j<5;++j){
                if(robots[j].isCat){
                    points += negamax(x,y,robots[j].x,robots[j].y);
                }
            }

            multiplier[i] -= penaltyScore(map,x,y);


            points *= multiplier[i];
            score[i] = points;
            if(i==0){
               maxScore = points;

            } else if(points > maxScore){
                maxScore = points;
                maxScoreSide = i;
            }
        }
        switch (maxScoreSide) {
        case side_front:
            *lPow=0.1;
            *rPow=0.1;
            break;
        case side_frontleft:
            *lPow=0.08;
            *rPow=0.1;
            break;
        case side_left:
            *lPow=0.03;
            *rPow=0.1;
            break;
        case side_backleft:
            *lPow=-0.02;
            *rPow=0.1;
            break;
        case side_back:
            if(score[3] > score[5]){
                *lPow=-0.1;
                *rPow=0.1;
            } else {
                *lPow=0.1;
                *rPow=-0.1;
            }
            break;
        case side_backright:
            *rPow=-0.02;
            *lPow=0.1;
            break;
        case side_right:
            *rPow=0.03;
            *lPow=0.1;
            break;
        case side_frontright:
            *rPow=0.08;
            *lPow=0.1;
            break;
        default:
            break;
        }
    }




    counter++;
}