                        The Tic-Tac-Toe System
                        ======================

Overview
--------

The Tic-Tac-Toe system provides a framework for writing automatic
Tic-Tac-Toe players and interfaces to human players, and for letting
these players get together from different networked machines to play
games.


Module Structure
----------------

The whole project is described in the workspace tttws.  The read
package for the whole system is ttt.

The system consists of the following modules:

* tttmgrs: This module defines the ttt.<game> structure which holds
  all the state information relevent for a game.  This private
  structure is managed by the module tttmgre.

* tttmgre: This module implements the game rules and is responsible
  for managing games and calling the protocol defined for a player
  correctly.  The main entry points in this module are ttt.start-game
  and ttt.do-game-turn.

* tttserve: This module implements the tic-tac-toe network server.
  After starting the server in a Talk process by calling
  start-ttt-server, different players can connect to the server
  process and play games.  Whenever two players have connected, a game
  is started between them.

* tttcliente: This module implements the client side of a networked
  tic-tac-toe game.  It is responsible for taking a taking a local
  player object and informing the server process of its existence, and
  then transmitting the protocol data to the local player through a
  socket.  The main entry point is submit-ttt-player, which takes a
  local player object and asks the server to let it play.

* tttplays: This module implements the initial hierarchy of simple
  player classes, rooted in the abstract class ttt.<player>. The
  available concrete subclasses include:
    - ttt.<random-player>: A player who responds to the protocol by
      choosing an arbitrary legal move.  This player has no brains at
      all.  Make a random player by calling ttt.make-random-player.
    - ttt.<server-player>: A proxy player which exists only in the
      server process and is used to communicate the protocol data
      through a socket between a real player in a distant process and
      the local game manager.  The distant player can be of any type.

* tttplaye: This module implements the player protocol methods for the
  various player classes defined in tttplays.  This module has no
  useful entry points; you should merely make random players by
  calling ttt.make-random-player.

* ttthplays: This module defines the ttt.<hplayer> structure which is
  a player who interfaces with a human user through a grahic user
  interface written in ILOG VIEWS.

* ttthplaye: This module implements the human interface player GUI.
  The main entry point is the function make-human-player.

* tttutils: This module defines a number of utility functions useful
  throughout the tic-tac-toe system.


Player Protocol
---------------

Extending the system for a new type of automated player involves two
steps:

1. Define a new subclass of ttt.<player> for your player.
2. Define methods on the player protocol generic functions to
   implement the behavior of your new class.  The most important of
   these methods is ttt.ask-move, which must return a legal move in
   the game.  This is where the intelligence (or lack thereof) of your
   player will reside.

In the player protocol, several pieces of information are represented
by common Talk types to facilitate transfer across the network.  Here
they are:

* Players' names are represented as strings.

* A tic-tac-toe board state is represented as an 8 character string,
  each character representing one square in the board.  The #\x
  character represents a square occupied by the X player; #\o by the O
  player; and #\. represents an unoccupied spot.  Here is how the
  board is labeled:

         0 | 1 | 2
        ---+---+---
         3 | 4 | 5
        ---+---+---
         6 | 7 | 8

  Thus, the string ".xo...o.x" represents the board:

           | X | O
        ---+---+---
           |   | 
        ---+---+---
         O |   | X

* A move is represented by an int in the range [0..8], which denotes a
  position in the board as described above.

* A set of moves is represented by a list of ints.  This
  representation is used to transmit the legal moves for a turn and
  the winning list of three positions at the end.

Here is a detailed description of each of the generic functions in the
player protocol.  All of these generic functions except ttt.ask-move
have a default method which will suffice for many new types of players.

.tell-start-game player other-name play-char
   This function is called at the beginning of a game to inform
   each player of the name of his or her adversary (a string) and
   the side on which he's going to play (a character, either #\x
   for the X player or #\o for the O player).  The default method
   merely prints out this information.

.tell-move player other-name move new-state
   This function informs the player that the other player has made a
   move.  The new state of the game --- a string --- is passed as
   new-state.  The return value is ignored.  The default method prints
   out the new board.

.tell-winner player winner-name positions
   This function informs the player that the game is over, and that
   winner-name is the name --- a string --- of the winning player.  If
   winner-name is (), the game is a tie.  Positions is a list of three
   moves indicating the winning combination.  This is used, for
   example, by the human interface player to light up the positions at
   the end of the game.  The return value is ignored.  The default
   method prints a congratulatory message.

.ask-move player state legal-moves
   This function indicates to the player that it is his or her turn.
   The argument state --- a string of 9 chars --- is the current board
   state, and legal-moves is a list of possible moves from which the
   player must choose.  The return value must be one of these moves,
   or the manager signals an error.  There is no default method for
   this generic function.  The random player chooses a random element
   of legal-moves, while the human interface player waits for the
   player to click on a square corresponding to a legal move.  This
   method is the most important to write for a new player; it should
   implement an intelligent algorithm to select a good move from
   legal-moves.

.ask-player-name player
   This function should return the name of the player, a string.  The
   default method calls the accessor function ttt.player-name to
   retrieve the name given when the player is created.

.tell-game-error player msg rest: args
   This function is called by the game manager when an error has
   occurred, such as another player selecting an illegal move.  The
   msg argument is a printf format string, and the args fill in the
   format statements.  The default method prints the message using
   efprintf on the tty.

.stop-ttt-player player
   This function is called when a player is to stop playing, typically
   after an error or at the end of a game.  The default method just
   prints a message.

.pprintf player msg rest: args
   This utility function is called by some others to print out
   informational messages during the course of a game.  By default, it
   simply prints out the message on the tty, but it could be redefined
   to print to a file, or to pop an asker widget, for example.


Extension
---------

A sample extension player can be found in the modules tttlplays.t and
tttlplaye.t.  These modules implement a learning player, who remembers
what it plays for a given state and whether it led to success or
failure.
