I have built an AI to play the Mancala game. I have implemented a minimax search however it always loses when it starts 2nd against a local greedy AI. The minimax is only able to beat the local greedy player when minimax starts first. Is there an explanation to this or is there a way to be able to beat the local greedy AI with some generic algorithm?
Related
I am making an AI application where I found about minimax and Alpha-beta pruning. I found that in the program I already used the concept of minimax.
I found that Alpha-beta pruning reduces branches to search for.
So my question is what type of tree should I need to apply the algorithm.
In research, I always found binary tree. (Where each node has exactly two children)
But in my application, each node can generate 1 to 30 child nodes.
So should I use alpha-beta pruning on it? Or it isn't possible.
Is there any other algorithm to reduce branches as Alpha-beta pruning does?
You can certainly use Alpha-beta pruning on a tree where nodes have more than two children. In fact, you can see it in the first image for the English Wikipedia article about Alpha-beta pruning. Alpha-beta pruning is introduced as an optimisation of minimax, which is often used in board game AIs, where more than two choices are available to the player (think of chess, draughts, backgammon, etc.). You should be able to just add Alpha-beta pruning to your current minimax implementation.
I implemented an AI playing checkers (also known as draughts) using the popular Monte Carlo Tree Search.
I was inspired by this resource http://www.bailopan.net/checkers/ that does the same.
Unfortunately my implementation and that implementation have an issue:
While the AIs play very well during early and middle stages of the game they do not handle end-game too well: i found they end up just moving the last pieces around and not trying to win.
I implemented the simulation step making random moves for both players for N turns in the future (ie: it does not simulate the game until the end but for a significant number of turns).
I gave to the AI a large amount of time for its considerations just to be sure that computational time was not the bottleneck.
I'm considering to tweak the simulation step with some domain-based heuristic but i don't know how to develop the evaluate function, if needed.
Under this circumstances, how do you think I can improve my AI to have a better late game?
I have implemented a connect 4 AI to play in a tournament for my class. I have implemented a depth limited minimax with alpha-beta pruning. We are allowed to give one depth to give as an argument for the tournament. My program will make a move, then another student will make a move, and this continues until there is a winner. It is also a modified connect 4 in which the entire 42 spots in the 6×7 game board are filled, and every 4-in-a-row is a point, and the most points wins.
My question is about the alpha-beta pruning. Our moves have to take "about 1 second", so anything under 2 seconds should be fine. Running my program without alpha-beta pruning allows a move about 1.3 seconds or less at depth 6. Depth 7 is unacceptable. Now, with alpha-beta pruning, can I guarantee that I can change my depth to go deeper? I know on average that it will let me go deeper, but I believe on the worst case nothing gets pruned, and I would exceed the time limit. Is this correct?
This IS correct: in the worst-case scenario, alpha-beta is just as slow as minimax.
Bit there is a really small chance for that to happen. To optimise alphabeta and prevent that problem, search "move ordering alpha beta" on google.
If you have to stay inside a time limit, I suggest to use iterative deepening (search with depth 1, 2, ..., x). That should not be a problem due to the exponential explosion. If your program runs out of time, just play the move you figured out with the previous searchdepth.
I have to create an AI which has to compete against other AIs.
Both AIs will run on the same hardware, have the same amount of processing time and memory. I know the opponent AI will be using the minimax algorithm with alpha beta pruning.
Now my question is - what are some approaches for beating such an opponent? If I use minimax myself - then both AI's perfectly predict each other's moves and the game resolves based on an inherent property of the game (first move wins etc).
The obvious solution is to somehow see further ahead into the possible moves which would allow for a better evaluation - since the processor time is the same I couldn't evaluate to a greater depth (assuming the opposing AI code is equally optimized). I could use a precomputed tree for an extra advantage but without a super computer I certainly couldn't "solve" any nontrivial game.
Is there some value in intentionally picking a non optimal node such as one that alpha beta would have pruned? This could potentially incur a CPU time penalty on the opponent as they'd have to go back and re-evaluate the tree. It would incur a penalty on me as well as I'd have to evaluate the minimax tree + alpha beta to see which nodes alpha beta would prune without reaping any direct benefits.
What are some other strategies for optimizing against such an opponent?
First, there isn't any value in choosing a non-optimal line of play. Assuming your opponent will play optimally (and that's a fundamental assumption of minimax search), your opponent will make a move that capitalizes on the mistake. A good game engine will have a hashed refutation table entry containing the countermove for your blunder, so you'll gain no time by making a wild move. Making bad moves allows a computer opponent to find good moves faster.
The key thing to realize with a game like Othello is that you can't be sure what the optimal move is until late in the game. That's because the search tree is almost always too large to be exhaustively searched for all won or lost positions, and so minimax can't tell you with certainty which moves will lead to victory or defeat. You can only heuristically decide where to stop searching, arbitrarily call those nodes "terminal", and then run an evaluation function that guesses the win/loss potential of a position.
The evaluation function's job is to assess the value of a position, typically using static metrics that can be computed without searching the game tree further. Piece counts, positional features, endgame tablebases, and even opponent psychology can play a role here. The more intelligence you put into your evaluation function, generally the better your engine will play. But the point of static evaluation is replace searches that would be too expensive. If your evaluation function does too much or does what it does too inefficiently, it can become slower than the game tree search needed to obtain the same information. Knowing what to put in an evaluation function and when to use static evaluation instead of search is a large part of the art of writing a good game engine.
There are a lot of ways to improve standard minimax with AB pruning. For example, the killer heuristic attempts to improve the order moves are looked at, since AB's efficiency is better with well-ordered moves.
A lot of information on different search enhancements and variations on AB can be found at chessprogramming.wikispaces.com.
There are plenty of Chess AI's around, and evidently some are good enough to beat some of the world's greatest players.
I've heard that many attempts have been made to write successful AI's for the board game Go, but so far nothing has been conceived beyond average amateur level.
Could it be that the task of mathematically calculating the optimal move at any given time in Go is an NP-complete problem?
Chess and Go are both EXPTIME complete. IIRC, Go has more possible moves, so I think it a higher multiple of that complexity class than chess. Wikipedia has a good article on the complexity of Go.
Even if Go is merely in P it could still be something horrendous like O(n^m) where n is the number of spaces and m is some (large) fixed number. Even being in P doesn't make something reasonable to compute.
Neither Chess or Go AIs completely evaluate all possibilities before deciding on a move.
Chess AIs use various heuristics to narrow down the search space, and to quantify how 'good' a given position on the board happens to be. This can be done recursively by evaluating possible board positions 14-15 moves ahead and choosing a path that leads to a good position.
There's a bit of 'magic' in how a board position is quantified so the that at the top level, the AI can simply go Move A > Move B therefore lets do Move A. But since there's a limited number of pieces and they all have quantifiable value a 'good enough' algorithm can be implemented.
But it turns out to be a lot harder for a program to evaluate two possible board positions in Go and make that A > B calculation. Without that critical piece its a little hard to make the rest of the AI work.