Ejemplo n.º 1
0
/* ディスクの設置をする関数 */
int place_disk(const int side, const XY sq)
{
    int n = 0, i;
    
    // パスのとき
    if (sq.x == PASSMOVE.x || sq.y == PASSMOVE.y)
        return 0;
    
    assert(is_legal_move(side, sq));
    
    for (i = 0; i < 8; i++)
    {
        const XY dir = directions[i];
        
        if (!can_flip(side, sq, dir))// この方向にはひっくり返せないとき
            continue;
        
        int x = sq.x + dir.x;
        int y = sq.y + dir.y;
        
        // ある方向のディスクをひっくり返す
        while (board[x][y] == -side)
        {
            board[x][y] = side;
            n++;
            x += dir.x;
            y += dir.y;
        }
    }
    board[sq.x][sq.y] = side;   // 最後に端をひっくり返す
    assert(n > 0);
    
    return n;
}
Ejemplo n.º 2
0
// moves must contain at least b->len elements
index_t gen_moves(const board_t *b, stone_t color, index_t *moves, bool ko_rule)
{
    index_t cnt = 0;
    for (index_t i = 0; i < b->empty_ptr; i++) {
        if (is_legal_move(b, b->list[i], color, ko_rule)) {
            moves[cnt++] = b->list[i];
        }
    }
    return cnt;
}
Ejemplo n.º 3
0
int main(int argc, char **argv)
{
  srand((unsigned) time(NULL));
  int board[8][8];//グローバル変数ではなく、いちいち渡すことに
  const int random_side = (argc >= 2) ? atoi(argv[1]) : 0;//MANの先攻後攻の決定
  init_board(board);

  int turn;
  int pass=0;
  for (turn = 1;; turn *= -1) {//先手の時はturn=1,後手の時はturn=-1
    print_board(board);
    Pair legal_moves[60];//合法手を全て収納するための配列
    const int nmoves = generate_all_legal_moves(turn, legal_moves,board);//空きマス0能時にnamoves=-1を返す ←一回目のここで既に何かミスってる
    if (nmoves == -1) break;     // no empty square→ゲーム終了
    if (nmoves ==  0) {
      pass++;
      printf("turn = %d, move = Pass\n", turn);//パスの処理
      if(pass>=2){
	break;
      }
      continue;  
    }else{//passの初期化
      pass=0;
    }

    Pair move;
    if (turn == random_side) {//人間側の操作のとき。com同士ならこれはおこらない
      move = legal_moves[rand()%nmoves];  //ランダム選択
      assert(is_legal_move(turn,move,board));
    } else {//COM側の操作
      move = goodmove(turn,board);//turnは少なくとも必要
      assert(is_legal_move(turn,move,board));//念のため。最適解がちゃんとlegalmoveか確認
    }
    place_disk(turn, move,board);//moveをそもそも受け取れていなかった
    printf("turn = %d, move = %c%c\n", turn, 'a' + move.x, '1' + move.y);
  }//breakするまでfor文は繰り返す
  judge(random,board);//先攻か後攻かを返す
  return 0;
}
Ejemplo n.º 4
0
// iterater interface to gen_moves
// set ptr to b->list in first function call
// set ptr to NULL in the end
index_t gen_moves_next(board_t *b, stone_t color, index_t &offset, bool ko_rule)
{

    index_t* ptr = b->list+offset;
    while (ptr < b->list + b->empty_ptr) {
        if (is_legal_move(b, *ptr, color, ko_rule)) {
            offset++;
            return *ptr;
        }
        ptr++;
        offset++;
    }
    return -1;
}
Ejemplo n.º 5
0
int main()
{
    initialize();
    int tests = 1000;
    int passed = 0;
    fast_srandom(time(0));
    for (int i = 0; i < tests; i++) {
        board_t *b = new board_t;
        int size = fast_random(max_size - 4) + 5;
        empty_board(b, size);
        int steps = 0;
        bool failed = false;
        while (true) {
            stone_t color = steps % 2 == 0 ? STONE_BLACK : STONE_WHITE;
            index_t pos = gen_move(b, color);
            if (pos < 0)
                break;
            if (!is_legal_move(b, pos, color)) {
                failed = true;
                break;
            }
            if (pos >= 0) {
                put_stone(b, pos, color);
                if (!check_board(b)) {
                    failed = true;
                    break;
                }
            }
            steps++;
        }
        delete b;
        if (failed) {
            printf("[F]");
        } else {
            printf("[%d]", steps);
            passed++;
        }
    }
    printf("\n");
    printf("Passed %d out of %d random tests\n", passed, tests);

    return passed == tests ? 0 : 1;
}
Ejemplo n.º 6
0
/* 合法手を作る関数 */
int generate_moves(const int side, XY *moves)
{
    int nmoves = 0;
    int x, y;
    
    for (x = 0; x < 8; x++)
    {
        for (y = 0; y < 8; y++)
        {
            XY tmp = {x, y};    // 検査用
            
            if (!is_legal_move(side, tmp)) // 合法手でないなら次へ
                continue;
            
            assert(nmoves < 60);
            moves[nmoves++] = tmp;     // 合法手の代入
        }
    }
    
    return nmoves;
}
Ejemplo n.º 7
0
/* Perform checks on a move's legality and return TRUE if the move is made.  */
int make_move (int player, int start_pos, int end_pos) 
{
    if (valid_start_pos (player, start_pos) == FALSE) {
        return FALSE;
    }
    if (valid_end_pos (end_pos) == FALSE) {
        return FALSE;
    }
    if (is_legal_move (player, start_pos, end_pos) == FALSE) {
        return FALSE;
    }

    move_piece (start_pos, end_pos);
    if (player_in_check (opponent_player (player)) == TRUE) {
        printf ("Move places opponent in check!\n");
    }

    if (player_has_moves (opponent_player (player)) == FALSE) {
        checkmate = TRUE;
    }

    return TRUE;
}
Ejemplo n.º 8
0
Archivo: move.c Proyecto: cxd4/chess
int enum_moves(move_storage ** list_address)
{
    move_storage * list;
    void * new_address;
    int x1, y1, x2, y2;
    register int legal_moves;

    if (list_address == NULL)
        return (legal_moves = 0);
    list = *(list_address);
    if (list == NULL)
        list = (move_storage *)malloc(0);

    legal_moves = 0;
    for (y1 = 0; y1 < BOARD_SIZE; y1++)
        for (x1 = 0; x1 < BOARD_SIZE; x1++)
            for (y2 = 0; y2 < BOARD_SIZE; y2++)
                for (x2 = 0; x2 < BOARD_SIZE; x2++)
                    if (is_legal_move(x1, y1, x2, y2)) {
                        new_address = realloc(
                            list,
                            ++legal_moves * sizeof(move_storage)
                        );
                        assert(new_address != NULL);
                        list = (move_storage *)new_address;

                        list[legal_moves - 1].origin.file = x1;
                        list[legal_moves - 1].origin.rank = y1;
                        list[legal_moves - 1].target.file = x2;
                        list[legal_moves - 1].target.rank = y2;
                    }

    assert(list != NULL);
    assert(legal_moves >= 0);
    *(list_address) = list;
    return (legal_moves);
}
Ejemplo n.º 9
0
/* 人間の入力を管理する関数 */
void man_player(const int side, XY *move)
{
    XY moves[MOVENUM];
    char buf[1000];
    
    // 手がなければパス
    if (generate_moves(side, moves) == 0)
    {
        printf("Pass!\n");
		printf("Press Enter!\n");
		fgets(buf, sizeof(buf), stdin);
        *move = PASSMOVE;
        return ;
    }
    
    while (1)
    {
        // 手の入力
        do
		{
            printf("Where? ");
            fgets(buf, sizeof(buf), stdin);
		} while(strlen(buf) < 1
                || buf[0] < 'a' || buf[0] > 'h'
                || buf[1] < '1' || buf[1] > '8');
        
        move->x = buf[0] - 'a';
        move->y = buf[1] - '1';
        
        
        // 合法手かどうかの判定
        if (is_legal_move(side, *move))
            break;
        else
            printf("Illeagal Move\n\n");
    }
}
Ejemplo n.º 10
0
// Unified alpha-beta and quiescence search
int abq(board *b, int alpha, int beta, int ply, int centiply_extension, bool allow_extensions, bool side_to_move_in_check) {
	if (search_terminate_requested) return 0; // Check for search termination

	int alpha_orig = alpha; // For use in later TT storage

	// Retrieve the value from the transposition table, if appropriate
	evaluation stored;
	tt_get(b, &stored);
	if (!e_eq(stored, no_eval) && stored.depth >= ply && use_ttable) {
		if (stored.type == qexact || stored.type == exact) return stored.score;
		if (stored.type == qlowerbound || stored.type == lowerbound) alpha = max(alpha, stored.score);
		else if (stored.type == qupperbound || stored.type == upperbound) beta = min(beta, stored.score);
		if (alpha >= beta) return stored.score;
	}

	// Futility pruning: enter quiescence early if the node is futile
	if (use_futility_pruning && !side_to_move_in_check && ply == 1) {
		if (relative_evaluation(b) + frontier_futility_margin < alpha) ply = 0;
	} else if (use_futility_pruning && !side_to_move_in_check && ply == 2) {
		if (relative_evaluation(b) + prefrontier_futility_margin < alpha) ply = 0;
	}

	bool quiescence = (ply <= 0);

	// Generate all possible moves for the quiscence search or normal search, and compute the
	// static evaluation if applicable.
	move *moves = NULL;
	int num_available_moves = 0;
	if (quiescence) moves = board_moves(b, &num_available_moves, true); // Generate only captures
	else moves = board_moves(b, &num_available_moves, false); // Generate all moves
	if (quiescence && !use_qsearch) {
		free(moves);
		return relative_evaluation(b); // If qsearch is turned off
	}

	// Abort if the quiescence search is too deep (currently 45 plies)
	if (ply < -quiesce_ply_cutoff) { 
		sstats.qnode_aborts++;
		free(moves);
		return relative_evaluation(b);
	}

	int quiescence_stand_pat;
	// Allow the quiescence search to generate cutoffs
	if (quiescence) {
		quiescence_stand_pat = relative_evaluation(b);
		alpha = max(alpha, quiescence_stand_pat);
		if (alpha >= beta) {
			free(moves);
			return quiescence_stand_pat;
		}
	} else if (!e_eq(stored, no_eval) && use_tt_move_hueristic) {
		assert(is_legal_move(b, stored.best)); // TODO
		// For non-quiescence search, use the TT entry as a hueristic
		moves[num_available_moves] = stored.best;
		num_available_moves++;
	}

	// Update search stats
	if (quiescence) sstats.qnodes_searched++;
	else sstats.nodes_searched++;

	// Search hueristic: sort exchanges using MVV-LVA
	if (quiescence && mvvlva) nlopt_qsort_r(moves, num_available_moves, sizeof(move), b, &capture_move_comparator);

	// Search extensions
	bool no_more_extensions = false;

	// Extend the search if we are in check
	//coord king_loc = b->black_to_move ? b->black_king : b->white_king;
	bool currently_in_check = side_to_move_in_check; //in_check(b, king_loc.col, king_loc.row, b->black_to_move);
	if (check_extend && currently_in_check && ply <= check_extend_threshold && !quiescence && allow_extensions) { // only extend in shallow non-quiescence situations 
		centiply_extension += check_extension_centiply;
		no_more_extensions = true;
	}

	// Process any extensions
	if (allow_extensions && centiply_extension >= 100) {
		centiply_extension -= 100;
		ply += 1;
	} else if (allow_extensions && centiply_extension <= -100) {
		centiply_extension += 100;
		ply -= 1;
	}

	if (no_more_extensions) allow_extensions = false; // Only allow one check extension

	move best_move_yet = no_move;
	int best_score_yet = NEG_INFINITY; 
	int num_moves_actually_examined = 0; // We might end up in checkmate
	//for (int iterations = 0; iterations < 2; iterations++) { // ABDADA iterations
		for (int i = num_available_moves - 1; i >= 0; i--) { // Iterate backwards to match MVV-LVA sort order
			/*int claimed_node_id = -1;
			if (i != num_available_moves - 1 && iterations == 1) { // Skip redundant young brothers on the first pass
				if (!tt_try_to_claim_node(b, &claimed_node_id)) continue; // Skip the node if it is already being searched
			} else tt_always_claim_node(b, &claimed_node_id);*/
			apply(b, moves[i]);
			bool we_moved_into_check;
			// Choose the more efficient version if possible
			// If we were already in check, we need to do the expensive search
			if (side_to_move_in_check) {
				coord king_loc = b->black_to_move ? b->white_king : b->black_king; // for side that just moved
				we_moved_into_check = in_check(b, king_loc.col, king_loc.row, !(b->black_to_move));
			} else we_moved_into_check = puts_in_check(b, moves[i], !b->black_to_move);
			// Never move into check
			if (we_moved_into_check) {
				unapply(b, moves[i]);
				//tt_unclaim_node(claimed_node_id);
				continue;
			}
			bool opponent_in_check = puts_in_check(b, moves[i], b->black_to_move);
			/*coord opp_king_loc = b->black_to_move ? b->black_king : b->white_king;
			bool opponent_in_check = in_check(b, opp_king_loc.col, opp_king_loc.row, (b->black_to_move));*/
			int score = -abq(b, -beta, -alpha, ply - 1, centiply_extension, allow_extensions, opponent_in_check);
			num_moves_actually_examined++;
			unapply(b, moves[i]);
			if (score > best_score_yet) {
				best_score_yet = score;
				best_move_yet = moves[i];
			}
			alpha = max(alpha, best_score_yet);
			if (alpha >= beta) {
				//tt_unclaim_node(claimed_node_id);
				break;
			}
			//tt_unclaim_node(claimed_node_id);
		}
	//}
	free(moves); // We are done with the array

	// We have no available moves (or captures) that don't leave us in check
	// This means checkmate or stalemate in normal search
	// It might mean no captures are available in quiescence search
	if (num_moves_actually_examined == 0) {
		if (quiescence) return quiescence_stand_pat; // TODO: qsearch doesn't understand stalemate or checkmate
		// This seems paradoxical, but the +1 is necessary so we pick some move in case of checkmate
		if (currently_in_check) return NEG_INFINITY + 1; // checkmate
		else return 0; // stalemate
	}

	if (quiescence && best_score_yet < quiescence_stand_pat) return quiescence_stand_pat; // TODO experimental stand pat

	if (search_terminate_requested) return 0; // Search termination preempts tt_put

	// Record the selected move in the transposition table
	evaltype type;
	if (best_score_yet <= alpha_orig) type = (quiescence) ? qupperbound : upperbound;
	else if (best_score_yet >= beta) type = (quiescence) ? qlowerbound : lowerbound;
	else type = (quiescence) ? qexact : exact;
	evaluation eval = {.best = best_move_yet, .score = best_score_yet, .type = type, .depth = ply};
	tt_put(b, eval);
	return best_score_yet;
}