Quote:
Original post by alvaro Quote:
Original post by kluster
Yes you are right about the position/move thing, but in gomoku they are almost the same.
I don't think so. "Place a black stone on E6" is a move, not a position. A position is the whole configuration on the board. Looking at your code, it looks like you are making many copies of the board when you generate children. Instead, you could just generate the moves, and then you can just do and undo each move on the existing board, without any copies. This saves a lot of time and is not too hard to implement.Quote:
Now Im calculation the Zobrist keys when Im generation the child-moves by XOR'ing the last
value with the new position.
I guess you mean "with the new move".Quote:
Unfortunately, the TT-AI still playes different comparing to the AI without a TT. But the TT-part seems ok? that makes it even more confusing. Im pretty sure that the TT implementation works and all that stuff.
It looks reasonable to me. You may still have a bug somewhere that I haven't seen (or is in a part of the code that you haven't posted).
Even if you get rid of all the bugs, you shouldn't expect the program with the transposition table to play the exact same moves as the program without it. Transposition tables introduce a well-known nightmare called "search instability", which makes search results less reproducible and your program harder to understand in general. Well, this is true at least for chess and checkers; I haven't thought carefully about how this would affect a gomoku program.
You can (should) store the best move from this position in the transposition table, so even if later on you can't use the score you stored, you can still search that move first, which will improve your move ordering and therefore the efficiency of your alpha-beta search.
In general, you should pay attention to move ordering. It is not obvious from looking at your code if you have made any efforts in that direction.
I have made some drastic changes, and now the AI can't play at all.
I implemented negamax to make/undo moves instead of copy the whole board and
apply the new move the it. Perhaps I did't understand what you ment, can you spot
any errors directly by looking at this part of the code?
[SOURCE]int negamax(Position* pos, Move* bestMove, char player, int depth, int alpha, int beta) { /* pos->value was generated for the other player, reversing the value. */ if (depth == 0 || pos->value == MAXSCORE) { return -pos->value; } /* generate possible moves and evaluate them */ vector<Move*> *childs = getChilds(pos, player); if (childs->empty()) { return 0; } for (unsigned int i = 0; i < childs->size(); i++) { int x = childs->at(i)->x; int y = childs->at(i)->y; int val = pos->value; /* update value and set a new move */ pos->makeMove(childs->at(i)); int value = -negamax(pos, bestMove, player == RING ? CROSS: RING, depth-1, -beta, -alpha); /* reset the value of the move to val, and make the position x,y free */ pos->undoMove(val, x, y); if(value > alpha) { if(value >= beta) { bestMove->setInfo(x, y, pos->value, size); return beta; } bestMove->setInfo(x, y, pos->value, size); alpha = value; } } return alpha;}[/SOURCE]