Next: The Makefile
Up: A 2-player coordination game
Previous: Rules and Implementation
  Contents
  Index
/*
* game.c
* Copyright: Oliver Kirchkamp
* Date: 15. 1. 1998
* Project: A simple coordination game
* Purpose: Demonstration for WWW experiments
*
*/
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/file.h>
#include "gd.h"
#include "gdfonts.h"
#include "cgi-lib.h"
#include "html-lib.h"
#include <math.h>
#include <sys/stat.h>
#define PUSH_HEADER "HTTP/1.0 200 OK\nServer: Apache/1.2b6\n\
MIME-Version: 1.0\n\
Content-Type: multipart/x-mixed-replace;boundary=EOM\n\n\
--EOM\nContent-Type: text/html\n\n"
#define PUSH_HEADER_SANS_CONT "HTTP/1.0 200 OK\n\
Server: Apache/1.2b6\nMIME-Version: 1.0\n\
Content-Type: multipart/x-mixed-replace;boundary=EOM\n\n\
--EOM\n"
#define PUSH_BOUNDARY "\n--EOM\n"
#define PUSH_CONT "Content-Type: text/html\n\n"
#define PUSH_END "\n--EOM"
#define push_header printf(PUSH_HEADER_SANS_CONT)
#define push_start_page printf(PUSH_CONT)
#define push_end_page printf(PUSH_BOUNDARY);fflush(stdout)
#define myfile "../dat/file"
llist cgi_entries;
int number;
/***********************************/
/* goodbye */
/***********************************/
void goodbye (char *message) {
push_start_page;
h4 (message);
push_end_page;
exit (0);
}
/***********************************/
/* call for strategy */
/***********************************/
int call_for_strategy () {
/* start with a heading: */
h1 ("Welcome to the game");
printf ("You will play a game against a single opponent. ");
printf ("Both of you will enter a number between 0 and 100. ");
printf ("Your payoff will be twice the minimal number ");
printf ("minus the number that you have chosen. The same holds ");
printf ("for your opponent.<p>");
/* we want to transmit some data, this can best be done with a form,
* METHOD can either be POST or GET, we take POST, since it may
* send more data,
* ACTION is the script that we want to call with the form,
*/
printf ("<FORM METHOD=POST ACTION=nph-game \
ENCTYPE=application/x-www-form-urlencoded>");
printf ("Please enter a number between 0 and 100: ");
printf ("<INPUT TYPE=TEXT NAME=Number>");
printf ("<INPUT TYPE=SUBMIT NAME=I_DID_IT VALUE=Continue>");
printf ("</FORM>");
push_end_page;
exit (0);
}
/***********************************/
/* read_the_file */
/***********************************/
void read_the_file (int *lines, int *smallest_number,
long int* opponent) {
FILE *number_file;
int any_number;
long int other_process;
*opponent = 0; /* we do not know her yet */
*lines = 0;/* no lines read at all */
/* attempt to open a file for reading */
number_file = fopen (myfile,"r");
/* if we could not open the file, say goodbye */
if (! number_file)
goodbye ("could not read from my file");
/* read all entries in the file */
while (EOF != fscanf(number_file,"%d,%ld",&any_number,
&other_process)) {
/* initialise with the highest possible value */
if (*lines % 2 == 0)
*smallest_number = 100;
if (any_number < *smallest_number)
*smallest_number = any_number;
/* if we find our opponent's pid, remember her */
if (other_process != getpid())
*opponent = other_process;
++(*lines);
}
fclose (number_file);
}
/***********************************/
/* print_results */
/***********************************/
void print_results () {
int lines;
int smallest_number;
long int opponent;
read_the_file (&lines,&smallest_number,&opponent);
push_start_page;
printf ("The smallest number was %d<P>",smallest_number);
printf ("Your number was %d<P>",number);
printf ("Your Payoff is, thus, <B>%d</B><p><hr>",
2*smallest_number-number);
call_for_strategy () ;
exit (0);
}
/***********************************/
/* wait for the other */
/***********************************/
void wait_for_the_other () {
push_start_page;
h4("Please wait for your opponent");
printf ("%ld",(long int) getpid());
push_end_page;
/* wait for a signal... */
signal (SIGUSR1, &print_results);
/* in the meantime, first have a nap */
sleep (3600);
/* if nothing happens, exit */
exit (0);
}
/***********************************/
/* write_number_into_a_file */
/***********************************/
void write_number_into_a_file () {
FILE *number_file;
/* translate the string "Number" into an integer "number" */
sscanf (cgi_val(cgi_entries,"Number"),"%d",&number);
/* check whether number is within 0 and 100 */
if (number>100)
number = 100;
if (number<0)
number = 0;
/* attempt to open a file for writing
(append to the end of the file) */
number_file = fopen (myfile,"a");
/* if we could not open the file, say goodbye */
if (! number_file)
goodbye ("could not write into my file");
/* wait until we are the only ones to write into that file */
flock (fileno (number_file),LOCK_EX);
/* write our number, and our identity into the file
* as identity we take our pid */
fprintf (number_file,"%d,%ld\n",number,(long int) getpid());
/* unlock and close the file, such that others
will be able to write there */
fflush (number_file);
flock (fileno (number_file),LOCK_UN);
fclose(number_file);
}
/***********************************/
/* evaluate_strategy */
/***********************************/
void evaluate_strategy () {
/* define some variables that we will use lateron */
int lines;
int smallest_number;
long int opponent;
write_number_into_a_file ();
/* now read, what is actually in the file, in order to determine
whether I am the first or the last */
read_the_file (&lines,&smallest_number,&opponent);
if (lines % 2 == 1)
wait_for_the_other ();
else {
/* send her a signal, as long as she exists */
if (opponent)
kill (opponent,SIGUSR1);
print_results ();
}
}
/***********************************/
/* main */
/***********************************/
int main () {
push_header;
/* read, whatever was sent to us from a form */
read_cgi_input (&cgi_entries);
/* check, whether somebody sent us a number */
if (cgi_val(cgi_entries,"Number"))
evaluate_strategy ();
/* otherwise, invite playing a game */
else {
push_start_page;
call_for_strategy ();
}
return (0);
}
Next: The Makefile
Up: A 2-player coordination game
Previous: Rules and Implementation
  Contents
  Index
Oliver Kirchkamp