|
Post by sparrowhawk on Jul 13, 2004 10:51:37 GMT
Topic raised here as part of discussion of Mads' poor start positions when initiating games! I've written a simple script to test the efficacity of the shuffle() function. Here is the script: <?php
//Midnight split into 4 $QUADRANTS = array( 1=>array(1,1,30,31), //NW 2=>array(1,32,30,64), //NE 3=>array(31,1,61,31), //SW 4=>array(31,32,61,64), //SE );
for($i = 1; $i <= 100; $i++){ echo "Iteration #" . $i . "<br>\n"; shuffle($QUADRANTS); for($a = 0; $a <= 3; $a++){ echo "Player " . ($a + 1) . " starts at " . $QUADRANTS[$a][0].",".$QUADRANTS[$a][1] . "<br>\n"; } echo "<hr>\n"; } ?>
And the link to the live version is here: www.westhaven.uklinux.net/vmidnight//zzz_shuffle_test.phpOddly enough, it seems OK, but in-game there does seem to be a bias towards player 1 starting in the NW. Any thoughts?
|
|
|
Post by sparrowhawk on Jul 13, 2004 11:07:20 GMT
Forgot to say (although it will be obvious to coders) that the coordinates displayed are for the top left hand corner of each quadrant, and refer to row, column (ie y,x)
|
|
merlin
Public Area Guest
Posts: 19
|
Post by merlin on Jul 13, 2004 13:09:03 GMT
Topic raised here as part of discussion of Mads' poor start positions when initiating games! I've written a simple script to test the efficacity of the shuffle() function. Here is the script: <?php
//Midnight split into 4 $QUADRANTS = array( 1=>array(1,1,30,31), //NW 2=>array(1,32,30,64), //NE 3=>array(31,1,61,31), //SW 4=>array(31,32,61,64), //SE );
for($i = 1; $i <= 100; $i++){ echo "Iteration #" . $i . "<br>\n"; shuffle($QUADRANTS); for($a = 0; $a <= 3; $a++){ echo "Player " . ($a + 1) . " starts at " . $QUADRANTS[$a][0].",".$QUADRANTS[$a][1] . "<br>\n"; } echo "<hr>\n"; } ?>
And the link to the live version is here: www.westhaven.uklinux.net/vmidnight//zzz_shuffle_test.phpOddly enough, it seems OK, but in-game there does seem to be a bias towards player 1 starting in the NW. Any thoughts? Ignore the iterations... you are actually only interested in what happens when you refresh the page, as you will never get the iterations. Can you set a seed linke with c RAND ? if so you might want to set this to a timer or somesuch. Keep refreshing and 1,32 seems to appear regular for player one.
|
|
|
Post by sparrowhawk on Jul 13, 2004 13:18:03 GMT
Well I was thinking that I could maybe iterate a few times if the shuffle was always screwing up on the first instance. Clutching at straws maybe! As for the seeding I use the following line in the live code: srand ((double)microtime()*1000000); as uklinux have not updated their php level to a version that no longer requires seeding! They are several million versions behind the current php release
|
|
merlin
Public Area Guest
Posts: 19
|
Post by merlin on Jul 13, 2004 15:53:12 GMT
When do you seed it? Try just before the shuffle.
|
|
Perun
Public Area Guest
Issa (Vis) [1:76:24]
Posts: 2,506
|
Post by Perun on Jul 13, 2004 20:32:36 GMT
Chris is right.
Have you also tried mt_srand() and mt_rand() functions?
|
|
|
Post by sparrowhawk on Jul 14, 2004 7:21:53 GMT
Yes, I seed on the line immediately prior to the shuffle, and I have tried the mt_ functions a while back. I seem to recall no noticeable difference, but I'll try again, jut to be sure.
Here's the actual code that creates the array and shuffles it:
//Randomise which quadrant each lord will start in //Need the max size of the map, to work out quadrant boundaries $query = "SELECT MAX(MPD_Row) as MaxRow, MAX(MPD_Column) as MaxColumn"; $query .= " FROM MPD_MapDescriptions"; $query .= " WHERE MPD_SCN_ID = " . $scenarioID;
$result = mysql_query($query) or die(mysql_error() . "<p>$query</p>Failed at (5a)"); $dbRow = mysql_fetch_array($result); $maxRow = $dbRow["MaxRow"]; $maxColumn = $dbRow["MaxColumn"]; $midRow = round($maxRow / 2); $midColumn = round($maxColumn / 2); unset($dbRow);
$QUADRANTS = array(); $QUADRANTS[1] = array(1,1,$midRow,$midColumn); //NW $QUADRANTS[2] = array(1,($midColumn + 1),$midRow,$maxColumn); //NE $QUADRANTS[3] = array(($midRow + 1),1,$maxRow, $midColumn); //SW $QUADRANTS[4] = array(($midRow + 1),($midColumn + 1),$maxRow,$maxColumn); //SE
srand ((double)microtime()*1000000); shuffle($QUADRANTS); //randomise where players 1-4 starts for each game
(I wish proboards would support the [php] tag, it is so much better than the all-green code display above, plus it retains formatting such as indents)
.
|
|
|
Post by sparrowhawk on Jul 14, 2004 7:43:59 GMT
Hmm. An upper case variable! Apologies to all purists and be assured that is has been changed ;D
|
|
merlin
Public Area Guest
Posts: 19
|
Post by merlin on Jul 14, 2004 10:05:08 GMT
Ok, how about a different approach....
Create a table with loads of starting points in... and then just run through the list. That is a global list, you could then shuffle the list when you get to the end...
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 14, 2004 10:20:58 GMT
How about an algorithm like this:
Randomise player numbers, take a random starting rotation R, and let N := 360 / no. of players.
for i = 1 to no. of players do r := a random rotation within N starting position i is then a random distance in the direction R + (i-1) * N + r from the centre of the map.
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 14, 2004 10:24:30 GMT
I don't do php, but if you need the mathematics, I can provide them.
|
|
|
Post by sparrowhawk on Jul 14, 2004 10:58:24 GMT
Thanks for the suggestions. I'll look into these once 0.2 is out, and may ask for your help then Matija.
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 14, 2004 17:39:36 GMT
I was intrigued, so I worked it out let n be the number of players, X and Y the dimensions of the map x0 := X / 2 ; x coordinate of the centre y0 := Y / 2 ; y coordinate of the centre R0 := random(2pi) ; starting rotation Rn := 2pi / n ; each player's 'slice' c := sqrt(sqr(x0) + sqr(y0)) ; we will use this to determine maximum possible distance from the centre for i = 1 to n do r := random(Rn) ri := R0 + (i-1) * Rn + r ; the angle of the starting position - we now need the distance if c * abs(cos(ri)) > x0 then dmax := x0 / abs(cos(ri)) else dmax := y0 / abs(sin(ri)) di := random(dmax) Sxi := trunc(x0 + di * cos(ri)) ; this are now coordinates of the i-th starting position Syi := trunc(y0 + di * sin(ri))
|
|
|
Post by sparrowhawk on Jul 15, 2004 7:23:09 GMT
Blimey Matija! What do you do when you want to relax then?! I'll give it a go post 0.3 release. I'll add a drop down to the new game 2 page that lets you chose your preferred method. Choices will be: - Quadrants - Segments (your method - let me know if there is a better description!) - Completely random (could throw up some very one sided games but does mean that you can't automatically assume where someone won't be (ie behind you in a corner of the map) Default will be whichever we all decide works best after some trial games (segments probably?)
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 15, 2004 8:06:48 GMT
Slices, perhaps. At least I imagine it as slices from an angular pie or gateau.
It could still lead to some very unbalanced starts, unless further mechanisms were incorporated. In fact, the Quadrants starting positions are just a subset of this one. Thus the advantage to the quadrants method is that here players would have absolutely no idea where their adversaries might be starting from.
|
|