/* * 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); }