[ Jocelyn Ireson-Paine's Home Page | Try Traveller | Traveller source | Traveller for the student | About the design ]

Traveller PHP script

Every so often, people ask me how I call SWI-Prolog from PHP. I put up a script showing how I did this for the Spin SF plot-generator, and then someone asked how to preserve state throughout a session. So here is the script for my Traveller game, which does just that. The key here is my predicate step_and_display, which writes out both the output to be sent to the browser, and some state to be kept until the user's next command. The PHP script splits out the latter, then saves it in $_SESSION['game_state'].

The code follows:

<?php
session_start();
header("Cache-control: private"); 
//IE 6 fix; apparently it may not work without this.

session_register('game_state');
?>


<HTML>
<HEAD>
<TITLE>Traveller</TITLE>
</HEAD>

<BODY BGCOLOR=#ffffff>

[ <A HREF="/index.html">Jocelyn Ireson-Paine's Home Page</A>
| <A HREF="/traveller.html">Traveller source</A>
| <A HREF="/traveller_script.html">Traveller PHP script</A>
| <A HREF="/traveller/traveller.html">Traveller for the student</A>
| <A HREF="/traveller/design.html">About the design</A>
]

<CENTER>
<H1>Traveller</H1>
</CENTER>

<P>
Press the first button below to continue the current game, the second to
restart it, and the third to restart with a specified square and trader.
<TABLE WIDTH=100% BORDER>
<TR>
<TD><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="step">
    <INPUT TYPE=SUBMIT VALUE="Next"> 
   </FORM>
</TD>
<TD><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="restart">
    <INPUT TYPE=SUBMIT VALUE="Restart"> 
   </FORM>
</TD>
<TD><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="restart-new">
    <INPUT TYPE=SUBMIT VALUE="Restart"> 
    <SELECT 
NAME=trader><OPTION>trader</OPTION><OPTION>circler</OPTION></SELECT> 
       at square <SELECT NAME=start-square>
<OPTION VALUE="59">2, 2</OPTION>
<OPTION VALUE="9">2, 5</OPTION>
<OPTION VALUE="1">2, 12</OPTION>
<OPTION VALUE="58">3, 2</OPTION>
<OPTION VALUE="16">3, 4</OPTION>
<OPTION VALUE="10">3, 6</OPTION>
<OPTION VALUE="8">3, 11</OPTION>
<OPTION VALUE="2">3, 13</OPTION>
<OPTION VALUE="57">4, 2</OPTION>
<OPTION VALUE="15">4, 4</OPTION>
<OPTION VALUE="11">4, 6</OPTION>
<OPTION VALUE="32">4, 7</OPTION>
<OPTION VALUE="31">4, 8</OPTION>
<OPTION VALUE="30">4, 9</OPTION>
<OPTION VALUE="29">4, 10</OPTION>
<OPTION VALUE="7">4, 11</OPTION>
<OPTION VALUE="3">4, 13</OPTION>
<OPTION VALUE="56">5, 2</OPTION>
<OPTION VALUE="14">5, 4</OPTION>
<OPTION VALUE="12">5, 6</OPTION>
<OPTION VALUE="6">5, 11</OPTION>
<OPTION VALUE="4">5, 13</OPTION>
<OPTION VALUE="55">6, 2</OPTION>
<OPTION VALUE="13">6, 5</OPTION>
<OPTION VALUE="5">6, 12</OPTION>
<OPTION VALUE="54">7, 2</OPTION>
<OPTION VALUE="61">7, 8</OPTION>
<OPTION VALUE="62">7, 9</OPTION>
<OPTION VALUE="33">7, 12</OPTION>
<OPTION VALUE="53">8, 2</OPTION>
<OPTION VALUE="68">8, 4</OPTION>
<OPTION VALUE="60">8, 7</OPTION>
<OPTION VALUE="17">8, 12</OPTION>
<OPTION VALUE="52">9, 2</OPTION>
<OPTION VALUE="67">9, 4</OPTION>
<OPTION VALUE="25">9, 7</OPTION>
<OPTION VALUE="24">9, 11</OPTION>
<OPTION VALUE="18">9, 13</OPTION>
<OPTION VALUE="51">10, 2</OPTION>
<OPTION VALUE="66">10, 5</OPTION>
<OPTION VALUE="28">10, 6</OPTION>
<OPTION VALUE="26">10, 8</OPTION>
<OPTION VALUE="35">10, 9</OPTION>
<OPTION VALUE="34">10, 10</OPTION>
<OPTION VALUE="23">10, 11</OPTION>
<OPTION VALUE="19">10, 13</OPTION>
<OPTION VALUE="50">11, 2</OPTION>
<OPTION VALUE="27">11, 7</OPTION>
<OPTION VALUE="22">11, 11</OPTION>
<OPTION VALUE="20">11, 13</OPTION>
<OPTION VALUE="49">12, 2</OPTION>
<OPTION VALUE="63">12, 7</OPTION>
<OPTION VALUE="21">12, 12</OPTION>
<OPTION VALUE="48">13, 2</OPTION>
<OPTION VALUE="65">13, 5</OPTION>
<OPTION VALUE="64">13, 6</OPTION>
<OPTION VALUE="36">13, 12</OPTION>
<OPTION VALUE="47">14, 2</OPTION>
<OPTION VALUE="37">14, 12</OPTION>
<OPTION VALUE="46">15, 3</OPTION>
<OPTION VALUE="45">15, 4</OPTION>
<OPTION VALUE="44">15, 5</OPTION>
<OPTION VALUE="43">15, 6</OPTION>
<OPTION VALUE="42">15, 7</OPTION>
<OPTION VALUE="41">15, 8</OPTION>
<OPTION VALUE="40">15, 9</OPTION>
<OPTION VALUE="39">15, 10</OPTION>
<OPTION VALUE="38">15, 11</OPTION>
</SELECT> 
   </FORM>
</TD>
</TR>
<TR>
<TD COLSPAN=3><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="accounts">
    <INPUT TYPE=SUBMIT VALUE="Accounts"> 
   </FORM>
</TD>
</TR>
</TABLE>
</P>


<P>
<TABLE BORDER>
<TR>
<TD BGCOLOR=#FFCCFF>
<B>
<?php 
  $act = $_GET['act'];
  // Find out which button was pressed. Does the
  // user want to continue, retart, or restart with
  // parameters?
 
  // Now build an appropriate Prolog goal.
  //
  if ( $act == 'restart' ) {
    $goal = "step_and_display(1,trader)";
  }
  else if ( $act == 'restart-new' ) {
    $start_square = $_GET['start-square'];
    $trader = $_GET['trader'];
    $goal = "step_and_display($start_square,$trader)";
  }
  else if ( $act == 'accounts' ) {
    $accounts_file = tempnam( "/home/popx/www.j-paine.org_html/scratch/", "" );
    chmod( $accounts_file, 700 );
    $goal = "accounts(1,trader,$accounts_file)";
  }
  else {
    $game_state = $_SESSION['game_state'];
    if ( $game_state == "" ) {
      $game_state = "1";
    }
    // $game_state becomes either the state after the previous move,
    // or if none, the number of a starting square.

    $goal = "step_and_display($game_state,trader)";
  }

  $cmd = "nice -n15 /software/bin/pl -L128k -G128k -T128k -A128k -f /home/popx/traveller/traveller.pl -g \"$goal,halt\"";

  $output = shell_exec($cmd);
  // Build the Prolog command and, using shell_exec, get
  // the output as a string.

  list($english_state,$board,$prolog_state)= split ("==========", $output, 3);
  // Split output into an English description of the new 
  // state, a table displaying the board, and the new
  // state.

  $_SESSION['game_state'] = $prolog_state; 
  // Store the latter.
?> 

<P>
<?php
  echo $english_state;
  // First part of output.
?>
</P>

<P>
<?php
  if ( $act == "accounts" ) {
    $url = basename($accounts_file);
?>
    <A HREF="/scratch/<? echo $url ?>">Accounts as comma-separated-value file</A>
<?php    
  }
?>
</P>

<P>
<?php
  echo $board;
  // Second part of output.
?>
</P>

</B>
</TD>
</TR>
</TABLE>
</P>

<P>
Press the first button below to continue the current game, the second to
restart it, and the third to restart with a specified square and trader.
<TABLE WIDTH=100% BORDER>
<TR>
<TD><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="step">
    <INPUT TYPE=SUBMIT VALUE="Next"> 
   </FORM>
</TD>
<TD><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="restart">
    <INPUT TYPE=SUBMIT VALUE="Restart"> 
   </FORM>
</TD>
<TD><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="restart-new">
    <INPUT TYPE=SUBMIT VALUE="Restart"> 
    <SELECT 
NAME=trader><OPTION>trader</OPTION><OPTION>circler</OPTION></SELECT> 
       at square <SELECT NAME=start-square>
<OPTION VALUE="59">2, 2</OPTION>
<OPTION VALUE="9">2, 5</OPTION>
<OPTION VALUE="1">2, 12</OPTION>
<OPTION VALUE="58">3, 2</OPTION>
<OPTION VALUE="16">3, 4</OPTION>
<OPTION VALUE="10">3, 6</OPTION>
<OPTION VALUE="8">3, 11</OPTION>
<OPTION VALUE="2">3, 13</OPTION>
<OPTION VALUE="57">4, 2</OPTION>
<OPTION VALUE="15">4, 4</OPTION>
<OPTION VALUE="11">4, 6</OPTION>
<OPTION VALUE="32">4, 7</OPTION>
<OPTION VALUE="31">4, 8</OPTION>
<OPTION VALUE="30">4, 9</OPTION>
<OPTION VALUE="29">4, 10</OPTION>
<OPTION VALUE="7">4, 11</OPTION>
<OPTION VALUE="3">4, 13</OPTION>
<OPTION VALUE="56">5, 2</OPTION>
<OPTION VALUE="14">5, 4</OPTION>
<OPTION VALUE="12">5, 6</OPTION>
<OPTION VALUE="6">5, 11</OPTION>
<OPTION VALUE="4">5, 13</OPTION>
<OPTION VALUE="55">6, 2</OPTION>
<OPTION VALUE="13">6, 5</OPTION>
<OPTION VALUE="5">6, 12</OPTION>
<OPTION VALUE="54">7, 2</OPTION>
<OPTION VALUE="61">7, 8</OPTION>
<OPTION VALUE="62">7, 9</OPTION>
<OPTION VALUE="33">7, 12</OPTION>
<OPTION VALUE="53">8, 2</OPTION>
<OPTION VALUE="68">8, 4</OPTION>
<OPTION VALUE="60">8, 7</OPTION>
<OPTION VALUE="17">8, 12</OPTION>
<OPTION VALUE="52">9, 2</OPTION>
<OPTION VALUE="67">9, 4</OPTION>
<OPTION VALUE="25">9, 7</OPTION>
<OPTION VALUE="24">9, 11</OPTION>
<OPTION VALUE="18">9, 13</OPTION>
<OPTION VALUE="51">10, 2</OPTION>
<OPTION VALUE="66">10, 5</OPTION>
<OPTION VALUE="28">10, 6</OPTION>
<OPTION VALUE="26">10, 8</OPTION>
<OPTION VALUE="35">10, 9</OPTION>
<OPTION VALUE="34">10, 10</OPTION>
<OPTION VALUE="23">10, 11</OPTION>
<OPTION VALUE="19">10, 13</OPTION>
<OPTION VALUE="50">11, 2</OPTION>
<OPTION VALUE="27">11, 7</OPTION>
<OPTION VALUE="22">11, 11</OPTION>
<OPTION VALUE="20">11, 13</OPTION>
<OPTION VALUE="49">12, 2</OPTION>
<OPTION VALUE="63">12, 7</OPTION>
<OPTION VALUE="21">12, 12</OPTION>
<OPTION VALUE="48">13, 2</OPTION>
<OPTION VALUE="65">13, 5</OPTION>
<OPTION VALUE="64">13, 6</OPTION>
<OPTION VALUE="36">13, 12</OPTION>
<OPTION VALUE="47">14, 2</OPTION>
<OPTION VALUE="37">14, 12</OPTION>
<OPTION VALUE="46">15, 3</OPTION>
<OPTION VALUE="45">15, 4</OPTION>
<OPTION VALUE="44">15, 5</OPTION>
<OPTION VALUE="43">15, 6</OPTION>
<OPTION VALUE="42">15, 7</OPTION>
<OPTION VALUE="41">15, 8</OPTION>
<OPTION VALUE="40">15, 9</OPTION>
<OPTION VALUE="39">15, 10</OPTION>
<OPTION VALUE="38">15, 11</OPTION>
</SELECT> 
   </FORM>
</TD>
</TR>
<TR>
<TD COLSPAN=3><FORM METHOD=GET ACTION="/cgi-bin/traveller.php">
    <INPUT TYPE=HIDDEN NAME=act VALUE="accounts">
    <INPUT TYPE=SUBMIT VALUE="Accounts"> 
   </FORM>
</TD>
</TR>
</TABLE>
</P>

<P>
The program is one I've used in teaching Prolog. 
The source is <A
HREF="/traveller.html">here</A>; it's running under 
<A HREF="http://www.swi-prolog.org/">SWI-Prolog</A> and <A 
HREF="http://www.php.net/">PHP</A>.
You can see the PHP script
<A HREF="/traveller_script.html">here</A>.
</P>

<P>
<ADDRESS>1st November 2008</ADDRESS>
<P>

</BODY>
</HTML>

1st November 2008