Ejemplo n.º 1
0
int get_shallow_move(int *board, int side) {
    /* Return the move that gives the best position immediately after
     */
    int i;
    int move = 0;
    int score;
    int flips[20];
    int old_board[100];
    int best_score = MIN_SCORE;
    // backup the existing board
    copy_board(board, old_board);
    for (i=11; i<89; ++i) {
        if (legal_move(board,i,side,flips) == 1) {
            make_move(board,i,side,flips);
            score = evaluate_board(board, side, 0);
            if (score > best_score) {
                best_score = score;
                move = i;
            }
            // reset the board before each iteration
            copy_board(old_board, board);
        }
    }
    return move;
}
Ejemplo n.º 2
0
int have_legal_moves (othello_bd *bd) {
  for (int i = 0 ; i < X_SIZE ; ++i) {
    for (int j = 0 ; j < Y_SIZE ; ++j) {
      if (legal_move(bd,i,j)) {
        return true;
      }
    }
  }
  return false;
}
Ejemplo n.º 3
0
/* Generate a move. */
static void
generate_move(int *i, int *j, int color)
{
  int moves[MAX_BOARD * MAX_BOARD];
  int num_moves = 0;
  int move;
  int ai, aj;
  int k;

  memset(moves, 0, sizeof(moves));
  for (ai = 0; ai < board_size; ai++)
    for (aj = 0; aj < board_size; aj++) {
      /* Consider moving at (ai, aj) if it is legal and not suicide. */
      if (legal_move(ai, aj, color)
	  && !suicide(ai, aj, color)) {
	/* Further require the move not to be suicide for the opponent... */
	if (!suicide(ai, aj, OTHER_COLOR(color)))
	  moves[num_moves++] = POS(ai, aj);
	else {
	  /* ...however, if the move captures at least one stone,
           * consider it anyway.
	   */
	  for (k = 0; k < 4; k++) {
	    int bi = ai + deltai[k];
	    int bj = aj + deltaj[k];
	    if (on_board(bi, bj) && get_board(bi, bj) == OTHER_COLOR(color)) {
	      moves[num_moves++] = POS(ai, aj);
	      break;
	    }
	  }
	}
      }
    }

  /* Choose one of the considered moves randomly with uniform
   * distribution. (Strictly speaking the moves with smaller 1D
   * coordinates tend to have a very slightly higher probability to be
   * chosen, but for all practical purposes we get a uniform
   * distribution.)
   */
  if (num_moves > 0) {
    move = moves[xor_randn(num_moves)];
    *i = I(move);
    *j = J(move);
  }
  else {
    /* But pass if no move was considered. */
    *i = -1;
    *j = -1;
  }
}
Ejemplo n.º 4
0
static int
gtp_play(char *s)
{
  int i, j;
  int color = EMPTY;

  if (!gtp_decode_move(s, &color, &i, &j))
    return gtp_failure("invalid color or coordinate");

  if (!legal_move(i, j, color))
    return gtp_failure("illegal move");

  play_move(i, j, color);
  return gtp_success("");
}
Ejemplo n.º 5
0
int get_random_move(int *board, int side) {
    /* Randomly pick a move!
     * Mostly used for simulating other AI algorithms
     */
    int move;
    int counter = 0;
    int possible_moves[64];
    int flips[20];
    for(int i=11; i<89; ++i) {
        if (legal_move(board,i,side,flips)) {
            possible_moves[counter] = i;
            counter++;
        }
    }
    // Using modulus with rand is not ideal, but it's good enough
    // Problem is that it can give skewed results
    move = possible_moves[(rand() % counter)];
    return move;
}
Ejemplo n.º 6
0
int minimize(int *board, int side, int unplayed, int ply) {
    /* Search to depth ply with mutual recursion
     * Side should be the opponent of currently playing side
     * Return the lowest score found
     */
    int old_board[100];
    int flips[20];
    int score = MAX_SCORE;
    if (ply == 0 || test_end(board, unplayed) == 1)
        return evaluate_board(board, side, unplayed);
    copy_board(board, old_board);
    for (int i=11; i<89; ++i) {
        if (legal_move(board, i, side, flips) == 0)
            continue;
        make_move(board, i, side, flips);
        score = MIN(score, maximize(board, -side, 0, ply-1));
        copy_board(old_board, board);
    }
    return score;
}
Ejemplo n.º 7
0
int ab_minimize(int *board, int side, int unplayed, int ply,int a, int b) {
    /* Search to depth ply with mutual recursion
     * Return minimum score possible as opponent of current player
     * Cut off with a and b when possible
     */
    int old_board[100];
    int flips[20];
    if (ply == 0 || test_end(board, unplayed) == 1)
        return evaluate_board(board, side, unplayed);
    copy_board(board, old_board);
    for (int i=11; i<89; ++i) {
        if (legal_move(board, i, side, flips) == 0)
            continue;
        make_move(board, i, side, flips);
        b = MIN(b, ab_maximize(board, -side, 0, ply-1, a, b));
        copy_board(old_board, board);
        if (b <= a)
            break;
    }
    return b;
}
Ejemplo n.º 8
0
int ab_maximize(int *board, int side, int unplayed, int ply, int a,int b) {
    /* Search to depth ply with mutual recursion
     * Return maximum score possible for current side
     * Cuts off search using a and b parameters if possible
     */
    int old_board[100];
    int flips[20];
    if (ply == 0 || test_end(board, unplayed) == 1)
        return evaluate_board(board, side, unplayed);
    copy_board(board, old_board);
    for (int i=11; i<89; ++i) {
        if (legal_move(board, i, side, flips) == 0)
            continue;
        make_move(board, i, side, flips);
        a = MAX(a, ab_minimize(board, -side, 0, ply-1, a, b));
        copy_board(old_board, board);
        if (b <= a)
            // that's a cutoff, no point further pursuing this position
            break;
    }
    return a;
}
Ejemplo n.º 9
0
// main difference between get_move and maximize is that this one 
// returns a move, not a score
int get_minimax_move(int *board, int side, int unplayed, int ply) {
    /* Similar to maximize(), but return move instead of score
     */
    int score;
    int best_move = 0;
    int flips[20];
    int old_board[100];
    int best_score = MIN_SCORE-2;
    copy_board(board, old_board);
    for (int i=11; i<89; ++i) {
        if (legal_move(board, i, side, flips) == 0)
            continue;
        make_move(board, i, side, flips);
        score = minimize(board, -side, unplayed, ply);
        copy_board(old_board, board);
        if (score > best_score) {
            best_score = score;
            best_move = i;
        }
    }
    return best_move;
}
Ejemplo n.º 10
0
int get_alphabeta_move(int *board, int side, int unplayed, int ply) {
    /* Return best move using alphabeta search to ply depth
     * Similar to ab_maximize, but finds move instead of score
     */
    int score;
    int best_move = 0;
    int flips[20];
    int old_board[100];
    int best_score = MIN_SCORE-1;
    copy_board(board, old_board);
    for (int i=11; i<89; ++i) {
        if (legal_move(board, i, side, flips) == 0)
            continue;
        make_move(board, i, side, flips);
        score = ab_minimize(board, -side, unplayed, ply,
                best_score,MAX_SCORE+1);
        copy_board(old_board, board);
        if (score > best_score) {
            best_score = score;
            best_move = i;
        }
    }
    return best_move;
}
Ejemplo n.º 11
0
// Blasphemous! maximize instead of maximise?!
int maximize(int *board, int side, int unplayed, int ply) {
    /* The max portion of minimax
     * Return maximum score available from position
     * Used with currently playing side's turn
     * Search with mutual recursion to depth ply 
     */
    int old_board[100];
    int flips[20];
    int score = MIN_SCORE;
    if (ply == 0 || test_end(board, unplayed) == 1)
        // either reached end of search or game is over, so return
        return evaluate_board(board, side, unplayed);
    // backup the current playing board
    copy_board(board, old_board);
    for (int i=11; i<89; ++i) {
        if (legal_move(board, i, side, flips) == 0)
            continue;
        make_move(board, i, side, flips);
        score = MAX(score, minimize(board, -side, 0, ply-1));
        // reset the board after computing the score
        copy_board(old_board, board);
    }
    return score;
}
Ejemplo n.º 12
0
/*-
 * Add a randomly chosen tile to a given vertex.  This requires more checking
 * as we must make sure the new tile conforms to the vertex rules at every
 * vertex it touches. */
