I'm making a networked card game that will be played on android and PC.
To handle stuff like shuffling the cards before the game starts and choosing who goes first (and a couple other things like that) I want to use java.util.Random and set a seed on the server and all of the clients to be the same (generated by the server).
This seems to be the easiest way, and more efficient than sending a long message containing the sequence of all 52 cards in the deck shuffled by the server
Is this something I can count on to always generate the same numbers from the same seed on different kind of JVMs/JREs etc (I'm mainly thinking about various versions of android and different versions of dalvik JVM used by android and other things), or should I go the route of shuffling the cards on the server and sending the card list to all the players? (or is there something I can use besides java.util.Random?)
Since standard javadoc states that Random must behave the same in all plattforms, you should trust that. Nevertheless, you could let Random appart and code your own algorithm to produce pseudo-random numbers: For example: Imagine a SINE-based function:
double myRandom=amplitude*Math.sin(frequency * sequence)
... where amplitude is the upper bound of your numbering interval (52), and frequency should be a high constant value, non multiple of PI. And sequence should start by a constant offset value and be incremented every time you get a new random value.
Choosing accurately a value for the frequency, you could also ensure that your algorithm won't produce repeated values within a certain number of iterations.
According to javadoc, all implementations are required to be the same.
Java implementations must use all the algorithms shown here for the
class Random, for the sake of absolute portability of Java code.
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html
Related
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.
I wrote a class that, given a seed and difficulty, will return a playing field to my game. The generation is consistent (no matter what, the same seed & difficulty level will always result in the same play field). As far as I know all android devices use Java 1.6 so here goes my question(s):
Is it safe to send only the seed and difficulty to other devices in a multiplayer environment?
Do I need to worry about when Google updates Java version level form 1.6? or will they likely update all android devices to that version level (I am assuming the Random class will have been changed)? And if not what would be a good way to detect if Random class is different?
Rephrased, what precautionary measures should be in place to ensure that the class java.util.Random, which my field generation class uses heavily, will result in the same play field for every device? Or, alternatively, would it be more wise to consider sending all play field data to the non-hosting device(s)?
I could probably accomplish the latter with a reliable message with size of:
byte[ROWS * COLUMNS]
In advance, I appreciate any guidance/suggestions in this matter. This is a difficult issue to search for so some links for future views may be appropriate.
There are a few options here, but I guess I was hoping for some magic JVM property defining the java.util.Random class revision version.
First option is to check the java version and compare it against the other device's version. If they are the same it is safe (as far as I know) to assume that the Random class is the same and thus the seed and difficulty can be sent. If, however, they are different you either send all the data or check the documentation/version release notes yourself to see when the Random class was changed and then determine if all the data should be sent based on previously acquired java version identifier.
The second option is to simply always send all the data. Which is what I will personally be doing.
If you're not as lucky as I and your data exceeds the value of Multiplayer.MAX_RELIABLE_MESSAGE_LEN (in bytes) you may have to break the data into multiple messages which could get ugly but is entirely doable.
I have a continuous stream of integers across the space of all the 32-bit integers, and upon each update I want to know either the exact or approximate entropy of the distributions of integers I have encountered. It can be global entropy across the lifetime or a windowed approximation that attenuates older information as time passes.
Does anyone know of a library that does this already or an algorithm that has this property?
Clearly, this is a streaming algorithm as it is too expensive to iterate over the range each time and calculate the entropy on each update. Does anyone know of such an algorithm or sketch data structure that can do this?
The motivation and use case is that I want to detect skew in the stream of integers. It is supposed to be uniform across the range of integers but at certain times, due to other conditions, the uniformity may be disturbed and I think entropy is the best way to detect this kind of condition. I'd ideally have an alert on low entropy for the calculating component.
Thanks for any help!
EDIT: I actually found a paper that does exactly this but I know of no existing implementation. Reusing tested, verified code would be way better than having to implement it myself. :)
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. =)
I am working on a spades game that connects players over the internet, but I don't know how I should distribute the cards to players:
If I send the seed values for the SecureRandom object used for shuffling to each player, they could theoretically sniff their own traffic for the values and look at the source code to create their own program that deals the cards similarly;
But if I use the dealer-player's machine to deal the cards and send them to the other players, the dealer could theoretically cheat.
Sending seed values would decrease the amount of data sent over the internet, but sending the actual cards would seem to make it harder to cheat. I've thought about making my own trusted third-party server that the dealer-player would send their seed values to and would send the cards to the other players, but that would require setting up an EC2 instance and I have no idea how to even begin to do that.
Or am I overthinking this a bit?
You can have a decentralized card game without cheating.
However, you should consider that cheating might not be an issue as long as players aren't competing to be on a leaderboard or anything.
Also, if the dealer sends just the seed out, he can still cheat.
I would think that the only way to prevent cheating is to have a central, trusted server deal the cards, and notify each user what cards he got. Or is the problem that you don't have a central, trusted server, but rather are making an app available which other users can run as a "dealer"?
If that's the case, I would think the problem is unsolvable even in theory. If someone else runs the server that deals the cards, no matter how you manage it, he could always fudge the seed value to give everyone the cards he wants, or examine the seed value so he can predict all the cards that will come up. Or for that matter, he could intercept the output stream from his server and replace it with whatever cards he wants.
I was briefly thinking that you could send some hash value along with each deal that is associated with the random number generator, so that a program on the receiving end could validate that the hash is consistent with the card sent. Assuming the hash is generated by some secure encryptian algorithm, the dealer could have a hard time changing a card and generating a fake hash code that was consistent with the card he sent. But that would be easy to beat: The dealer could just run the deal program a few hundred times, get a list of valid deals and hash codes, and then pick one of these to send out.
Maybe you could have the players send a token which is factored into the random number generator. But I can't think of an actual algorithm for including such a token that can't be beaten by the dealer system simply repeating whatever calculation is done on the token.
If you send a seed, then any player can find out the cards any other player is holding. Also, the dealer can choose the seed he sends out to be in his favor.
If you send cards from the dealer, then the dealer knows what everyone is holding. Either use a central server, or use some crypto like Nick's answer suggests