Way way back (think 20+ years) I encountered a Gomoku game source code in a magazine that I typed in for my computer and had a lot of fun with.
The game was difficult to win against, but the core algorithm for the computer AI was really simply and didn't account for a lot of code. I wonder if anyone knows this algorithm and has some links to some source or theory about it.
The things I remember was that it basically allocated an array that covered the entire board. Then, whenever I, or it, placed a piece, it would add a number of weights to all locations on the board that the piece would possibly impact.
For instance (note that the weights are definitely wrong as I don't remember those):
1 1 1
2 2 2
3 3 3
444
1234X4321
3 3 3
2 2 2
1 1 1
Then it simply scanned the array for an open location with the lowest or highest value.
Things I'm fuzzy on:
Perhaps it had two arrays, one for me and one for itself and there was a min/max weighting?
There might've been more to the algorithm, but at its core it was basically an array and weighted numbers
Does this ring a bell with anyone at all? Anyone got anything that would help?
Reading your description, and thinking a little about it, I think it probably works with a single array, exactly the way you described.
To accomplish the goal of getting five-in-a-row you have to (a) prevent the opponent from succeeding and (b) succeed yourself.
To succeed yourself, you have to place stones near other stones you already have on the board, so it makes sense to add a positive score for fields next to your stones that could participate in a row. Either the linear example you gave, or something quadratic would probably work well.
To prevent your opponent from succeeding, you have to place stones next to his / her stones. It's especially good if you strike two birds with a single stone, so opponent's stones should increase the value of the surrounding fields the same way yours do -- the more stones he already has lined up, the higher the score, and the more likely the algorithm will try to cut the opponent off.
The most important thing here is the weighting of the different fields, and whether the opponent's stones are weighted differently than yours. Unfortunately I can't help with that, but the values should be reasonably simple to figure out through trial and error once the game itself is written.
However this is a very basic approach, and would be outperformed by a tree search algorithm. Searching Google, there's a related paper on Threat search, which apparently works well for Gomoku. The paper is behind a pay-wall though :/
I haven't read the article, but from the description my guess would be some form of the Minimax algorithm
I saw this algorithm you mentioned - it was pretty simple and fast (no backtracking :-)) and it played very well :-) I must have the source somewhere but it is a lot years ago... There were weights for your stones depending on how much of other stones were near, and weights of oponent stones. These were lower so the algorithm preferred the attacking strategy.
But this is of course very trivial algorithm. Winning strategy has been already found.
See this paper: L. Victor Allis, H. J. van den Herik, M. P. H. Huntjens. Go-Moku and Threat-Space Search. It helped me a lot when I was writting my own program. This way you'll be able to write program which is very good in attacking the opponent and finding winning combinations.
It's an ancient game - I found the code on Planet Source Code. I played this game during college and in 286 days had a BASIC version of it.
Here is the program you are looking for
ftp://ftp.mrynet.com/USENIX/80.1/boulder/dpw/gomoku.c
It is almost 40 years old
Working on an open source version for iPhone.
Hit me up if interested in joining!
https://github.com/kigster/kigomoku
Related
I am looking for a faster way to solve this problem:
Let's suppose we have n boxes and n marbles (each of them has a different kind). Every box can contain only some kinds of marbles (It is shown it the example below), and only one marble fits inside one box. Please read the edits. The whole algorithm has been described in the post linked below but it was not precisely described, so I am asking for a reexplenation.
The question is: In how many ways can I put marbles inside the boxes in polynomial time?
Example:
n=3
Marbles: 2,5,3
Restrictions of the i-th box (i-th box can only contain those marbles): {5,2},{3,5,2},{3,2}
The answer: 3, because the possible positions of the marbles are: {5,2,3},{5,3,2},{2,5,3}
I have a solution which works in O(2^n), but it is too slow. There are also one limitation about the boxes tolerance, which I don't find very important, but I will write them also. Each box has it's own kind-restrictions, but there is one list of kinds which is accepted by all of them (in the example above this widely accepted kind is 2).
Edit: I have just found this question but I am not sure if it works in my case, and the dynamic solution is not well described. Could somebody clarify this? This question was answered 4 years ago, so I won't ask it there. https://math.stackexchange.com/questions/2145985/how-to-compute-number-of-combinations-with-placement-restrictions?rq=1
Edit#2: I also have to mention that excluding widely-accepted list the maximum size of the acceptance list of a box has 0 1 or 2 elements.
Edit#3: This question refers to my previos question(Allowed permutations of numbers 1 to N), which I found too general. I am attaching this link because there is also one more important information - the distance between boxes in which a marble can be put isn't higher than 2.
As noted in the comments, https://cs.stackexchange.com/questions/19924/counting-and-finding-all-perfect-maximum-matchings-in-general-graphs is this problem, with links to papers on how to tackle it, and counting the number of matchings is #P-complete. I would recommend finding those papers.
As for dynamic programming, simply write a recursive solution and then memoize it. (That's top down, and is almost always the easier approach.) For the stack exchange problem with a fixed (and fairly small) number of boxes, that approach is manageable. Unfortunately in your variation with a large number of boxes, the naive recursive version looks something like this (untested, probably buggy):
def solve (balls, box_rules):
ball_can_go_in = {}
for ball in balls:
ball_can_go_in[ball] = set()
for i in range(len(box_rules)):
for ball in box_rules[i]:
ball_can_go_in[ball].add(i)
def recursive_attempt (n, used_boxes):
if n = len(balls):
return 1
else:
answer = 0
for box in ball_can_go_in[balls[n]]:
if box not in used_boxes:
used_boxes.add(box)
answer += recursive_attempt(n+1, used_boxes)
used_boxes.remove(box)
return answer
return recursive_attempt(0, set())
In order to memoize it you have to construct new sets, maybe use bit strings, BUT you're going to find that you're calling it with subsets of n things. There are an exponential number of them. Unfortunately this will take exponential time AND use exponential memory.
If you replace the memoizing layer with an LRU cache, you can control how much memory it uses and probably still get some win from the memoizing. But ultimately you will still use exponential or worse time.
If you go that route, one practical tip is sort the balls by how many boxes they go in. You want to start with the fewest possible choices. Since this is trying to reduce exponential complexity, it is worth quite a bit of work on this sorting step. So I'd first pick the ball that goes in the fewest boxes. Then I'd next pick the ball that goes in the fewest new boxes, and break ties by fewest overall. The third ball will be fewest new boxes, break ties by fewest boxes not used by the first, break ties by fewest boxes. And so on.
The idea is to generate and discover forced choices and conflicts as early as possible. In fact this is so important that it is worth a search at every step to try to discover and record forced choices and conflicts that are already visible. It feels counterintuitive, but it really does make a difference.
But if you do all of this, the dynamic programming approach that was just fine for 5 boxes will become faster, but you'll still only be able to handle slightly larger problems than a naive solution. So go look at the research for better ideas than this dynamic programming approach.
(Incidentally the inclusion-exclusion approach has a term for every subset, so it also will blow up exponentially.)
I'm working on making a sudoku app, and one of the things needed is a way to solve the sudoku. I did a lot of research on some backtracking algorithms, including making my own version, but then came across Dancing Links and Algorithm X. I've seen a few implementations of it, and it looks really cool, but had some questions - I can't quite wrap my head around it fully yet (I don't have much experience coding, so I haven't grasped all of what's needed to fully understand the core of it and how it works, though I am using this as a handy reference)
As far as I understand, you have a sudoku, which you then convert to an array of 1s and 0s - the end goal of which is to find a combinations of rows that will be fully 1s - that then means we've found a valid solution (yay!)
Now, I kinda sorta understand how that works on normal sudokus - for example, if we put a 5 in the top left cell, it removes all the other options along that row and column, and in turn also removes all options of a 5 being in that square too. But what I don't quite understand is if I'm doing a sudoku variation, how will it work? For example, one popular type of variation is X-Sudoku, where, on top of the normal rules, you have to have the numbers 1 to 9 once on each of the main diagonals. Can I just pretend there's an extra 2 rows/columns on the sudoku that also need to be filled from 1-9 and do it that way, or does it not work like that?
Now, the hard question: another variant is anti-knight sudoku. Basically, on top of the normal rules, you can't have the same number a chess knight's move away (2 out and 1 to the side). Since this now gets a bit wonky in terms of the rows and whatnot, can these be added as extra constraints to the algorithm to solve sudokus along these lines?
X-Sudoku can be solved exactly the way you describe.
Anti-knight Sudoku is trickier because the anti-knight constraint does not fit as straightforwardly into the exact cover framework. There's an extension of Algorithm X that handles packing constraints (at most one instead of exactly one) efficiently by treating them as satisfied when choosing an unsatisfied constraint. Then for each triple of consisting of a digit and two squares a knight's jump apart, you have a packing constraint that at most one of those squares is filled with that digit.
If implementing Algorithm X seems like too much of a challenge, you could look into finding a SAT solver library instead.
I am thinking about an AI for a game that I could implement. My question is about finding an evaluation function for this game in order to apply the minimax algorithm with alpha/beta cuts.
https://en.wikipedia.org/wiki/Minimax
https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning
Let me describe the game first, explain what I plan to achieve with my AI, and get to the problem.
The game:
A 2-player turn-by-turn game.
Goal is to kill opponent or have more life points at the end.
In comparison with Magic: The Gathering, you both have monsters to attack the opponent. The number is fixed, let’s say 5 each.
A monster has a fight ability (let's say between 1 and 10), and a damage ability (let's say between 1 and 5).
Each turn:
- Active player declares to his opponent which monster (he owns) engages the current fight.
- He secretly sets multipliers face down (let’s see that in next paragraph).
- Opponent declares which monster (he owns) fights against the first one, while setting multipliers the same way.
- Fight: fight ability * multipliers = final attack. Biggest attack wins and inflicts damage ability to opponent.
- Next turn, active player switch
About multipliers: you have 4 cards in hand that can double your attack (and many empty cards, so that you put 4 cards each turn on the table, and the opponent does not know if you multiplied by 1, 2, 4, 8 or 16).
Just in case: let's say we have a rule for draws to be solved.
What I expect with the AI:
To be able to say if a perfect player should win in a given position. That means, for a winnable position, AI should tell that there is a way that leads to victory, and give the steps (see example below). For a position that is a winnable by the opponent, I have not decided yet, neither for positions that do not lead to the same winner in all cases (they exist ;D).
** An example: **
2 rounds left to go. I have
- Monster A: fight: 5, damage: 2
- Monster B: fight: 3, damage: 4
- life: 5, 1 multiplier left, my turn to begin
My opponent has
- Monster C: fight: 2, damage: 6
- Monster D: fight: 8, damage: 1
-life: 5, 1 multiplier left
In that case, if you think about it, you win if you play well.
Solution:
You can see that if monster C wins, he inflicts 6 and I lost.
But if he loses, one my monsters will inflict at least 2, and even if monster D wins (before or after),
I won't die and I will have more life that my opponent. Victory.
That's an example of what I want the AI to find.
Of course, I simplified the example. Maybe it can be trickier. And that's where my question arrives.
We can mentally kind of see that it is simple to calculate all possible duels when we have 2 rounds left (the last round does not need calculation: it is deterministic if both play their last multipliers).
As we said, we have 5 rounds to go. But my point is that we could have 20, and it becomes very long to calculate everything (as in trying to find best move in first round).
Indeed, we won't try to compute that. In chess, for instance, too many positions lead to the impossibility of computing all possibilities.
But, if you follow me, there is a solution in chess - we can implement an evaluation function. How do we know that 10 moves ahead, this moves leads to a better position ? Because we evaluate this position. We claim that a position is better if it's checkmate, obviously, or if you have more pieces, or if you control the center and so on...
Then, my question here:
How to evaluate a position in the game I presented ?
I mean, first round, if I can compute the possible moves in the 2 next rounds, I arrive at all possible positions for round 3 or 4. But it does not seem to help in my opinion. You can have better life points, better cards, more left multipliers, it all depends on what will arrive next. I don't see advantages that are compliant in general situations. What about you ?
N.B.1 I hope it was clear, I simplified game rules, of course we could add rules (combo if 2 consecutive rounds won, multipliers applicable to damage ability...)
N.B.2 I thought about a neural network, but the question is still interesting for me. And a neural network seems hard to settle because of the multiple rounds (my knowledge is far more restricted than knowing any model with retroactive action in a neural network).
N.B.3 I think that minimax and alpha/beta cuts will help if I still do a full computation analysis, but what I am afraid of is computation time, that's why I ask this here. I could probably begin with complete computation for last-2-round positions, yes.
Thanks for reading, and I hope you find this problem as stimulating as I do!
One way to evaluate the position in any game is to try to understand the thinking process of players who are considered experts in the game. So you can find experts in this game and ask them about factors that determine their decisions during the game. Or you can become an expert yourself by studying the game and playing it a lot. It can be very hard to come up with a good evaluation function by just looking at the rules of the game.
I haven't played this game, but probably it makes sense to start with some simple heuristic which is a linear combination of variables that determine the game state (health points of your main character, number of multipliers you have, total fight/damage ability of all your monsters, maximum fight/damage ability of any of your monsters, number of turns left etc). Take into account the corresponding values for your opponent and you'll get the eval function like this: a1*(my_hp - opp_hp) + a2*(my_monsters_total_fight - opp_monsters_total_fight) + a3*(my_monsters_total_damage - opp_monsters_total_damage) + a4*(my_number_of_multipliers - opp_number_of_multipliers) + ..., where coefficients a1,a2,.. can be positive or negative depending on the effect of corresponding variable (for instance, coefficient of hp variable a1 is positive etc.)
Now, this function might or might not work, but at least it will give you a starting point from which you can try to improve it or completely discard if it fails miserably. You can try to improve this evaluation function by tuning the coefficients, adding some non-linear terms to produce more complex relationships between the variables (multiplications, powers, logs etc.) and see how it affects performance. You can also try to automate the tuning process by using optimization techniques like genetic algorithms and differential evolution. In general, coming up with a good heuristic can be more an art than a science (after all, it's called heuristic for a reason). Start by trial and error and see how it goes.
I'm dealing with a war game. I have a list of my bases B(x,y) from which I can send attacks on the enemy (they have bases between my own bases). Each base B can attack at a range R (the same radius for all bases). How can I find my bases to be able to attack as many enemy bases as possible, but use a minimum number of my bases?
I've reduced the problem to finding the minimum number of bases (and their coordinates) required to cover the largest area possible. I wonder if there is a better way than looking at all the possible combinations and because the number of bases could reach thousands.
Example: If the attack radius is 10 and I have five bases in a square and its center: (0,0), (10,0), (10,10), (0,10), (5,5) then the answer is that only the first four would be needed because all the area covered by the one in the center is already covered by the others.
Note 1 The solution must be single-threaded.
Note 2 The solution doesn't have to be perfect if that means a big gain in speed. The number of bases reaches thousands and this needs to use as little time as possible. I would consider running time greater than 100 ms for 10,000 bases in Python on a modern computer unacceptable, so I was thinking maybe I could start by eliminating the obvious, like if there are multiple bases within R/10 distance of each other, simply eliminate all except for one (whichever).
If I understand you correctly, the enemy bases and your bases are given as well as the (constant) attack radius. I.e. if you select one of your bases, you know exactly which of the enemy bases get attacked due to the selection.
The first step would be to eliminate those enemy cities from the problem which can not be attacked by any of your bases. Then, selecting all of your bases guarantees attacking all attackable enemy bases, so there is solution that attacks as many enemy bases as possible.
Under all those solutions you are looking for the one that uses the minimum number of your bases. This problem is equivalent to the https://en.wikipedia.org/wiki/Set_cover_problem, which is unfortunately NP-hard. You can apply all known solution methods such as Integer Linear Programming or the already mentioned greedy algorithm / metaheuristics.
If your problem instance is large and runtime is the primary concern, greedy is probably the way to go. For example you could always add that particular base of yours to the selection which adds the highest number of enemy bases that can be attacked which were previously not under attack by your already selected bases.
Hum the solution depends on your needs. If you need real time answer, maybe a greedy algorithm could provide good solution.
Other solution could be using meta-heuristic with constraint time(http://en.wikipedia.org/wiki/Metaheuristic). I probably would use genetic algorithm to search a solution for this problem under a limited time.
If interested I can provide a toy example of implementation in Python.
EDIT :
When you have to provide solution quickly a greedy algorithm is often better. But in your case I doubt. Particularity of many greedy algorithm is that you need to start from scratch each time you try to compute a new result.
Speaking again of genetic algorithm, you could for example each time you have to take a decision restart the search process from its last result. In fact you could probably let him turning has a subprocess and each 100ms take the better solution computed during the last loop.
If not too greedy in computing resource, this solution would provide better results than greedy one on the long run as the solution will probably need to be adapted to the changes of the situation but many element will stay unchanged. Just be aware that initializing a meta-search with the solution of a greedy algorithm is anyway a good idea!
This question refers to the Google-sponsored AI Challenge, a contest that happens every few months and in which the contenders need to submit a bot able to autonomously play a game against other robotic players. The competition that just closed was called "ants" and you can read all its specification here, if you are interested.
My question is specific to one aspect of ants: combat strategy.
The problem
Given a grid of discrete coordinates [like a chessboard] and given that each player has a number of ants that at each turn can either:
stay still
move east / north / west / south,
...an ant will be killed by an enemy ant if an enemy ant in range is surrounded by less (or the same) of its own enemies than the ant [equivalent to: "An ant will kill an enemy ant if an enemy in range is surrounded by more (or the same) enemies than its target"]
A visual example:
In this case the yellow ants are going to move west, and the orange ant, not being able to move away [blue tiles are blocking] will have two yellow ants "in range" and will die (if the explanation is still not clear, I invite you to visit the link above to see more examples and explained scenarios).
The question
My question is substantially about complexity. I thought to this problem extensively, but I still couldn't come up with an acceptable way to calculate the optimal set of moves in a reasonable time. It seems to me that for finding the best possible set of moves for my ants, I should evaluate the outcome for every possible scenario, but since battles can be pretty crowded with ants, this would mean that computation time would grow exponentially (5^n, with n being the number of ants involved).
Another limitation of this approach is that the solution being worked on doesn't improve its effectiveness proportionally to the time spent computing, so arbitrarily interrupting its execution might leave you with a non-acceptable solution.
I suspect that a good solution might be found via some geometrical considerations in combination with linear algebra, (maybe calculating some "centres of gravity" for groups of ants?) but I could not pass the level of "intuition" on this...
So, my question really boils down to:
How should this problem be approached to find [nearly] optimal solutions in a computation time of ~50-100 ms on a modern machine (this figure is derived by the official contest rules)?
If you are interested by the problem and need some inspiration, I highly recommend to watch some of the available game replays.
I think your problem can be solved by turning the problem around.
Instead of calculating the best moves - per ant - you could caclulate the best move candidates per discrete position on your playing board.
+1 for a save place
+2 for a place that results in an enemy dying
-1 point for a position of certain death
That would scale in a linear way - but have some trade off in not providing best individual movement.
Maybe worth a try :)
Tricky indeed. You may find some hints in Bee algorithms. This is a set of algorithms to use swarm cooperation and 'reasonable computation time'. Bee algorithms can for instance be used to roughly (!) solve the traveling salesman problem. I expect that these algorithms can provide you with the best solution given computing time.
Of course, the problem can be simplified using geometry: relative positions of ants in a neighbourhood are more important than absolute positions. And also light_303's solution is complementatry to the search pattern I propose.
EDIT FROM THE OP:
I'm selecting this answer as accepted as the winner of the contest published a post-mortem analysis of his code, and indeed he followed the approach suggested by the author of this answer. You can read the winner's blog entry here.
For these kind of problems, MinMax algorithm with alpha beta pruning is usually used. (*) [simple explanation for minmax and alpa beta prunning is at the end, but for more details, the wikipedia page should also be read].
In order to overcome the problem you have mentioned about extremely large number of possible moves, a common improvement is doing the minmax algorithm iteratively. At first you explore all nodes until depth 1, and find the best solution. If you still have some time: explore all nodes until depth 2, and now chose a new more informed best solution, and so on...
When out of time: gives the best solution you could find, at the last level you explored.
To further improve your solution, you might want to reorder the nodes you develop: for iteration i, sort the nodes in iteration (i-1) [by their heuristical value for each vertex] and explore each possibility according the order. The idea behind it is that you are more likely to prun more vertices, if you first investigate the "best" solutions.
The problem here remains finding a good heuristical function, which evaluates "how good a state is"
(*)The MinMax algorithm is simple: You explore the game tree, and decide what will you do for each state, and what is your oponent is most likely to do for each action. This is done until depth k, where k is given to the algorithm.
The alpha beta prunning is an addition to minmax, which tells you "which nodes should not be explored anymore, since any way I am not going to chose them, because I have a better solution"
My question is substantially about complexity. I thought to this
problem extensively, but I still couldn't come up with an acceptable
way to calculate the optimal set of moves in a reasonable time.
Exactly!
It's an AI competition. AI deals with problems which are too complex to be solved with optimal algorithms.
So you have to try "stuff", like your idea about centers of gravity. Even better would be some genetic algorithms where better strategies are found through natural selection (but it's hard to set up some evolving "framework" for that).
BTW: you can see the blog of the current leader and his strategy is surprisingly simple.