Problems using vectors for a negamax algorithm c++ -
ok, first time asking own question on stack overflow, hope in right place, here goes:
i trying write program can total solve of game abalone - @ least in theory, if there isn't computational power it. using vectors hold board positions, , use max_size indicate length of longest diagonal on board. code appears work correctly board sides length 2 (meaning max_size of 3), returning -2 player 1 win, 0 draw, , 2 player 2 win, throws error when try increase max_size.
i think problem occurring in legality_check() function, can't figure out where. appreciated! include entirety of code can compile , run (hope that's ok), tell think problem is.
#include <vector> #include <iostream> #include <future> #include <map> #include <string> const int max_depth = 100; const int max_size = 3; const int winning_score = 2; std::vector<std::vector<int>> starting_vector(max_size, std::vector<int>(max_size)); std::map<std::vector<std::vector<int>>, std::vector<int>> positions_checked; //checks legality of specified move , performs move if legal std::vector<std::vector<int>> legality_check(std::vector<std::vector<int>> initial_pos, int posr, int posc, int direction) { std::vector<std::vector<int>> new_pos(initial_pos); int start_posr = posr; int start_posc = posc; //weight keeps track of weight of 2 players separately , adds them @ end //the result of addition (mod 10) gives function result should return int weight[2] = {0, 0}; //keeps track of when color of marbles changes opponents bool player_changed = false; //the color of marble in starting position int color; //how program have row , column increment each iteration. int row_move; int column_move; int score = 0; int buffer = 0; if (posc >= max_size) { buffer = posc - max_size + 1; } else { buffer = 0; } bool out_of_bounds = false; //not ((posr>buffer , posc>=0) , (posr<(signed)initial_pos.size() , posc<(signed)initial_pos[posr].size())); //calculates row_move , column_move. follow below pattern: //direction 0: [posr][posc+1] each time //direction 1: [posr-1][posc] each time //direction 2: [posr-1][posc-1] each time //direction 3: [posr][posc-1] each time //direction 4: [posr+1][posc] each time //direction 5: [posr+1][posc+1] each time switch (direction) { case 0: { row_move = 0; column_move = 1; break; } case 1: { row_move = -1; column_move = 0; break; } case 2: { row_move = -1; column_move = -1; break; } case 3: { row_move = 0; column_move = -1; break; } case 4: { row_move = 1; column_move = 0; break; } case 5: { row_move = 1; column_move = 1; break; } //if not 1 of above directions, bad function call , illegal move default: return initial_pos; } //stores color of starting position marble color = initial_pos[posr][posc]; if (color == 0) { return initial_pos; } //while not out of bounds of board or not on empty square while (not out_of_bounds , initial_pos[posr][posc] != 0) { //if current position's marble not same color, marbles of other player if (initial_pos[posr][posc] != color) { player_changed = true; } //if 2 marble colors have been checked, , see original color again, illegal move if (player_changed) { if (initial_pos[posr][posc] == color) { return initial_pos; } //otherwise, add marble's weight player total weight[1] = (weight[1] + initial_pos[posr][posc]) % (max_size + 1); } else { //add marble's weight player total weight[0] = (weight[0] + initial_pos[posr][posc]) % (max_size + 1); } posr += row_move; posc += column_move; if (posc >= max_size) { buffer = posc - max_size + 1; } else { buffer = 0; } out_of_bounds = not ((posr > buffer , posc >= 0) , (posr < (signed)initial_pos.size() , posc < (signed)initial_pos[posr].size())); } if (out_of_bounds) { score = 1; posr -= row_move; posc -= column_move; } weight[0] = weight[0] / color; //the formula (color*max_size)%(max_size+1) switches value of color opposing players values due how //chose numbers represent each color (1 1 player, max_size other player) weight[1] = weight[1] / ((color * max_size) % (max_size + 1)); int final_weight = weight[0] - weight[1]; if (weight[0] <= 3 , final_weight > 0) { while (posr != start_posr , posc != start_posc) { new_pos[posr][posc] = new_pos[posr - row_move][posc - column_move]; posr -= row_move; posc -= column_move; } new_pos[start_posr][start_posc] = 0; if (positions_checked.count(new_pos) == 0) { positions_checked[new_pos] = std::vector<int>(3, 0); } if (color == 1) { //positions_checked[new_pos][0]+=score+positions_checked[initial_pos][0]; ??? positions_checked[new_pos][0] += score; } else { //positions_checked[new_pos][1]+=score+positions_checked[initial_pos][1]; ??? positions_checked[new_pos][1] += score; } return new_pos; } else { return initial_pos; } } int negamax(std::vector<std::vector<int>> initial_pos, int depth, int color, bool prev_move) { int best_value=-10000; int value; int score=0; int buffer=0; bool loop_entered=false; if(color==1) { score=positions_checked[initial_pos][1]; } else { score=positions_checked[initial_pos][0]; } //implement position repetition check later if(depth==0 or score>=winning_score) { return -score; } else { for(int column=0; column < (signed)initial_pos.size(); ++column) { if(column>=max_size) { buffer=column-max_size+1; } else { buffer=0; } for(int row = buffer; row < (signed)initial_pos[column].size(); ++row) { if(initial_pos[column][row]==color) { bool found_legal_move=false; for(int direction=0; direction!=6; direction++) { std::vector<std::vector<int>> new_pos = legality_check(initial_pos, column, row, direction); if(max_size==3) { new_pos[0][max_size+2]=(color*max_size)%(max_size+1); } else { new_pos[0][max_size]=(color*max_size)%(max_size+1); } if(new_pos != initial_pos && positions_checked[new_pos][2]==0) { found_legal_move=true; positions_checked[new_pos][2]=1; value = negamax(new_pos, depth-1, (color*max_size)%(max_size+1),true); //color 1: score 2. return 2. color 2 receives 2. becomes -2. //color1: score -1. return -1. color 2 receives -1. becomes 1. returns 1. //color1 receives 1. becomes -1.; //color1 receives -1. becomes 1. best_value = std::max(best_value, value); } } if((not found_legal_move) , prev_move) { value = negamax(initial_pos, depth-1, (color*max_size)%(max_size+1), false); best_value = std::max(best_value, value); } else if((not found_legal_move) , (not prev_move)) { return 0; //stalemate, neither player has legal move, draw } loop_entered=true; } } } if(loop_entered==false) { //if color has no marbles, opponent has won return winning_score; } } return best_value*-1; } int main() { starting_vector[(max_size-1)/2].resize(max_size); starting_vector[0].resize(max_size); starting_vector[0][0] = 1; starting_vector[0][1] = 1; starting_vector[1][0] = 1; starting_vector[1][1] = 1; starting_vector[1][2] = 0; starting_vector[2][0] = max_size; starting_vector[2][1] = max_size; starting_vector[0][max_size+2]=1; positions_checked[starting_vector] = std::vector<int>(3,0); std::cout << starting_vector.size() << " " << starting_vector[0].size() << std::endl; std::cout<<starting_vector[0][0] << " " << starting_vector[0][1] << " " << starting_vector[1][0] << " " << starting_vector[1][1] << " " << starting_vector[1][2] << " " << starting_vector[2][0] << " " << starting_vector[2][1] << std::endl; std::vector<std::vector<int>> new_vector(legality_check(starting_vector, 0, 0, 1)); std::cout<<new_vector[0][0] << " " << new_vector[0][1] << " " << new_vector[1][0] << " " << new_vector[1][1] << " " << new_vector[1][2] << " " << new_vector[2][0] << " " << new_vector[2][1] << std::endl; std::cout<<starting_vector[0][0] << " " << starting_vector[0][1] << " " << starting_vector[1][0] << " " << starting_vector[1][1] << " " << starting_vector[1][2] << " " << starting_vector[2][0] << " " << starting_vector[2][1] << std::endl; std::cout<<new_vector[0][2] << std::endl; std::cout<<negamax(starting_vector, max_depth, 1,true)<< " returned successfully" << std::endl; return 0; } ok, that's lot of code, here's what's happening. run code , gives me "* error in './abalone.exe':free(): invalid next size (fast): 0x0000000001c8f0b0 *" aborted (core dumped). error, , might wrong on this, seems occurring after last cout returns - line before return in int main(), doesn't make sense, since program outputs 6 lines, , have 6 couts. confusing me, since code after last cout return.
also, wasn't segmentation fault, had gotten code mixed other code working on, sorry that.
i did backtrace gdb , got after program threw exception:
*** error in '/abalone.exe': free(): invalid next size (fast): 0x000000000060b0b0 *** program received signal sigabrt, aborted. 0x00007ffff7313cc9 in __gi_raise (sig=sig@entry=6) @ ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 ../nptl/sysdeps/unix/sysv/linux/raise.c: no such file or directory. (gdb) bt #0 0x00007ffff7313cc9 in __gi_raise (sig=sig@entry=6) @ ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007ffff73170d8 in __gi_abort () @ abort.c:89 #2 0x00007ffff7350394 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff745eb28 "*** error in `%s': %s: 0x%s ***\n") @ ../sysdeps/posix/libc_fatal.c:175 #3 0x00007ffff735c66e in malloc_printerr (ptr=<optimized out>, str=0x7ffff745ecc8 "free(): invalid next size (fast)", action=1) @ malloc.c:4996 #4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) @ malloc.c:3840 #5 0x000000000040457c in __gnu_cxx::new_allocator<int>::deallocate(int*, unsign ed long) () #6 0x0000000000403694 in std::_vector_base<int, std::allocator<int> >::_m_deall ocate(int*, unsigned long) () #7 0x0000000000402b25 in std::_vector_base<int, std::allocator<int> >::~_vector _base() () #8 0x00000000004023f9 in std::vector<int, std::allocator<int> >::~vector() () #9 0x0000000000405191 in void std::_destroy<std::vector<int, std::allocator<int > > >(std::vector<int, std::allocator<int> >*) () #10 0x00000000004047cf in void std::_destroy_aux<false>::__destroy<std::vector<i nt, std::allocator<int> >*>(std::vector<int, std::allocator<int> >*, std::vector <int, std::allocator<int> >*) () #11 0x00000000004039a0 in void std::_destroy<std::vector<int, std::allocator<int ---type <return> continue, or q <return> quit--- is there more information need give guys me?
ok, using method lux32 , vsoftco recommended me let me figure out error occurring , how fix it. line in int main() starting_vector[0][max_size+2]=1; trying set value out of bounds of vector, result in undefined behavior. needed used starting_vector[0].push_back(1). increases size of starting_vector 1 , sets location 1, needed do. thank everybody!
Comments
Post a Comment