I'm developing a simple Connect4 game in Android.
Currently I'm using a minimax algorithm with alpha-beta pruning and bit-board state representation so the search is very effective and fast.
The skill is set by setting the maximum depth the algorithm should reach during its DFS search inside the game tree.
I noticed that the time required to choose a move depends on how far we are in the game: at the beginning it takes more time (as there are many possibilities to explore), in mid-game it take a reasonable amount of time and near the end is very fast.
My problem is that if I set a given skill the user has to wait to much on the first/second/third moves. I'd like to speed-up the aperture but I suspect it depends even on the hardware itself how I want to implement the speed-up process.
Can I set a timeout for the thread running the DSF mimimax?
The simplest way to circumvent this issue is to use an opening book for the first few moves. An opening book is a set of predetermined moves for a given scenario. Since there are relatively few possibly board states for the opening moves, you can easily compile a database of all possibly moves for the first three turns, and call upon it instead of actually doing the search. Thus you no longer require a time out and you sped up the search with zero cost to accuracy.
Related
we are working on a little Java game, based on the game Blokus.
Blokus-Manual
I'm a Java-beginner and plan to implement an advanced artificial intelligence. We already have a random AI (picks a random valid move) and an AI with a simple move-rating mechanism. We also want an AI which should be as good as possible (or at least very good ;) ).
The question is: Which AI-concept would be suitable for our purpose?
The minimax-algorithm seems to be a valid choice, but how do you adapt it to a 4-player-game? Are there better concepts for a game like blokus?
Thanks already :)
Min-max is hard to implement in a 4 player game because:
Decision tree grows exponentially, so you're going to be bounded by memory and/or computation time to a log(medMoves)=N steps. For a 4 player game, this is down to N/4. If N is 8 for example, you're only going to be able to see 2 moves ahead for each player.
Player collusion is hard to account for. In a realistic game, some players might help each other out (even if they're not on the same team). This will cause them to deviate from their personal 'maximum'.
If you want Minmax, you're going to have to do a lot of pruning to make it viable. What I would suggest is learning a few patterns so the AI would know how to react. This can be done via neural net, or reinforcement learning with a few tweaks.
These patterns could be be static (you can create the input scenario manually or programmatically), or dynamic (create all valid scenarios and randomly makes moves select the ones with the best score).
Theoretically speaking, an "as good as possible AI" is a perfect AI, which is an AI that has, at any moment in the game, full knowledge of the game state (if the full game state is not known by human players). In case of games that everyone has full game state knowledge (like Blokus), a good as possible AI is an AI that can try to predict the very best move to make (minimax here, as you said). You can also google for genetic algorithms and simulated annealing, as they are valid, depending on what you want. Also, you can use minimax for more than 2 players.
I would recommend minimax algorithm. One thing you can add to make it more efficient (meaning you should be able go more moves deep into the future) is alpha-beta pruning.
The problem with minimax search is that the number of games states it has to examine is exponential in the depth of the tree. Unfortunately, we can't eliminate the exponent, but it turns out we can effectively cut it in half.
The quote is from Chapter 5.3 of Artificial Intelligence: A Modern Approach third edition by Stuart Russel and Peter Norvig. It was holding up my monitor, and I used it in a few of my classes in college. I know people don't often reference books on SO, but it's extremely relevant. I have used it extensively, and I do really recommend it for both being understandable, and covering a wide range of AI content.
It is available on amazon for $104, or * cough cough * I'm sure you can find it online if you don't have that kind of money for a textbook floating around. Looking up the minimax algorithm and alpha beta pruning online should also get you good results.
I think the only circumstance that would make Minimax a poor option for you is if the game state is only partially observable to any given player (they don't know everything about what's going on), or if the game is non-deterministic (it has random elements). Because neither of these are the case for Blokus, I think you made an excellent choice with Minimax.
The area of AI is called Adversarial Search in the textbook (Chapter 5: Adversarial Search), so looking up more info online with that term may get you more helpful information, or help you find an example Java implementation. I do not consider this a beginner's task, but it sounds like you are up to it, if you made the game and can pick random valid moves. Keep up the good work!
In 2011, with many updates since then, a program called Pentobi
was released, and it is a very strong Blokus playing program.
The only one known to date, in fact, which is any good at all, and it
surpasses all the others by a great deal. It will beat many good human players and gives even the best a run for their money.
Its main algorithm is Monte Carlo Search Tree, but it also uses a "book" of openings and some heuristics.
There is documentation and download information at
http://pentobi.sourceforge.net/
I found that using a very simple heuristic provides a fairly intelligent player even using only 1-step look ahead. I implemented what I called "space heuristic" which takes the board state and floods it by coloring all squares adjacent to each placed piece the color of that piece. Then, the total number of colored squares is counted once the flooding terminates. The space heuristic gives a rough estimate of how much a play claims or occupies board space, and way outperforms random play. Could be combined with minimax or MCTS to get way stronger as well.
I have been working on a 2D top down shooter game for a while, I've implemented most of the game and wrote the engine from scratch in JOGL but i ran into a small problem and would like to get other peoples view on how to best approach the problem. So I have creeps spawning at random locations in the map, and each of these creeps use A* path finding, it has been optimized to minimize unnecessary checks, but the maps are massive can be anything from 10x10 to 200x200 tiles and the only thing slowing down the game significantly is the AI, I've also tried to implement a distance based solution where the creeps Idle until i am in a certain range but that still slows down the game a lot because a lot of creeps are spawned. Any advice would be appreciated.
There are numbers of ways of speeding up your code.
First - there are many modifications of the A* algorithm, which may be used, like:
Hierarchical A*, which is often used method in games, where the map is analyzed on many resolution levels, from "general planning" to the "local path search" http://aigamedev.com/open/review/near-optimal-hierarchical-pathfinding/
Jump Point Search A*, which dramaticaly speeds up A* for maps with lots of open spaces (like RPG games) http://gamedev.tutsplus.com/tutorials/implementation/speed-up-a-star-pathfinding-with-the-jump-point-search-algorithm/
Other modifications can be more application specific, if your creeps are searching a path to the player (there is one goal for all creeps), then you can change your search to one of following algorithms:
calculate distance from player to each point in the map using Dijkstra algorithm, for 200x200 it will be very quick (40,000 vertices with O(nlgn) algorithm), and simply move your creep to any adjacent point with less distance to player then current one
run A* search from the player to any creep (with lowest id for example), once the path is found - change aim to the next creep but do not reset the algorithm itself, let if use already computed paths and distances (as they are already optimal paths from player), obviously - if during execution you encounter another creep then your goal - you simply record it (found path is optimal).
Another possible modification, which can be applied if your map is somehow specific (contains doors/entrances to some parts of it) is to place triggers, which "enable" creeps AI. This is O(1) solution, but requires a specific type of map.
And one final idea would be to implement some suboptimal solutions, by for example:
First, calculate A* for each creep
If the distance to the player is smaller then some threshold value T, then in next iteration - recalculate your path, so there is no lag
otherwise - follow your path for at least 10-50 iterations before another path search
There are countless more optimizations, but we would need more details regarding your game as well as time you wish to spend on those optimizations.
So basically I coded an A* pathfinder that can find paths through obstacles and move diagnolly. I basically implemented the pseudocode from Link into real code and also used a binary heap method to add and delete items from the openlist.
Using binary heap led to significant performance boost , about 500 times faster than the insert sorting algorithm I used before.
the problem is that it still takes around on average 1.5 million nanoseconds which is around .0015 of a second.
So the question is, my plan is to make a tower defense game where the pathfinding for each mob needs to update everytime I add a tower to the map. If I were to have around a maximum of 50ish mobs on the map, that means it will take around .0015 * 50 = .075 seconds to update all paths for the entire mob. The game basically ticks( all the ingame stuff updates) every 1/60 seconds which is .016 of a second, so the problem is that it takes longer to update the paths than it takes to tick, which will lead to massive lag. So how should I go about this? DO I need to find a better algorithm for sorting the openlist or somehow divide the pathfinding tasks so that each tick only does X number of pathfinding tasks as opposed to all of them.
Rather than searching from each enemy to the checkpoint, search outwards from the checkpoint to every enemy at once. This way, rather than doing 50 searches, you only need to do one.
More specifically, just do a breadth-first search (or djikstra's, if your graph is weighted) from the player outwards, until every enemy has been reached.
You could alter this strategy to work with A* by changing your heuristic EstimatedDistanceToEnd (aka h(x)) to be the minimum estimate to any enemy, but with a lot of enemies this may end up being slower than the simpler option. The heuristic must be consistent for this to work.
Additionally, make sure you are using the correct tie-breaking criteria.
Also, and most importantly, remember that you don't need to run your pathfinder every single frame for most games - often you can get away with only once or twice a second, or even less, depending on the game.
If that is still too slow, you could look into using D* lite to reuse information between subsequent searches. But, I would bet money that running a single breadth-first search will be more than fast enough.
(copied from my answer to a similar question on gamedev)
Have you considered the Floyd-Warshall algorithm?
Essentially, A* is for path-finding from a single source to one or more destinations. However, in tower defense (depending on your rules of course), it is about multiple sources navigating around a map.
So for this, Floyd's algorithm seems more optimal. However, you could have your A* algorithm find paths for unit groups instead of individual units, which should optimize your calculation times.
Presumably, you can back-search from the exit towards all the creeps, so you need to explore your maze only once.
I'm going be competing in a board game AI competition at my school and am trying to come up with some ideas for concurrency to gain an edge. I will most likely be at a disadvantage because I will be implementing it in java and I understand c or c++ would be much faster.
It doesn't seem like you could just split the game tree in half because of the move ordering which should leave the best moves first and it seems that it would be difficult or maybe even impossible to communicate the current alpha/beta at a given depth. I'm going to be using transposition tables as well which would need to be synchronized.
Besides searching, is there something that a second thread could be doing which could aid in the search or provide some type of speed increase. Each AI will have 5 seconds to make a move and your program can be working while the opponent is thinking.
Any input, no matter how obscure, would be appreciated.
An overview can be found in the Chess Programming Wiki's parallel search article. Even if your actual game is not chess, many concepts will also apply. The site also covers sophisticated solutions for shared transposition tables.
However, when you don't have much time, I would not start with a parallel search. You are correct that parallelism can increase the strength of the search algorithm. It is very difficult to get it right, though, and the benefits are way lower than one would expect.
If you want to experiment with parallelism, go ahead. It is an interesting topic. However, if you just want to get the best results in a limited amount of time, I would recommend to stick with a sequential search, and instead focus on move ordering and correctness.
It is possible. You have to make communication between threads to have AB prunning help. Also, move ordering must be tweaked, it doesn't help if one thread has the best-rated moves to analyze while the others not.
This is my first question here, if I did something wrong, tell me...
I'm currently making a draughts game in Java. In fact everything works except the AI.
The AI is at the moment single threaded, using minimax and alpha-beta pruning. This code works, I think, it's just very slow, I can only go 5 deep into my game tree.
I have a function that recieves my mainboard, a depth (starts at 0) and a maxdepth. At this maxdepth it stops, returns the player's value (-1,1 or 0) with the most pieces on the board and ends the recursive call.
If maxdepth isn't reached yet, I calculate all the possible moves, I execute them one by one, storing my changes to the mainboard in someway.
I also use alpha-beta pruning, e.g. when I found a move that can make the player win I don't bother about the next possible moves.
I calculate the next set of moves from that mainboard state recursively. I undo those changes (from point 2) when coming out of the recursive call. I store the values returned by those recursive calls and use minimax on those.
That's the situation, now I have some questions.
I'd like to go deeper into my game tree, thus I have to diminish the time it takes to calculate moves.
Is it normal that the values of the possible moves of the AI (e.g. the moves that the AI can choose between) are always 0? Or will this change if I can go deeper into the recursion? Since at this moment I can only go 5 deep (maxdepth) into my recursion because otherwise it takes way too long.
I don't know if it's usefull, but how I can convert this recursion into a multithreaded recursion. I think this can divide the working time by some value...
Can someone help me with this please?
1. Is it normal that the values of the possible moves of the AI (e.g. the moves that the AI can choose between) are always 0?
Sounds strange to me. If the number of possible moves is 0, then that player can't play his turn. This shouldn't be very common, or have I misunderstood something?
If the value you're referring to represents the "score" of that move, then obviously "always 0" would indicate that all move are equally good, which obviously doesn't make a very good AI algorithm.
2. I don't know if it's usefull, but how I can convert this recursion into a multithreaded recursion. I think this can divide the working time by some value...
I'm sure it would be very useful, especially considering that most machines have several cores these days.
What makes it complicated is your "try a move, record it, undo it, try next move" approach. This indicates that you're working with a mutable data structure, which makes it extremely complicated to paralellize the algorithm.
If I were you, I would let the bord / game state be represented by an immutable data structure. You could then let each recursive call be treated as a separate task, and use a pool of threads to process them. You would get close to maximum utilization of the CPU(s) and at the same time simplify the code considerably (by removing the whole restore-to-previous-state code).
Assuming you do indeed have several cores on your machine, this could potentially allow you to go deeper in the tree.
I would strongly recommend reading this book:
One Jump Ahead: Computer Perfection At Checkers
It will give you a deep history about computer AI in the game of Checkers and will probably given you some help with your evaluation function.
Instead of having an evaluation function that just gives 1/0/-1 for differing pieces, give a score of 100 for every regular piece and 200 for a king. Then give bonuses for piece structures. For instance, if my pieces form a safe structure that can't be captured, then I get a bonus. If my piece is all alone in the middle of the board, then I get a negative bonus. It is this richness of features for piece configurations that will allow your program to play well. The final score is the difference in the evaluation for both players.
Also, you shouldn't stop your search at a uniform depth. A quiescence search extends search until the board is "quiet". In the case of Checkers, this means that there are no forced captures on the board. If you don't do this, your program will play extremely poorly.
As others have suggested, transposition tables will do a great job of reducing the size of your search tree, although the program will run slightly slower. I would also recommend the history heuristic, which is easy to program and will greatly improve the ordering of moves in the tree. (Google history heuristic for more information on this.)
Finally, the representation of your board can make a big difference. Fast implementations of search do not make copies of the board each time a move is applied, instead they try to quickly modify the board to apply and undo moves.
(I assume by draughts you mean what we would call checkers here in the States.)
I'm not sure if I understand your scoring system inside the game tree. Are you scoring by saying, "Position scores 1 point if player has more pieces than the opponent, -1 point is player has fewer pieces, 0 points if they have the same number of pieces?"
If so, then your algorithm might just be capture averse for the first five moves, or things are working out so that all captures are balanced. I'm not deeply familiar with checkers, but it doesn't seem impossible that this is so for only five moves into the game. And if it's only 5 plies (where a ply is one player's move, rather than a complete set of opposing moves) maybe its not unusual at all.
You might want to test this by feeding in a board position where you know absolutely the right answer, perhaps something with only two checkers on the board with one in a position to capture.
As a matter of general principle, though, the board evaluation function doesn't make a lot of sense-- it ignores the difference between a piece and a crowned piece, and it treats a three piece advantage the same as a one piece advantage.