Master Baboon The sea of the simulation

14Feb/096

Guess 2/3 game: sending data from Flash to a remote database

I wrote a simple game to learn how to store on and retrieve data from a server-side database. The rules are simple: you have to guess 2/3 of the average of the guesses of all the players. So, for example, if you think that the other players guessed on average 100, your guess should be 67. The 2/3 rule is there to avoid the trivial strategy of  submitting the same number over and over again. According to game theory, the game has a Nash equilibrium at 0, which in this case does not correspond to a rational strategy. Wikipedia has some information and links about the game. Give it a try:

Get Adobe Flash player

The score you see after submitting is the distance from your guess to the true 2/3 of the average. Since you get some information about your and others' score, it should be possible to find a strategy to win in a small number of trials... Let me know if you find one!

Communicating with the server

To implement the game, I created a MySQL table in a database on the server that is used to store the players' name and guess. The database is accessed by calling a server-side PHP script from the game Actionscript client.

The PHP script gets the player's information and stores it in the database; then it computes the 2/3 of the average of all entries, and returns the score and rank of the current player, along with the top scores in the database. The script receives the data as a HTTP request (the ?var1=value1&var2=value2 thing you see in many dynamical web pages), and returns an XML fragment.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
\n";
// top scores
while (($row = mysql_fetch_array($hit)) && ($currentrank==0 || $rank<=$ntop)) {
  if ($rank<=$ntop) {
    print "
\n";
    print "
\t{$row['name']}\n";
    print "
\t{$row['diff']}\n";
    print "
\n";
  }
  if ($row['time'] == $time) {
    $currentrank = $rank;
    $currentscore = $row['diff'];
  }
  $rank = $rank + 1;
}

// current score
print "
\n\t{$name}\n\t{$currentscore}\n";
print "


\n";

mysql_close();

?>

Calling the script from AS3 is relativelty easy. The remote call is done by a URLLoader object; the actual request is stored in a URLRequest object, and the request variables are wrapped in a URLVariables instance. I had an annoying problem with testing the code: for some reason, Flash always caches the requests. I looked around and it seems that the only workaround is to add a dummy variable to the request with a value that changes constantly, e.g., the current time.

This is the code for the communication with the server:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public function submitGuess(name:String, guess:uint, ntop:int):void {
    var request:URLRequest = new URLRequest("http://www.masterbaboon.com/php/guess23/guess23submit.php");
    var httpHeader : URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
    request.requestHeaders.push(httpHeader);

    // request variables: name of player, guess, number of top scores to return
    var vars:URLVariables = new URLVariables();
    vars.name = name;
    vars.guess = guess;
    vars.ntop = ntop;
    // this is to trick AS3 into not caching the URL request
    vars.nocache = Number(new Date().getTime());

    request.method = URLRequestMethod.GET;
    request.data = vars;

    // send to server and call loadingComplete when complete
    var loader:URLLoader = new URLLoader();

    // the results of the request is not returned immediately, but
    // we can monitor the COMPLETE event dispatched by the loader
    loader.addEventListener(Event.COMPLETE, loadingComplete);
    try {
        loader.load(request);
    } catch (e:Error) {
        trace("An error has occurred while communicating with the server.");
        trace(e);
    }
}

public function loadingComplete(e:Event):void {
    // this is how to access the data returned from the request
    data = XML(e.target.data);
    // switch frame
    gotoAndStop("highScoreFrame");
}

You're welcome to download the whole code.

[ad#adpost]