0

I am currently working on building a chess AI by using the MINIMAX algorithm. It was pretty good initially without the threadings but it was only going as deep as 5 ply at max, So in order to increase the depth I used multithreading but it is falling into an inifinite loop, Can someone help to make it work ?

The code :

void* best_move(void *_args){

    struct forThread *args = (struct forThread *) _args;

    for(int i=0; i<8; ++i){
        for(int j=0; j<8; ++j){
            args->res += args->state_score[i][j];
            printf("%c", state[i][j]);
        }
        printf("\n");
    }
    if(args->depth == 5){
        //printf("Return value in the last node = %lld\n", current_score);
        pthread_exit((void*)(args->res));
    }

    // TURN OF THE PLAYER THAT MAXIMIZES THE SCORE :
    int mid[] = {0, 7, 1, 6, 2, 5, 3, 4};
    if(args->depth % 2 == 0){
        //printf("Reached the maximizing player\n");
        int ans = -1e8;
        for(int i=0; i<8; ++i){
            for(int j=0; j<8; ++j){
                if(isUpper(args->state[i][mid[j]]) && args->state_score[i][mid[j]]>0){
                    vector<pair<int, int>> possible_moves = get_moves(i, mid[j], args->state);
                    if(possible_moves.size() == 0) continue;
                    for(auto u : possible_moves){
                        int x = u.first, y = u.second;
                        int removed_points = args->state_score[x][y];
                        char state_copy[8][9];
                        int state_score_copy[8][8];
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) state_score_copy[k][io] = args->state_score[k][io];
                                state_copy[k][io] = args->state[k][io];
                            }
                        }
                        int new_score = args->res - args->state_score[x][y];
                        if(args->depth >= 3 && new_score == args->start_score) continue;

                        state_copy[x][y] = state_copy[i][mid[j]];
                        state_copy[i][mid[j]] = '_';
                        state_score_copy[x][y] = state_score_copy[i][mid[j]];
                        state_score_copy[i][mid[j]] = 0;

                        struct forThread *arg = (forThread*) malloc (sizeof (struct forThread));
                        arg->depth = args->depth + 1;
                        arg->depth = args->start_score;
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) arg->state_score[k][io] = args->state_score[k][io];
                                arg->state[k][io] = args->state[k][io];
                            }
                        }
                        arg->alpha = args->alpha;
                        arg->beta = args->beta;
                        arg->res = -1;

                        pthread_t id;
                        pthread_create(&id, NULL, best_move, arg);
                        void *result = NULL;

                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);

                        pthread_join(id, &result);
                        ans = min(ans, (int)result);
                        args->res = ans;


                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);
                        //printf("%lld\n", res);
                        args->alpha = max(args->alpha, ans);
                        if(args->beta <= args->alpha) break;
                        if(args->depth == 0 && ans == args->res){
                            //printf("got the answer = %d\n", ans);
                            moveX = i;
                            moveY = mid[j];
                            toX = x;
                            toY = y;
                        }
                    }
                }
            }
        }
        pthread_exit((void*)(args->res));
    }


    else{

        int ans = +1e8;
        //printf("Reached the minimizing player\n");
        for(int i=0; i<8; ++i){
            for(int j=0; j<8; ++j){
                if(isLower(args->state[i][mid[j]]) && args->state_score[i][mid[j]]<0){
                    vector<pair<int, int>> possible_moves = get_moves(i, mid[j], args->state);
                    if(possible_moves.size() == 0) continue;
                    for(auto u : possible_moves){
                        int x = u.first, y = u.second;
                        int removed_points = args->state_score[x][y];
                        char state_copy[8][9];
                        int state_score_copy[8][8];
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=9) state_score_copy[k][io] = args->state_score[k][io];
                                state_copy[k][io] = args->state[k][io];
                            }
                        }
                        int new_score = args->res - args->state_score[x][y];
                        if(args->depth >= 3 && new_score == args->start_score) continue;

                        state_copy[x][y] = state_copy[i][mid[j]];
                        state_copy[i][mid[j]] = '_';
                        state_score_copy[x][y] = state_score_copy[i][mid[j]];
                        state_score_copy[i][mid[j]] = 0;

                        struct forThread *arg = (forThread*) malloc (sizeof (struct forThread));
                        arg->depth = args->depth + 1;
                        arg->depth = args->start_score;
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) arg->state_score[k][io] = args->state_score[k][io];
                                arg->state[k][io] = args->state[k][io];
                            }
                        }
                        arg->alpha = args->alpha;
                        arg->beta = args->beta;
                        arg->res = -1;

                        pthread_t id;
                        pthread_create(&id, NULL, best_move, arg);
                        void *result = NULL;
                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);

                        pthread_join(id, &result);
                        ans = min(ans, (int)result);
                        args->res = ans;

                        args->beta = min(ans, args->beta);
                        if(args->beta <= args->alpha) break;
                    }
                }
            }
        }
        pthread_exit((void*)(args->res));
    }

}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    What is the use of `pthread_create(&id, ...)` *directly* followed by `pthread_join(id, ...)`? That is no different than just calling the thread function in a non-threaded way. – Some programmer dude Oct 21 '20 at 06:40
  • 1
    I need to be a bit nitpicky here, sorry. that is pthreads, no c++ thread. there doesn't seem to be a single line of C++ code here. `std::thread` would be the thing you use in C++ – Reinhold Oct 21 '20 at 06:42
  • This is my first time using threads, I found many ways but their were few of them that told how to get the return value, can you suggest some easy way to get the return value from the function ? – Steven Anderson Oct 21 '20 at 06:47
  • 1
    @Reinhold There's a vector, so it's just enough not to be compilable by a C compiler. I hope C++ is not being taught by first teaching C. – stefaanv Oct 21 '20 at 06:54
  • 1
    @StevenAnderson you may want to look into `std::async` https://en.cppreference.com/w/cpp/thread/async And you might also enjoy this more: `auto arg = new forThread()` instead of `struct forThread *arg = (forThread*) malloc (sizeof (struct forThread));` – Reinhold Oct 21 '20 at 08:41
  • @Reinhold I read about them but most people have labelled it as bad so I never really used them. Does **std::async** really work properly ? – Steven Anderson Oct 21 '20 at 13:53
  • I tried using the std::async and std::future but got an error. Please help me rectify it. Link : **https://stackoverflow.com/questions/64465888/why-am-i-getting-error-in-async-future-in-c** – Steven Anderson Oct 21 '20 at 15:48
  • @StevenAnderson Sorry, I don't have the resources currently to look into that more. That's why I wasn't actually trying to provide an answer. – Reinhold Oct 22 '20 at 06:18

1 Answers1

0

This is probably the culprit:

arg->depth = args->depth + 1;
arg->depth = args->start_score;

You want to change depth to start_score in the second line twice in the code.

You also have to free() the allocated args or use a more C++ style memory management because your program now has memory leaks.

stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • 1
    @StevenAnderson Did you already verified whether this was the problem or whether there were also other issues? – stefaanv Oct 21 '20 at 14:45
  • there were some other issues so I tries using std::async function but still got the error. Link : **https://stackoverflow.com/questions/64465888/why-am-i-getting-error-in-async-future-in-c** – Steven Anderson Oct 21 '20 at 15:50