Solution for Multiplayer Random OOS Errors: Pseudorandom #s.

Discussion of all aspects of multiplayer development: unit balancing, map development, server development, and so forth.

Moderator: Forum Moderators

Post Reply
User avatar
Elvish_Pillager
Posts: 8137
Joined: May 28th, 2004, 10:21 am
Location: Everywhere you think, nowhere you can possibly imagine.
Contact:

Solution for Multiplayer Random OOS Errors: Pseudorandom #s.

Post by Elvish_Pillager »

Put this in your [multiplayer] tag, and you can use random numbers from turn 2 on. See the comments next to "#define PSEUDORANDOM NUMBER" for usage.

EDIT: It's still a little buggy, the while loop times out frequently. Please wait.
COUNTER-EDIT: I've fixed it, it should even be possible to generate a random number between 0 and 0 now.


Edit: Warning: After testing, one player I played with were faced with Out Of Sync errors. I suspect floating-point multiplication errors, but it could easily have been something else.

Code: Select all

################################################################################################
################Pseudo-Random Number Generation Engine For Multiplayer##########################
################################################################################################

#Don't use this, it's for internal use by other macros
#define GETNEXTNUMBER
{VARIABLE_OP xrand multiply 19}
{VARIABLE_OP xrand add 45}
[while]
[variable]
name=xrand
greater_than=32767
[/variable]
[do]
{VARIABLE_OP xrand add -32768}
[/do]
[/while]
#enddef

[event]
name=turn 2
	{VARIABLE xrand 0}
	[store_unit]
	[filter]
	[/filter]
	variable=units
	[/store_unit]
	{FOREACH units i}
		{VARIABLE_OP temp to_variable units[i].hitpoints}
		{VARIABLE_OP xrand add $temp}
	{NEXT i}
{GETNEXTNUMBER}
{GETNEXTNUMBER}
{GETNEXTNUMBER}
{GETNEXTNUMBER}
{GETNEXTNUMBER}
{GETNEXTNUMBER}
	{CLEAR_VARIABLE temp}
	{CLEAR_VARIABLE units}
[/event]

#Instead of {RANDOM 0..155}, use {PSEUDORANDOM 156}. This is the only way to use it.
#You can use {VARIABLE_OP random add X} afterwards to get a higher range.
#define PSEUDORANDOM NUMBER
{GETNEXTNUMBER}
{VARIABLE_OP random to_variable xrand}

{VARIABLE temp 1024}
{VARIABLE_OP temp multiply {NUMBER}}
{VARIABLE_OP temp2 to_variable temp}
{VARIABLE_OP temp2 multiply -1}
[while]
	[variable]
	name=temp
	less_than=$random
	[/variable]
		[do]
		{VARIABLE_OP random add $temp2}
		[/do]
[/while]

[while]
[or]
[variable]
name=random
greater_than={NUMBER}
[/variable]
[/or]
[or]
[variable]
name=random
equals={NUMBER}
[/variable]
[/or]
[do]
{VARIABLE_OP random add -{NUMBER}}
[/do]
[/while]
#enddef
It's all fun and games until someone loses a lawsuit. Oh, and by the way, sending me private messages won't work. :/ If you must contact me, there's an e-mail address listed on the website in my profile.
User avatar
Elvish_Pillager
Posts: 8137
Joined: May 28th, 2004, 10:21 am
Location: Everywhere you think, nowhere you can possibly imagine.
Contact:

Post by Elvish_Pillager »

:x This is so frustrating. The system doesn't work at all for about half the population, probably due to different implementations of floating-point multiplication.

Oh well, it's better than 0% of the population, but still...
It's all fun and games until someone loses a lawsuit. Oh, and by the way, sending me private messages won't work. :/ If you must contact me, there's an e-mail address listed on the website in my profile.
MadMax
Posts: 1792
Joined: June 6th, 2004, 3:29 pm
Location: Weldyn, Wesnoth

Post by MadMax »

try using addition loops to fake multiplication. ie. instead of xrand multiply 19 do this:

Code: Select all

[set_variable]
name=i
value=0
[/set_variable]
{VARIABLE_OP xranda to_variable xrand}
[while]
[variable]
name=i
not_equals=19
[/variable]
[do]
{VARIABLE_OP xrand add xranda}
{VARIABLE_OP i add 1}
[/do]
[/while]
EDIT: EP, we are both Mac users, and we both saw that one item which Konrad didn't. Perhaps it just doesn't work cross-platform?

Also, why can't there be true random support :roll: ? I would implement it with this system: the computer which has created the game generates the random number, and sends it to the other computers.
Last edited by MadMax on November 12th, 2004, 10:41 pm, edited 1 time in total.
"ILLEGITIMIS NON CARBORUNDUM"

