Sign in to follow this  
Lesan

Multiplayer game randomness

Recommended Posts

I'm creating a multiplayer over-the-internet tactical game. In combat, the attacker deals a random amount of damage to the target.

How should I code it to be certain that the amount of damage dealt will be the same on both computers? That is, that there won't be any out-of-sync errors.

I think of two possibilities:
1. Have the attacker generate a random number and send that number over.
2. At the beginning of the game, have the host send his random generator seed to all other computers so that they generate the same numbers.

Are there any other options? Is the second option possible at all? Which option is most often used/preferred?

I use C#/.NET and the Random class.

Thank you in advance,
Petr

Share this post


Link to post
Share on other sites
Instead of a pseudo-random number generator, you could take some details of the impact (the attacker's id, the target's id, the game-logic frame number in which the impact happens (assuming those are synchronized across computers)...) and hash all that information together. A decent hash will result in numbers that are hard to predict and which will be identical on both computers.

Share this post


Link to post
Share on other sites
Is your network peer-to-peer or server based?

If it's peer-to-peer, then you should have one client-as-server (the client who is the effective server for the other clients). If it's server based, then you already have a centralized server. Either way, I believe it's a really good idea to have a central authority managing the game state for the entire game. The game state refers to the objective, numerical representation of everything in the game world at the moment. This is stuff like.

Inventory
Entity Stats (Health, attack, mana, etc)
Ability Cooldowns
Entity Position and Orientation

These are all values that affect how the game is being played. If one client thinks PlayerC has an attack power of 10, while another client things PlayerC has an attack power of 50, their simulations are going to be out of synch. A way to mitigate this is to keep clients basically ignorant of the game state and handle it all on the server by passing action messages. Well, not completely ignorant. The clients will have a very slim dummy version of the gamestate that's used mostly for displaying information to the player, like current health or unit stats that they player can view. This information is not authoritative, however, and is never used for calculations.

For instance.

PlayerC wants to attack player A, so he right clicks on PlayerA's nearby squad.
PlayerC's game client sends a message to the server that says, "I want to attack PlayerA." That's all it says, it's just an action request.
The server receives the request and validates it (makes sure PlayerC is close enough to attack, his attack is not on cooldown, has resources to attack, so on and so forth).
The server then resolves the action by modifying its copy of the game state. It looks up what PlayerC's attack value is, then attacks PlayerA with that value.
The server sends back the dummy gamestate to its clients, showing updated health for PlayerA.

Not only does this make the game easier to keep in synch between clients, but it can make it more secure. If clients could pass up information like their attack damage to the server, and the server used it to deal damage to other players, someone could spoof their attack value and cheat pretty easily. By keeping everything in the server and letting the client only issue commands, the server keeps such sensitive values locked down and is generally more secure (though not 100% secure).

However, if something in the game doesn't effect gameplay, it doesn't need to be on the server. Say enemies have ragdoll physics associated with them when they die as a purely graphical effect (no picking up crocodiles and flailing other crocodiles to death with them). This has no impact whatsoever on the outcome of the game, it's just a sweet looking effect. There's no reason to process it on the server, you can let the client process it instead. It won't look the same between different clients, but who cares!? Same with generating particle effects for fire or a spell.

General rules of thumb:
1) If the value impacts the outcome of the game, generate it, process it, and keep it on the server.
2) If the value doesn't affect the outcome of the game, generate it, process ti and keep it on the client.
3) Try to eliminate the client sending game state information to the server wherever possible, especially raw numerical information. This makes your game more vulnerable to cheating.

(Disclaimer: This is simply my approach to server-client game state division. You can do it other ways, and may have to depending on the game.)

Share this post


Link to post
Share on other sites
Generating the number on a server and sending it to the clients involved would be the most secure method.

If you don't mind the potential exploits involved with this method, sending the random number generator seed to the clients would allow you to cut down on some network traffic (depending on how you handle timing), and not just for attacks. If the client has the seed, he can figure out for himself what loot drops, if he succeeds in mining ore, etc. Of course, the server would have the "real" state, but both the client and the server should stay in sync unless the client is compromised or another client gets involved in some way.

Another advantage with giving the client the seed is that you can avoid latency. The client would be able to predict actions a lot more reliably.

It pretty much depends on what you want.

Share this post


Link to post
Share on other sites
[quote name='Lesan' timestamp='1302719941' post='4798064']
I'm creating a multiplayer over-the-internet tactical game. In combat, the attacker deals a random amount of damage to the target.

How should I code it to be certain that the amount of damage dealt will be the same on both computers? That is, that there won't be any out-of-sync errors.

I think of two possibilities:
1. Have the attacker generate a random number and send that number over.
2. At the beginning of the game, have the host send his random generator seed to all other computers so that they generate the same numbers.

Are there any other options? Is the second option possible at all? Which option is most often used/preferred?

I use C#/.NET and the Random class.

Thank you in advance,
Petr
[/quote]

The second option is definitly doable for some games, most RTS games use a similar method, see: http://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf

There is however a quite significant delay with this system as you can't process the events for a "step" until you have retrieved the relevant commands from all players (All players need to know what everyone else did before they can start using the random numbers in order to get the same results), unless you are playing with a large number of units you're probably better off calculating the values on the server and sending them out to the clients.

Share this post


Link to post
Share on other sites
Any of the previously suggested approaches should work. However, if you want to make it cryptographically secure (ie to prevent cheating) you would probably need to do something a bit more complicated. Here is a discussion on stack overflow that gives a sketch of a two-phase procedure that should work: [url="http://stackoverflow.com/questions/224058/distributed-random-number-generation"]http://stackoverflow...mber-generation[/url]


For your problem, what you would do is basically have both players independently generate random numbers, then hash them with some salt to generate a signature. Then they exchange signature with each other. After this is complete, they then tell each other what their random number + salt was, and then verify the hash. If this fails, then one of the players was cheating so you can retry. Otherwise, just combine the numbers together (probably do something like xor them / concatenate and rehash) and then take the result as the new random number.

EDIT: For more information, see: [url="http://en.wikipedia.org/wiki/Commitment_scheme"]http://en.wikipedia.org/wiki/Commitment_scheme[/url]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this