static void
add_random_tile(fringe_node_c * vertex, ModeInfo * mi)
{
	fringe_node_c *right, *left, *far;
	int         i, j, n, n_hits, n_good;
	unsigned    side, fc, no_good, s;
	vertex_type_c vtypes[MAX_COMPL];
	rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
	tiling_c   *tp = &tilings[MI_SCREEN(mi)];

	if (MI_NPIXELS(mi) > 2) {
		tp->thick_color = NRAND(MI_NPIXELS(mi));
		/* Insure good contrast */
		tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color +
				  MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi);
	} else {
		unsigned long temp = tp->thick_color;

		tp->thick_color = tp->thin_color;
		tp->thin_color = temp;
	}
	n_hits = match_rules(vertex, hits, False);
	side = NRAND(2) ? S_LEFT : S_RIGHT;
	n = find_completions(vertex, hits, n_hits, side, vtypes /*, False */ );
	/* One answer would mean a forced tile. */
	if (n <= 0) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
			(void) fprintf(stderr, "n = %d\n", n);
		}
	}
	no_good = 0;
	n_good = n;
	for (i = 0; i < n; i++) {
		fc = fringe_changes(mi, vertex, side, vtypes[i], &right, &far, &left);
		if (fc & FC_BAG) {
			tp->done = True;
			if (MI_IS_VERBOSE(mi)) {
				(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
				(void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG);
			}
		}
		if (right) {
			s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_LEFT)) ? S_RIGHT : S_LEFT);
			if (!legal_move(right, s, VT_RIGHT(vtypes[i]))) {
				no_good |= (1 << i);
				n_good--;
				continue;
			}
		}
		if (left) {
			s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_RIGHT)) ? S_LEFT : S_RIGHT);
			if (!legal_move(left, s, VT_LEFT(vtypes[i]))) {
				no_good |= (1 << i);
				n_good--;
				continue;
			}
		}
		if (far) {
			s = ((fc & FC_CUT_LEFT) ? S_RIGHT : S_LEFT);
			if (!legal_move(far, s, VT_FAR(vtypes[i]))) {
				no_good |= (1 << i);
				n_good--;
			}
		}
	}
	if (n_good <= 0) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
			(void) fprintf(stderr, "n_good = %d\n", n_good);
		}
	}
	n = NRAND(n_good);
	for (i = j = 0; i <= n; i++, j++)
		while (no_good & (1 << j))
			j++;

	if (!add_tile(mi, vertex, side, vtypes[j - 1])) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
		}
		free_penrose(tp);
	}
}