Father of Flight to Freedom
http://www.wesnoth.org/wiki/FlightToFreedom
User avatar
Elvish_Pillager
Posts: 8137
Joined: May 28th, 2004, 10:21 am
Location: Everywhere you think, nowhere you can possibly imagine.
Contact:

Post by Elvish_Pillager »

MadMax wrote:try using addition loops to fake multiplication. ie. instead of xrand multiply 19 do this:

Code: Select all

[set_variable]
name=i
value=0
[/set_variable]
{VARIABLE_OP xranda to_variable xrand}
[while]
[variable]
name=i
not_equals=19
[/variable]
[do]
{VARIABLE_OP xrand add xranda}
{VARIABLE_OP i add 1}
[/do]
[/while]
Nice idea. Testing...
It's all fun and games until someone loses a lawsuit. Oh, and by the way, sending me private messages won't work. :/ If you must contact me, there's an e-mail address listed on the website in my profile.
MadMax
Posts: 1792
Joined: June 6th, 2004, 3:29 pm
Location: Weldyn, Wesnoth

Post by MadMax »

to do the white dots, you first put a side 3 in the map which must be empty. Set it to ai_algorithm=idle_ai, colour=whatever white is (I think 255), and no_leader-yes. Then, every time you create an item, you need to have a unit Invisible (fake unit with no image) created there. Then to move onto that square, what they do is kill Invisible (it has a 1-0 berserk attack both melee and ranged, and has [defense] tags to give you a 99% chance of hitting, and 1 hitpoint), and a kill event teleports it to the item site and gives you the item.
"ILLEGITIMIS NON CARBORUNDUM"

Father of Flight to Freedom
http://www.wesnoth.org/wiki/FlightToFreedom
User avatar
Elvish_Pillager
Posts: 8137
Joined: May 28th, 2004, 10:21 am
Location: Everywhere you think, nowhere you can possibly imagine.
Contact:

Post by Elvish_Pillager »

Madmax, that's crazy, and it's so incredibly hacky that I won't do it.

Now, what I need is a mechanism of extracting numbers from xrand that isn't modulus, because modulus extraction gives bad results. (I'll have to work on this tomorrow... too late for me)
It's all fun and games until someone loses a lawsuit. Oh, and by the way, sending me private messages won't work. :/ If you must contact me, there's an e-mail address listed on the website in my profile.
Dave
Founding Developer
Posts: 7071
Joined: August 17th, 2003, 5:07 am
Location: Seattle
Contact:

Post by Dave »

I'm actually thinking of an engine-based solution that should work.

At the moment, all random numbers are generated by the machine whose 'turn' it is. I.e. the machine with the player whose currently playing. These numbers are sent to other clients.

The problem arises because in the context of some events, such as a new turn event, it's between turns, and so there is no 'controlling' machine.

My idea for a solution is to make a consistent random number algorithm (likely 'stolen' from GNU Go), and then have the host machine specify the seed at the start of the game.

David
“At Gambling, the deadly sin is to mistake bad play for bad luck.” -- Ian Fleming
Dave
Founding Developer
Posts: 7071
Joined: August 17th, 2003, 5:07 am
Location: Seattle
Contact:

Post by Dave »

I'm actually thinking of an engine-based solution that should work.

At the moment, all random numbers are generated by the machine whose 'turn' it is. I.e. the machine with the player whose currently playing. These numbers are sent to other clients.

The problem arises because in the context of some events, such as a new turn event, it's between turns, and so there is no 'controlling' machine.

My idea for a solution is to make a consistent random number algorithm (likely 'stolen' from GNU Go), and then have the host machine specify the seed at the start of the game.

This should also have the very mild side-benefit of reduced bandwidth usage. It'll also make it slightly harder to cheat in that players won't be able to 'rig' the random numbers, though they will still be able to see what future random numbers are.

Eventually we may have an option to have random numbers generated by the server, though that has the disadvantage of possible latency (e.g. you click to attack an enemy, and the game pauses before attacking while it queries the server for random numbers).

David
“At Gambling, the deadly sin is to mistake bad play for bad luck.” -- Ian Fleming
MadMax
Posts: 1792
Joined: June 6th, 2004, 3:29 pm
Location: Weldyn, Wesnoth

Post by MadMax »

I think there is a way to do random names, but I can't figure out the WML which would handle it:

use a macro that accepts AMOUNT and NAMES (which is list of names)
convert NAMES into an array (where I am stuck)
get a random number from 1 to AMOUNT with {PSEUDORANDOM
transfer NAMES[RANDOM] into RANDOM_NAME
"ILLEGITIMIS NON CARBORUNDUM"

Father of Flight to Freedom
http://www.wesnoth.org/wiki/FlightToFreedom
Post Reply