I'm trying to make a simple AI for a little character that just wanders around for my 2D game. I am currently using my own way where there is a thread for each character that chooses a random number between 0~2 every 0.5 seconds.
If the number is 0 : character does not move.
If the number is 1 : character moves right.
If the number is 2 : character moves left.
But I figured out that if I use this, there will be too many threads if there are many characters, therefore making the game slower. Is there a more efficient way to make a simple AI for this type of character?
Is there a particular reason why each character has to be represented by a thread? If you're dealing with massive amounts of updates, then you may possibly consider creating one thread that deals with generating random moves of all characters in parallel with your game, however I'm guessing that isn't going to be your case.
The simple and optimal way to do this is to simply generate a random move for each character. If each character is its own class, then add a method called "moveRandomDirection()" that generates a random number and applies the move to its position.
Perhaps you're overthinking it.
Related
My question is more about logic than coding itself:
I am building a python script to simulate poker hands and get statistics from it.
My code works very well for assigning and comparing hands, and the only bottleneck for my script is getting the best combination of cards for each player:
The simulation is for omaha - each player gets 4 cards and the board has 5 cards. Each player must use the best combination of 5 cards (2 from the player's hand and 3 from the board).
The problem is: So far the only way I can think of doing this is comparing every possible hand a player can have and then compare to the other players.
For example, player A has cards A1A2A3A4 and the board is B1B2B3B4B5:
First I am comparing all possible hands player A can get:
[A1A2B1B2B3, A1A2B1B2B4, A1A2B1B2B5,...,A3A4B3B4B5] and get his best hand (that's 60 combinations from each player).
Do this for all players and then check who has the winner hand.
My question is: Do you think there is a way to get each player's best hand without having to check all 60 combinations?
It took me 16 hours to run ~6.5 billion iterations (~2.5 million hands x 60 board combinations x 40 iterations per hand).
Could you also weight in about the efficiency? I don't know if I am trying something impossible to be done here =P
EDIT - SOLVED
Thanks for the inputs, guys. In the end I solved it by using bit manipulation:
https://codereview.stackexchange.com/questions/217597/forming-the-best-possible-poker-hand?noredirect=1#comment421020_217597
Depends on how your evaluation function works. If you just have a black-box that takes a 5-card hand and produces an evaluation, then there's not much you can do other than feed it all 60 5-card hands. But if it can be broken into pieces, it might be possible to bypass some of them.
My code in onejoker, for example, is a 5-step walk through a directed acyclic graph, so I made a special-case function for 7 cards that skips repeating some of the steps for combinations that begin with the same cards. It still ends up evaluating all 21 (7 choose 5) combinations, but in fewer than 5 * 21 steps. You could do something similar for Omaha hands.
I would not divide into 5-hard hands:
Use collections.Counter on the 9-card hand to check for 4k, fh, 3k, 2p, p
Use collections.Counter on map(fget_suit, hand) to check for
flushes
Check for straights if you have to with Counter(x-y for x, y
in zip(hand[1:], hand))
If you really want to see each player's best 5-card hand:
Dump the lowest 4 (if you have four) un-paired, un-suited, un-connected cards.
That won't solve all of it, but it will cut the problem down considerably
I am trying to build a poker bot in java. I have written the hand evaluation class and I am about to start feeding a neural network but I face a problem. I need the winning odds of every hand for every step: preflop, flop, turn, river.
My problem is that, there are 52 cards and the combinations of 5 cards are 2,598,960. So I need to store 2,598,960 odds for each possible hand. The number is huge and these are only the odds I need for the river.
So I have two options:
Find the odds for every possible hand and every possible deck and every time I start my application load them and kill my memory.
Calculate the odds on the fly and lack processing power.
Is there a 3rd better option to deal with this problem?
3rd option is use the disk... but my first choice would be to calculate odds as you need them.
Why do you need to calculate all combinations of 5 cards, a lot of these hands are worth the same, as there are 4 suits there is repetition between hands.
Personally I would rank your hand based on how many hands beat your hand and how many hands your hand beats. From this you can compute your probability of winning the table by multiplying by number of active hands.
What about ignoring the colors? From 52 possible values, you drop to 13. You only have 6175 options remaining. Of course, colors are important for a flush - but here, it is pretty much binary - are all the colors the same or not? So we are at 12350 (including some impossible combinations, in fact it is 7462 as in the others, a number is contained more than once, so the color must differ).
If the order is important (e.g. starting hand, flip, flop, river or how is it called), it will be a lot more, but it is still less than your two millions. Try simplifying your problems and you'll realize they can be solved.
Introduction
I had made a extremely simple simulation on real time shuffling ball and pick ball on some time interval
https://github.com/gaplo917/Mark6-java/blob/master/src/Mark6.java
What I want to simulate is :
There are total 49 ball in a machine, the machine will keep shuffling the ball. After a period of time, the machine will open the gate pick a ball out.
Here is the video : http://youtu.be/5QHsYA2lcI0?t=2m2s
What I had written ( extremely easy version ):
There are 49 ball and I made it for 49+1 space.
Each shuffle of the ball if the ball is shuffle into the extra space.
After a period of time, I will check the extra space to see the ball is swapped into it and pick it out.
Then mark the space with -1 to represent the spaces is no longer valid.
Instead, I should pick a ball randomly but not using an extra space. Just ignore this scenario...
After this work, I will try to use Android Game engine to simulate the gravity and collision for learning purpose.
Back to my question :
Is it a good way to represent used data by -1 ? Is it a normal approach in real world application?
A more Object-Oriented way to handle this would be to create a BallSlot class with separate members for ball number and for whether it's valid.
It's generally not a good idea to use sentinel values like 0 or -1. It overloads multiple semantic meanings into a single data value, which complicates parsing the value. Practically speaking, it means all the code that uses the value becomes riddled with if() statements.
It would be more Java-like to model the balls as objects, even if for now they only have the one field "id". You may very well want to add other properties (position, momentum, etc, if you will extend this to do physics sim as you indicate), and you will need them to be Objects then!
If you're just using int to represent the balls, yes, it's common practice to do something like "-1 means empty". Please do not become "clever" and start using "-2" and "-3" to indicated other sorts of things, however. =)
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.
Can anyone shed any light on how a program like that might be structured?
What java classes would they employ to keep track of so many particles and then check against them for things like collision detection? Particles need to know what particles they are next to, or that they're not next to anything so they can fall etc.
Here's an example, incase you're not sure what a sand game is.
Arrays, mainly.
A one-dimensional array of actively moving grains, represented by two coordinates (and possible a velocity if you want gravitational acceleration).
A two-dimensional array of bools (or colours), representing the fixed parts of the world.
The simplest physics model is to remove a grain once it is at rest (e.g. when the world positions below, below to the left and below to the right are filled): instead, the corresponding world coordinate is filled in. This keeps the calculations manageable. Allow a grain to shift down if either the left or right below world coordinate is free. Grain collisions between moving grains can be ignored without loss of much verisimilitude.
(I can't quite get over how much CPU power we've got to spare these days!)
The simple version can be implemented without much trouble on a loose friday night (like I did just now). Simply make a program with a 2D array (of bytes, ints, whatever) representing your field. In each tick, iterate over all the elements and do a check:
If the field below (array[x][y+1]) is empty, move 1 spot down (= set [x][y] to empty, [x][y+1] to occupied)
Else, if [x-1][y+1] is empty, go there.
Else, if [x+1][y+1] is empty, go there.
That's the basics. Next you have to add checks like not 'repeating' the calculation for a grain (set a flag at the new position that's checked at the following iterations).
I followed this tutorial, it's quite good, not too long but still points out common pitfalls and things like that.