# Captive Game Server

Updated 2025-09-13 for Game Server ver 8.031

## Test the Rule Game

To play a game without installing the CGS, CLICK HERE!

## What is the Captive Game Server?

The Captive Game Server (CGS) is a small Java application that contains the same game engine as the Web-based Rule Game Server, but does not have a SQL database, does not write transcript files, and does not communicate with clients using HTTP. It can be used by a Machine Learning or AI researcher (in particular, a participant in the The Machine Learning Challenge (MLC)) who wants his or her ML program to learn how to play the Game of Hidden Rules (GOHR, a.k.a. the Rule Game) as a counterparty for his ML program to play with.

The Captive Game Server can be run in two ways: pipe-based and socket-based.

The pipe-based CGS is to be started, as a child process, by the client program (such as a machine learning (ML) program that wants to play a game), and communicates with the client using standard input and standard output (i.e. UNIX pipes). For testing purposes, it can also be run directly from the console by a person who wants to play the game himself, as a human player.

Since the Captive Game Server is run by the owner of the ML program, the latter has complete control how many times it's run, and with what data. It is a complete "honor system", so to speak. Thus, it is up to the owner of the ML program to keep track of how the CGS is used, how many game episodes were played, and how many moves were attempted in each episode.

For the convenience of some application, we also have the socket-based version of the CGS, discussed later in this document, which communicates with clients over sockets, rather than a pipe.

## The Rule Game / Game of Hidden Rules

More information on the Rule Game (a.k.a. the Game of Hidden Rules, GOHR), is provided in the following documents:

- The main concepts of the Rule Game.
- About the syntax of rule set files (GS 3.*)
- About the syntax of rule set files: GS 5.* extension
- Bucket expression arithmetic: more about the expressions used to compute the accepting bucket number(s)
- Try out your arithmetic expressions!
- Using custom colors and shapes in Game Server 2.*
- Image-and-property-based objects in Game Server 3.*
- Composite image objects, available in Game Server 4.009.

## The Machine Learning Challenge (MLC)

For further information on the Machine Learning Challenge (MLC), see:

- MLC Participant's Guide
- MLC Participant's Dashboard (submit results here; nickname password required -- obtain it through the article review platform, or, after publication, from one of the authors )

## Installation

If you're one of our own team members, and use the CGS on a server where it's already installed, you can safely ignore this section. But if you are installing the CGS on your own machine (especially at a different institution), please follow the instructions below to obtain the Captive Game Server distribution and the necessary third-party files.

### Main prerequisites

We are normally using the CGS on Linux machines, but if you want, you probably can install it on a MacOS or MS Windows machine as well, likely with some minimal changes to the shell scripts used to run it.

You need to have a Java Runtime Environment (JRE) (i.e. the system for running pre-compiled Java code) installed on your machine. Type `which java` on your console to see if you have one already; if you don't, you can get one from Oracle (How do I install Java?) or from OpenJDK (How to download and install prebuilt OpenJDK packages).

Our shell scripts are written in `csh`, so your system should have `csh` installed. (Most Linux / UNIX system already have, and if yours don't, you should be able to easily install it). Alternatively, you can re-write the scripts for your favorite shell (`sh, bash, ksh,` whatever).

### Choosing a directory

You can install the Captive Game Server anywhere on you computer. For the rest of the discussion, let's assume that you have decided to install it under ~/captive

### Third-part JAR files

(This section is not needed, since since Feb 2026 the third-party zip files are included into captive.zip)

You need to obtain a set of third-party JAR files that are used for working with JSON-format data (a "JAX-RS RI bundle"). This is how:

- You can download a file such as jaxrs-ri-2.31.zip, or a more recent version. (To do that, you can start from e.g. https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -Jersey Bundles JAXRS RI , clicking on a version number such as `3.1.0-M2`, and then, in a page such as https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri/3.1.0-M2 , clicking on `View all`, you get to a directory listing such as org/glassfish/jersey/bundles/jaxrs-ri/3.1.0-M2. In that page, you choose a ZIP file, such as `jaxrs-ri-3.1.0-M2.zip`).
- Unpack it on your machine under `~/captive`:

      	cd ~/captive
      	unzip jaxrs-ri-3.1.0-M2.zip

  This will create the directory `~/captive/jaxrs-ri`, with the JAX-RS stuff in it.

### Download and install CGS

Download a recent version of CGS from our server's Download Area. Choose a file with a name that indicates it's the most recent version, e.g. `captive-5.001-2022-05-26.zip`, or whatever you see. Unzip it under `~/captive`:

    	cd ~/captive
    	unzip ~/captive-5.001-2022-05-26.zip

This will create the directory `~/captive/game`, with all the CGS stuff in it.

## Sample data

To play with the CGS, you need to tell it what game to play. This is done by means of giving it some experiment control files: at the very least, a rule set file, and possibly some other files as well.

If you're a UWM or Rutger team member working on a machine such as `sapir`, you have access to the full set of our experiment control files in `/opt/w2020/game-data` (or another directory, such `/opt/tomcat/game-data`, as per the variable `FILES_GAME_DATA` in the master config file).

If you are running the CGS on your own machine, but you have also installed the web-based Game Server on that machine, you have the experiment control files in the same or similar location as well (its location may be overridden by the paramter `FILES_GAME_DATA` in the master config file.

Otherwise, you can use a smaller set of sample experiment control files that came with the CGS distribution; they are found in `~/captive/game/game-data`.

## Starting the Captive Game Server

The following assumes that you have installed the CGS as described above, in `~/captive`. If it was installed elsewhere, adjust the commands as appropriate.

The CGS can play one game at a time. An easy way to choose a game is to provide the CGS with a game rule file (a few of which can be found in `~/captive/game/game-data/rules/` or `~/captive/game/game-data/rules/`, as the case may be) and the initial number of pieces.

To use CGS, you need to add the directory in which your Java interpreter (`java`) is installed (such as `/opt/jdk-14.0.2/bin`, on `sapir`) into your `PATH`. Alternatively, you can modify the shell scripts mentioned below, so that they use `/opt/jdk-14.0.2/bin/java` rather than just `java`.

You can run the CGS from the command line as follows, with a `csh` script:

    ~/captive/game/captive-full.sh ~/captive/game/game-data/rules/rules-02.txt 8

In this example, you will start a session using the rule description from the specified file; each episode will use a random initial board with 8 pieces. During the session, you can play one or several episodes.

During the session, you will be able to type commands on the console, and the program will send the output to your screen. Type HELP to see the list of command, or EXIT to exit.

To use the CGS with your ML program, use the standard mechanism for spawning a child process, starting the script (captive-full.sh, captive-standard.sh, or captive-brief.sh), or the underlying Java program, as a child process from your program, with appropriate command-line arguments. You can capture the CGS's standard input and standard output via pipes, and communicate with it via writing into one pipe and reading from the other.

### Command-line option format

A number of options (name-value pairs) will be discussed below. For all of them, there are two alternative ways of passing them to the CGS, e.g.

        java -Dlog=foo.csv edu.wisc.game.engine.Captive ....

or

        java edu.wisc.game.engine.Captive log=foo.csv ....

The latter format is more convenient if you are passing the options through a shell script, e.g.

        ./captive-full.sh log=foo.csv ....

Command-line parameters: specifying the rule set and the initial board

The command line arguments for the scripts such as `captive-full.sh` are the same as for the underlying Java program, `edu.wisc.game.engine.Captive`. These arguments are used to specify, directly or indirectly, two things:

- The rule set to be used in all episodes of the session.
- The initial boards used in each episode.

There are several ways to provide this information, as illustrated below. In examples 1 thru 6, the first argument is the rule set file, specified as either a relative path (relative to the current directory), or an absolute path; it is followed by arguments specifying the initial board(s) for the session's episodes, in one of several ways. In example 7, the first argument is a trial list file, which contains information that both specifies the rule set and the initial board generation process.

In Game Server 2.*, the designers of human-subject experiments have a wide choice of experiment plan structures. Each parameter set in their trial lists may define a 6-paramter random board generator (specifying ranges of the number of pieces, the number of shapes, and the number of colors), with legacy or custom colors and shapes. Alternatively, a parameter set may define a sequence of predefined boards. Whichever structure the the parameter set has, using one of the methods described above will ensure that the captive server uses exactly the same random board generation process as is used by web-based Game Server in the human-subject experiments.

#### 1. Specify a pre-defined board file identified by name

    cd ~/captive/game
    ./captive-full.sh game-data/rules/farthest.txt game-data/boards/four-corners.json

If you do that, every episode in your session will start with the same identical initial board.

#### 2. Specify only the number of pieces, as a single number

    ./captive-full.sh game-data/rules/farthest.txt 3

In this example, every episode will start with a random board with the same number (3) pieces. The shapes and colors of each piece will be selected independently from each other from the entire set of shapes and colors available, which means that the number of shapes and colors will vary in each episode over the entire possible range.

#### 3. Specify only the number of pieces, as a single number or a range

    ./captive-full.sh game-data/rules/farthest.txt 2:4

In the above example, for each episode the number of pieces will be selected randomly, with a uniform distribution, from the speciified range, meaning that, on average, one-third of all initial boards will have 2 pieces, one-third will have 3, and one-third will have 4.

#### 4. Specify the number of pieces, the number of shapes, and the number of colors, as single numbers

     ./captive-full.sh game-data/rules/farthest.txt 5 2 3

In the above example, every initial board will have 5 pieces, with exactly 2 distinct shapes and 3 distinct colors

#### 5. Same as the above, but with using ranges for any of the three quantities.

Ranges and single numbers can be combined in arbitrary ways; essentially, a single number n is equivalent to the range n:n. E.g.

    ./captive-full.sh game-data/rules/farthest.txt 5 1:3 3:4

In the above example, every initial board will have 5 pieces, with 1, 2, or 3 distinct shapes (with equal probability) and 3 or 4 distinct colors.

When using ranges, make sure that the upper bound of range of the number of shapes the upper bound of the range of the number of colors do not exceed the lower bound of the range of the number of pieces. Otherwise, the random board generator may be occasionally faced with an impossible task of creating a board which has more distinct colors or shapes than it has pieces!

When you specify the random boad generation model in this way, the random board generator works in exactly the same way when you provide the parameters for the same Six-parameter distribution in a trial list file for human player experiments.

#### 6. Same as the above, but with custom shapes and/or custom colors.

To specify the sets from which colors and/or shapes will be drawn by the initial board generator, you can add additional parameters `colors=...` and/or `shapes=...` to the command line. The values of the parameters are semicolon-separated lists of colors and/or shapes, respectively. Make sure to use single quotes as shown below, since semicolons would be interpreted by the UNIX shell as command separators otherwise.

    ./captive-full.sh /opt/w2020/game-data/rules/arrows/rule-01.txt 3 2 2 'colors=red;pink' 'shapes=arrows/arrow-up-left;arrows/arrow-up-right;arrows/arrow-down-right;arrows/arrow-down-left'

One is allowed to use `*` to mean "use all shapes for which SVG files exist in the appropriate subdirectory of the main shapes directory". Thus, `'shapes=arrows/*;weather/*'` is equivalent to listing every shape from `/opt/w2020/game-data/shapes/arrows` and `/opt/w2020/game-data/shapes/weather`

If you're using custom shapes and/or custom colors, it is necessary that a list of colors and a set of shapes SVG files are found at the appropriate locations under `/opt/w2020/game-data`, as explained in the document Using custom shapes and colors in Rule Game Server 2.*. If you're running your Captive Game Server on `sapir` (the server used for the human subjects), and are playing a game that human subjects are already playing, then you're all set, because the human-player experiment team has already set up the necessary files in `/opt/w2020/game-data`. If you're running your Captive Game Server on another host, you may choose to create a copy of sapir's `/opt/w2020/game-data` directory with control files on your host, by checking out the experiment control files from the GitHub repository. Alternatively you can use `~/captive/game/game-data` as you control file directory.

If the root of your server data directory is somewhere else than in `/opt/w2020/game-data` directory, you can specify this by an additional parameter on the command line. This can be specified with e.g. `-inputDir ~/captive/game/game-data` as a parameter to a script such as `captive-full.sh`, or with `-DinputDir=~/captive/game/game-data` as a parameter to `java` in your own shell script. (Alternatively, the same effect can be achieved by setting the value of the variable `FILES_GAME_DATA` in the master config file).

#### 7. Use a trial list file

This is the easiest way to emulate the behavior of the web-based Game Server (with which humans play). To do this, you can specify a trial list file and the (1-based) row number, e.g.

    ./captive-full.sh /opt/w2020/game-data/trial-lists/vmColorTest/trial_1.csv 1

The CGS figures the file type based on the extension: the ".csv" extension means you are providing a trial list file, while the ".txt" extension (as in items 1 thru 6, above) refers to a rule set file.

Any of the valid trial list files prepared by our human-subject experiment team can be used with the CGS. In particular, this is a good way to play games that involve image-and-property-based objects.

To decide which games you want to play, you may ask knowledgeable PIs about various trial list files that can be found in the trial list directory, `/opt/w2020/game-data/trial-lists` on sapir.

The CGS will read the trial list file and extract the parameter set with the specified number. It will then create a game generator with the same parameters that the web-based Game Server would use when running on that parameter set; depending on the parameter set, that may involve random initial boards (with appropriate shapes, colors, and number of pieces) or predefined initial boards. As you play more episodes (starting each episode, after the first one, with the `NEW` command), the CGS will generate a sequence of initial boards in the same way as a web-based Game Server would, i.e. eiher randomly or by following a prescribed sequence of predefined boards. As in the web-based Game Server, the rule set specified in that parameter set will be used in each episode.

Since the trial list file implicitly refers to files in various directories under the server data directory (by default, `/opt/w2020/game-data`), you must either have that directory, with all relevant files, on your computer, or use the `-inputDir` parameter on the command line, just as in Example 6 above.

This technique for starting the CGS is the most appropriate one for games that involve Image-and-property-based objects or Composite image objects, because to play these games the server, besides having the rule set file, needs to know what kind of objects can be used as game pieces on the board.

#### 8. Combine a rule set file and a modifer file

Since Captive Game Server 5.003, it is possible to combine a rule set file with a "modifier file", which is like a trial list file, but only has columns for the parameters you need for the initial board generation. One can call it a pro forma trial list file. (If you are also configuring games for human players on the web-based Game Server, you will realize that this is very similar to the technique knowns as the R:-type dynamic experiment plan in that space).

The syntax is, you put

        R:ruleSet:modifier

as the main argument on your command line. Both ruleSet and modifier can be specified as absolute file paths (i.e. starting with a `/` or with a `~`). Alternatively, you can use the `inputDir` parameter to specify the root input data directory; if you do that, the ruleSet and modifier can be specified as relative paths, relative to the `rules` and `modifiers` subdirectories of the input data directory.

Here's an example, which uses a sample rule set file (`game-data/rules/MLC/BMK/colOrd_nearby.txt`) and a sample modifier file that we distribute for the The Machine Learning Challenge (MLC) participants:

      cd ~/w2020/game
      ./captive-full.sh inputDir=game-data R:MLC/BMK/colOrd_nearby.txt:MLC/BMK/bmk.csv

#### 9. Train/test: prohibiting or enforcing certain board properties when using the 6-parameter distribution

Based on a discussion with Paul on March 8, 2023, a new feature has been introduced in the CGS starting from version 6.010. It is now possible to run the CGS with the usual 6-parameter random board generator whose behavior is constrained in the following way:

- The CGS is aware of whether a given episode is played in the "training mode" or "testing mode".
- An additional "condition file" is provided, which contains a number of predicates ("conditions") that may apply to game pieces. (E.g. Condition 1 is "the game piece is located in positions 31 or 36"; Condition 2 is "the game piece is red"; Condition 3 is "the game piece is a square").
- If the episode is played in the training mode, then the board generator ensures that no game piece on the board satisfies any of the specified conditions. (In the above example, the board is guaranteed to have no squares, no red game pieces, and cells no. 31 and no. 36 are guaranteed to be empty).
- If the episode is played in the testing mode, then the board generator ensures that at least one game piece on the board satisfies at least one of the specified conditions. (In the above example, the board is guaranteed to either have a square, or a red game pieces, or a game piece in cells no. 31 or no. 36. The board, of course, may satisfy several conditions at once -- e.g. have a black triangle in cell no. 31, and red square somewhere else -- but is not required to do so).

Note that the sets of the allowed training-mode boards and of the allowed test-mode boards are complementary; in other words, each board that may be generated under the current parameter settings is either a legal training board, or a legal testing board, but it may never be both.

Specifying the conditions. The conditions are described by the so-called "condition file", whose format (although not semantics) are similar to that of rule set files. (For detailed guide on the rule file syntax, see rule file syntax in GS 4.*, and how it is extended in GS 5.*). For example, the set of three conditions desribed in the example above can be specified by the condition file that looks as follows:

        (pos:[31,36])
        (color:red)
        (shape:square)

Note that you must put one condition per line, but a condition may consist of multiple atoms. Thus the above file, with each condition made out of a single atom, prohibits (in the training mode) all red pieces and all squares. If, on the other hand, you have a condition line with multiple atoms, e.g. in the following file with two conditions:

        (pos:[31,36]) (shape:circle)
        (color:red) (shape:[square,triangle])

then you are prohibiting (in the training mode) circles (but no objects of other shapes) in cells no. 31 and 36, and you are prohibiting red squares and red triangles. In the testing mode, all boards will have either at least one circle in cell no. 31 or 36, or at least one red square or red triangle.

Sample condition files:

- `game-data/cond/vm/cond-01.txt, game-data/cond/vm/cond-02.txt`. (They are in the main code-and-sample-data repository, deployed under ~vmenkov/w2020/game on sapir, not in the main game data repository).
- `/opt/w2020/game-data/cond/vm/top-left-quarter.txt`, `/opt/w2020/game-data/cond/vm/outside-of-top-left-quarter.txt` (in the main game data repository). These are purely position-based conditions.

Costs: Using conditions may expensive, as they generlly are processed quite inefficiently: the board generator simply keeps creating random boards (without taking conditions into considerations) until a board happens to be produced that satsifies the conditions. Since ver. 7.008, more efficient processing is used for purely positon-based conditions; these are taken into account directly during the creation of the boards.

Specifying the training or test mode. To run the CGS starting in the training mode, you need to include `condTrain=conditionFileName.txt` on the command line, for example

          ./captive-full.sh condTrain=game-data/cond/vm/cond-01.txt game-data/rules/farthest.txt 5 1:3 3:4

All boards then will have no game pieces satisfying any of the listed conditions.

To run the CGS starting in the testing mode, you need to include `condTest=conditionFileName.txt` on the command line, for example

          ./captive-full.sh condTest=game-data/cond/vm/cond-02.txt game-data/rules/farthest.txt 5 1:3 3:4

All boards then will have at least one game piece satisfying at least one of the listed conditions.

If the CGS has been started in the training mode, the ML program can issue the command `COND test` to switch to the testing mode. It is most convenient to issue this command right before the `NEW` command of your first testing episode. Once the mode has been switched, the CGS will change its behavior accordingly, i.e. on all subseqent `NEW` commands it will generate boards with some game pieces satisfying some of the listed conditions, rather than boards in which no piece satisfies any condition.

Example.

    vmenkov% ./captive-full.sh condTrain=/opt/w2020/game-data/cond/vm/top-left-quarter.txt /opt/w2020/game-data/rules/FDCL/basic/ccw.txt 5 1:3 3:4
    6 0 0
    # Hello. This is Captive Game Server ver. 7.007. Starting a new episode (no. 1)
    {"id":0,"value":[{"id":0,"color":"BLACK","shape":"SQUARE","x":1,"y":4,"buckets":[0,1,2,3]},{"id":1,"color":"RED","shape":"CIRCLE","x":2,"y":4,"buckets":[0,1,2,3]},{"id":2,"color":"YELLOW","shape":"SQUARE","x":3,"y":4,"buckets":[0,1,2,3]},{"id":3,"color":"BLUE","shape":"SQUARE","x":1,"y":5,"buckets":[0,1,2,3]},{"id":4,"color":"RED","shape":"CIRCLE","x":2,"y":5,"buckets":[0,1,2,3]}]}
    #---+------------------------------
    # 6 |   .    .    .    .    .    .
    # 5 | (g#) (rO)   .    .    .    .
    # 4 | (b#) (rO) (y#)   .    .    .
    # 3 |   .    .    .    .    .    .
    # 2 |   .    .    .    .    .    .
    # 1 |   .    .    .    .    .    .
    #---+------------------------------
    #   |   1    2    3    4    5    6
    COND test
    # positionMask=PositionMask(atLeastOnePieceMustBeHere=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,22,23,24,28,29,30,34,35,36])
    # OK, cond=test
    NEW
    #(globalCounter=1) (-1,*,*,[; ],[0,1,2,3])
    #(globalCounter=-1) (-1,*,*,[; ],[[{p ADD_OP.- 1}]])
    6 0 0
    # Hello. This is Captive Game Server ver. 7.007. Starting a new episode (no. 2)
    {"id":0,"value":[{"id":0,"color":"YELLOW","shape":"CIRCLE","x":5,"y":1,"buckets":[0,1,2,3]},{"id":1,"color":"BLACK","shape":"CIRCLE","x":2,"y":2,"buckets":[0,1,2,3]},{"id":2,"color":"RED","shape":"SQUARE","x":4,"y":3,"buckets":[0,1,2,3]},{"id":3,"color":"BLUE","shape":"SQUARE","x":2,"y":4,"buckets":[0,1,2,3]},{"id":4,"color":"BLACK","shape":"STAR","x":2,"y":5,"buckets":[0,1,2,3]}]}
    #---+------------------------------
    # 6 |   .    .    .    .    .    .
    # 5 |   .  (b*)   .    .    .    .
    # 4 |   .  (g#)   .    .    .    .
    # 3 |   .    .    .  (r#)   .    .
    # 2 |   .  (bO)   .    .    .    .
    # 1 |   .    .    .    .  (yO)   .
    #---+------------------------------
    #   |   1    2    3    4    5    6

Note: If you specify conditions that are impossible to fulfill (e.g. prohibiting red and black pieces while requiring that each board contains pieces of at least 3 colors), the CGS won't detect this problem automatically. Instead, it will sit in a tight loop for a while, and then will terminate, with an error message going to its `stderr`. Thus before letting your ML program to play with the CGS using a particularly involved set of conditions, you may do well by testing the board generation parameters and the condition file, by playing at least one training episode and at least one testing episode from the command ine. (You don't even need to play the episode to the end; just make sure that a board is produced for you!)

#### 10. "Crowded boards": allowing multiple game pieces in one cell.

Historically, all boards in Rule Game have at most one game piece per cell. However, since GS 8.000, boards with multiple game pieces per cell (so called "crowded boards") are allowed as well. You can allow the Captive Game Server's random board generator to put multiple pieces into a cell by adding the option

        crowded=true

to the command line.

You can also use crowded boards as predefined initial boards.

### Specifying the random generator seed

Starting in ver. 1.026, it is possible to specify the seed of the random number generator, so that the same random boards would be generated on repeated runs. To do that, insert `-Dseed=N` (where N is a positive integer) into the Java command found in a script such as `captive-full.sh`, or used during the child-process spawning in your ML application. For example, you can modify the last line of this script to look as follows:

      java -Dseed=1 -Doutput=FULL edu.wisc.game.engine.Captive  $argv[1-]

It is also possible to specify the seed on the command line as follows:

     ./captive-full.sh /opt/w2020/game-data/rules/MLC/vm/test-05.txt 3 seed=5

Passing the seed value `0` will start the random number generator with a random seed (i.e. it will produce a different sequence of random numbers on different runs).

### Generating a results file

For the convenience of MLC participants, you can get the Captive Game Server produce a results file, each line of which will record the outcome of one episode. (This is the file the MLC participants are asked to submit so that their results can be compared to those of other participants' algortithms). Sample usage:

      ./captive-full.sh inputDir=game-data log=sample.csv log.nickname=JohnDoe log.run=0  R:MLC/BMK/colOrd_nearby.txt:MLC/BMK/bmk.csv

Here,

- `log=sample.csv` specifies the file to which the results will be written. Instead of `log=...` you can use `log.append=...`, in which case the data will be appended to the file, rather than overwritten.
- `log.nickname=JohnDoe` specifies the value that will go into the first column of the results file (`nickname`). This is used to identify the ML application that's playing with the CGS, or the research team who produced the application.
- `log.run=0` specifies the sequential number of your run, within the sets of runs you carry out for a particular rule set. The numbers should start with 0.

#### Compact format

Several results file formats are supported. As of ver. 6.002 (Jan 2023), the default format (which the MLC participants are advised to use) is the so-called "compact format", which looks like this:

    #.nickname,rule_name,trial_id
    #number_of_moves,number_of_errors,if_clear
    .RandomTest,alternateShape2Bucket_color2Bucket,0
    47,38,1
    36,27,1
    29,20,1
    35,26,1
    45,36,1
    .RandomTest,alternateShape2Bucket_color2Bucket,1
    31,22,1
    40,31,1
    61,52,1
    42,33,1
    30,21,1
       ..... etc ....

Here, the first 2 lines are the header. The rest of the file consists of sections, one section per run. Each run's section starts with the "run introduction line", which begins with a dot ("."), followed by the algorithm's name (the same throughout the entire file), the rule set name, and the zero-based run number.

The run introduction line is followed by lines describing the outcome of individual episodes. Each line has 3 numbers: the number of moves (counting all move and pick attempts in the episode, both successful and failed), the number of errors (the failed move and pick attempts), and the "if_clear" bit, which is 1 if the board has been cleared at the end of the episode and 0 otherwise (i.e. if the algorithm gave up on this board, or a stalemate has occurred).

You can compare the content of the results file produced by the server with what your own ML algorithm has calculated as its number of moves and errors in each episode. If there is a mismatch, then there is something wrong with the accounting, either in the server or in your code!

#### Long format

For backward compatibility with older versions, the CGS also supports the "long format" of the results file, which has more redundant information. If for some reason you desire to use it, include `log.format=Long` into the CGS command line, along with all the other log-related options.

Below is an example of a long-format results file that has been generated after 2 runs:

    nickname,rule_name,trial_id,board_id,number_of_pieces,number_of_moves,move_acc,if_clear
    JohnDoe,colOrd_nearby,0,0,9,3,1.0,0
    JohnDoe,colOrd_nearby,0,1,9,1,1.0,0
    JohnDoe,colOrd_nearby,0,2,9,1,1.0,0
    JohnDoe,colOrd_nearby,1,0,9,0,0.0,0
    JohnDoe,colOrd_nearby,1,1,9,9,1.0,1
    JohnDoe,colOrd_nearby,1,2,9,2,0.5,0

### Generating a detailed transcript

Since ver. 8.031, it is possible to request the CGS to generate a detailed transcript of all episodes, describing each move in the same way human players' moves are described in the detailed transcripts saved by the web-based Game Server. This is requested with the option `detailedTranscript=file_name`. Due to some silly technical reasons, this option can only be used if the option `log=log_file_name` is used as well.

The transcript data are always appended to a detailed transcript file. So if you want the recording to start from scratch, make sure to remove the old file of the same name!

Sample usage:

    rm transcript.csv
    captive-full.sh /opt/w2020/game-data/trial-lists/FDCL/basic/basic-01-A.csv 1 log=log.csv log.nickname=vm log.run=0 detailedTranscript=transcript.csv

The generated detailed transcript file may look like this:

    #playerId,trialListId,seriesNo,ruleId,episodeNo,episodeId,moveNo,timestamp,mover,reactionTime,objectType,objectId,y,x,bucketId,by,bx,code,objectCnt
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,0,20250912-011205.697,0,9.112,BLUE_SQUARE,0,2,4,1,7,7,0,8
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,1,20250912-011211.632,0,5.935,BLACK_SQUARE,1,2,5,2,0,7,0,7
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,2,20250912-011215.624,0,3.992,RED_STAR,2,3,5,0,7,0,0,6
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,3,20250912-011218.504,0,2.88,YELLOW_CIRCLE,3,4,3,3,0,0,0,5
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,4,20250912-011222.112,0,3.608,RED_CIRCLE,4,4,4,0,7,0,0,4
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,5,20250912-011225.880,0,3.768,BLUE_TRIANGLE,5,5,3,1,7,7,0,3
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,6,20250912-011229.456,0,3.576,BLACK_SQUARE,6,6,2,2,0,7,0,2
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,7,20250912-011233.168,0,3.712,BLUE_CIRCLE,7,6,3,1,7,7,0,1
    vm,basic-01-A,0,cm_RBKY,0,20250912-011156-RHVMVO,8,20250912-011236.096,0,2.928,RED_CIRCLE,8,6,4,0,7,0,0,0
    vm,basic-01-A,0,cm_RBKY,1,20250912-011249-6IYZOT,0,20250912-011436.489,0,106.659,BLACK_SQUARE,7,4,4,2,0,7,0,8
    vm,basic-01-A,0,cm_RBKY,1,20250912-011249-6IYZOT,1,20250912-011444.986,0,8.497,BLACK_STAR,8,5,6,2,0,7,0,7
    vm,basic-01-A,0,cm_RBKY,1,20250912-011249-6IYZOT,2,20250912-011456.650,0,11.664,RED_SQUARE,0,1,3,0,7,0,0,6
    ... ... ...

While the semantics of most fields in this detailed transcript is as close to that of the corresponding fields in the detailed transcripts of human players, some require additional explanation. Those are the fields that are important in our human players' framework, but don't apply well to the realities of an ML program playing with the CGS. Specifically:

- playerId -- the CGS puts here the same value that appears in the "nickname" field of CGS logs (supplied in the log.nickname option)
- trialListId -- in those runs when the CGS is given the name of a trial list file as an argument, that name is printed (without extenstion). Otherwise, blank.
- seriesNo -- in those runs when the CGS is given the name of a trial list file and a (1-based) row number as an argument, the CGS prints the (0-based) row number; otherwise, 0. (The conversion from 1-based to 0-based is for compatibility with the human players' transcripts).
- ruleId -- in those runs when the CGS is actually given the name of a trial list file and a row number as an argument, the rule name comes from the parameter set in the trial list file. In other runs, that can be inferred from the rule set file name supplied as a command line argument. In the latter case, though, the CGS just uses the file name without the full path relative to the game-data/rules directory (e.g. just "ccw" rather than "FDCL/basic/ccw"), because the full name may not always be provided anyway.
- episodeNo -- same as in log files (sequentially numbered within the file (or within the run, if you reuse the log file for multiple runs), starting from 0

Another usage example:

    rm transcript.csv
    captive-full.sh /opt/w2020/game-data/rules/FDCL/basic/ccw.txt 3 log=log.csv log.nickname=vm log.run=0 detailedTranscript=transcript.csv

The detailed transcript:

    #playerId,trialListId,seriesNo,ruleId,episodeNo,episodeId,moveNo,timestamp,mover,reactionTime,objectType,objectId,y,x,bucketId,by,bx,code,objectCnt
    vm,,0,ccw,0,20250913-011405-2FGIDD,0,20250913-011426.892,0,21.263,RED_TRIANGLE,0,1,6,1,7,7,0,2
    vm,,0,ccw,0,20250913-011405-2FGIDD,1,20250913-011432.874,0,5.982,RED_STAR,2,4,6,0,7,0,0,1
    vm,,0,ccw,0,20250913-011405-2FGIDD,2,20250913-011438.402,0,5.528,YELLOW_TRIANGLE,1,4,5,3,0,0,0,0
    vm,,0,ccw,1,20250913-011443-F0RAVC,0,20250913-011450.768,0,7.119,YELLOW_CIRCLE,2,5,6,1,7,7,0,2
    vm,,0,ccw,1,20250913-011443-F0RAVC,1,20250913-011457.912,0,7.144,BLUE_TRIANGLE,1,3,6,0,7,0,0,1
    vm,,0,ccw,1,20250913-011443-F0RAVC,2,20250913-011504.170,0,6.258,RED_CIRCLE,0,2,6,3,0,0,0,0
    ...  ...

## Your Machine Learning application talking to the CGS

It is likely that you have installed the CGS so that your ML application can "play" with it. Since the pipe-based CGS interacts with your ML application via pipes, the general idea is as following:

- Your ML app spawns the CGS as a child process.
- Your ML open an output stream asociated with the stdin of the CGS, and an input stream associated with the stdout of the CGS.
- Your ML writes its commands to the output stream, and reads the CGS's response via the input stream.

Additional details are found below.

### Talking to the CGS from a Java application

If your ML application is in Java, you can use the ProcessBuilder API to spawn child processes and deal with their I/O. You create a `Process` object, write your commands to the stream returned by `Process.getInputStream()`, and read responses from the stream returned by `Process.getOutputStream()`

### Talking to the CGS from a Python application

If your ML application is in Python, you can use subprocess.run for the same purpose.

For the convenience of ML researchers who may want their ML application written in Python to use the CGS, we provide a sample Python client that spawns a CGS and communicates with it via pipes.

To see how this works, run the script

    	./captive-python.sh

with no arguments. It will set the CLASSPATH as needed to include all relevant JAR files, and will then invoke `python/client.py` with some arguments (rule file and piece count), which in its turn will spawn a CGS and play an episode of the specified game with it, communicating via pipes. The script `python/client.py` can take all other command-line arguments that the shell scripts discussed above do.

You may want to modify the script `captive-python-socket.sh` as needed to use a different rule file.

In the Python code, after `python/client.py` spawns the CGS process, it uses code from `python/gameLoop.py` to do the actual communication and playing. In the latter file, the method `chooseMove()` is the one deciding on the next move. In the sample code, the move is done by picking a random piece and trying to put it to a randomly chosen bucket; in a real ML application, some appropriate learning logic would appear here instead.

Below is the console output from a sample session (from a different, earlier version of gameLoop.py, which "cheats" a bit by going only for moveable pieces).

    :~/w2020/game> ./captive-python.sh
    Rule file=./rules/rules-01.txt, #pieces=5
    Received: 6 0 0
    Received: # Hello. This is Captive Game Server ver. 1.003. Starting a new game (no. 1)
    Received: {"id":0,"value":[{"id":0,"color":"BLACK","shape":"SQUARE","x":2,"y":3,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":6,"y":4,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":5,"y":5,"bu
    ckets":[]},{"id":0,"color":"YELLOW","shape":"STAR","x":1,"y":6,"buckets":[0]},{"id":0,"color":"RED","shape":"TRIANGLE","x":3,"y":6,"buckets":[]}]}
    Code=6, status=0, stepNo=0
    5 pieces still on the board
    Sending: MOVE 6 1 0 0
    Received: 4 0 1
    Received: {"id":0,"value":[{"id":0,"color":"BLACK","shape":"SQUARE","x":2,"y":3,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":6,"y":4,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":5,"y":5,"bu
    ckets":[]},{"id":0,"color":"YELLOW","shape":"STAR","x":1,"y":6,"buckets":[0]},{"id":0,"color":"RED","shape":"TRIANGLE","x":3,"y":6,"buckets":[]}]}
    Code=4, status=0, stepNo=1
    5 pieces still on the board
    Sending: MOVE 6 1 0 0
    Received: 4 0 2
    Received: {"id":0,"value":[{"id":0,"color":"BLACK","shape":"SQUARE","x":2,"y":3,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":6,"y":4,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":5,"y":5,"bu
    ckets":[]},{"id":0,"color":"YELLOW","shape":"STAR","x":1,"y":6,"buckets":[0]},{"id":0,"color":"RED","shape":"TRIANGLE","x":3,"y":6,"buckets":[]}]}
    Code=4, status=0, stepNo=2
    5 pieces still on the board
    Sending: MOVE 6 1 7 0
    Received: 0 0 3
    Received: {"id":0,"value":[{"id":0,"color":"BLACK","shape":"SQUARE","x":2,"y":3,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":6,"y":4,"buckets":[]},{"id":0,"color":"RED","shape":"SQUARE","x":5,"y":5,"bu
    ckets":[]},{"id":0,"color":"RED","shape":"TRIANGLE","x":3,"y":6,"buckets":[0,1]}]}
    Code=0, status=0, stepNo=3
    4 pieces still on the board
      .... .... ....
    1 pieces still on the board
    Sending: MOVE 3 2 0 7
    Received: 4 0 11
    Received: {"id":0,"value":[{"id":0,"color":"BLACK","shape":"SQUARE","x":2,"y":3,"buckets":[3]}]}
    Code=4, status=0, stepNo=11
    1 pieces still on the board
    Sending: MOVE 3 2 0 0
    Received: 0 1 12
    Received: # Game finished - the board is clear
    Received: {"id":0,"value":[]}
    Code=0, status=1, stepNo=12
    Cleared board in 12 steps

#### Python version

The sample python app described above begins with the line

      #!/usr/bin/python

, which means that it will use whichever Python executable you have at that location. We have tested it both with Pyton 2 (specifically Python 2.7.17) and Python 3 (specicically Python 3.6.9). If the Python executable is installed at a different location on your system, you may need to edit the first line of this Pythin script (and any other Python scripts with a similar line) as appropriate.

#### Sample Python app that also does MLC logging

We have provided a sample shell script for the Machine Learning Challenge (MLC) participants who wants their ML program to play with the Captive Game Server and to save a results file for submission to the MLC Leader Board. The can model their scripts on the `csh` script `scrupts/captive-python-mlc.sh`, which in its turn uses `python/client-2.py`.

Usage:

    	~/w2020/game/scripts/captive-python-mlc.sh

If you are an MLC participants, you may want to read this script (and the Python scripts it invokes), and insert functionally similar code into your application, so that it gets the CGS to generate necessary results files.

If you look inside this script, you'll see that it:

- Lists all rule files from `game-data/rules/MLC/BMK`;
- For each file, it makes 2 runs, by invoking

        python/client-2.py inputDir=${in} logappend=${log} log.nickname=RandomTest log.run=${run} R:${r}:MLC/BMK/bmk.csv

  with appropriate values for the shell variables in question.

In each run, the script `python/client-2.py` runs 5 episodes. Thus, the results file (test.csv) has 10 lines for each of the 15 rule set files. The results file may look like this:

    nickname,rule_name,trial_id,board_id,number_of_pieces,number_of_moves,move_acc,if_clear
    RandomTest,alternateShape2Bucket_color2Bucket,0,0,9,29,0.3103448275862069,1
    RandomTest,alternateShape2Bucket_color2Bucket,0,1,9,20,0.45,1
    RandomTest,alternateShape2Bucket_color2Bucket,0,2,9,70,0.12857142857142856,1
    RandomTest,alternateShape2Bucket_color2Bucket,0,3,9,39,0.23076923076923078,1
    RandomTest,alternateShape2Bucket_color2Bucket,0,4,9,55,0.16363636363636364,1
    RandomTest,alternateShape2Bucket_color2Bucket,1,0,9,36,0.25,1
    RandomTest,alternateShape2Bucket_color2Bucket,1,1,9,58,0.15517241379310345,1
    RandomTest,alternateShape2Bucket_color2Bucket,1,2,9,21,0.42857142857142855,1
    RandomTest,alternateShape2Bucket_color2Bucket,1,3,9,63,0.14285714285714285,1
    RandomTest,alternateShape2Bucket_color2Bucket,1,4,9,25,0.36,1
    RandomTest,colOrd_nearby,0,0,9,111,0.08108108108108109,1
    RandomTest,colOrd_nearby,0,1,9,137,0.06569343065693431,1
    RandomTest,colOrd_nearby,0,2,9,76,0.11842105263157894,1
    ...

The sample Python script is a fairly poor player, as it makes its moves completely at random (picking a random game piece and trying to move it to a randomly chosen bucket). If your ML program is any good, you should hope to obtain, on average, better values of `move_acc`, at least once it has learned something!

## Game description

This section is somewhat obsolete and mostly superfluous now, as a more detailed and updated description of the rule file syntax is now available elsewehere.

A few game rule description files have been supplied in `~/captive/game/rules/`. The rule description language is mostly described in a Google Sheets documents ( Design Checklist; if you cannot access it, ask the article authors for a share link). There are some extensions to this language though. In particular:

- Lines starting with a `#` character are comments (purely for human readers, ignored by the engine)
- The rule lines may be preceded by any number of order definition lines, e.g.

      Order Manchu=[31, 25, 19, 13, 7, 1, 32, 26, 20, 14, 8, 2, ....]
      Order fromOutsideIn=[ [1,2,3,4,5,6, 7,13,19,25, 31,32,33,34,35,36, 30,24,18,12], [8,9,10,11, 14,20, 26,27,28,29, 23,17], [15,16,21,22]]

  The first line defines an order named `Manchu`, according to which one must first pick objects in the order in which one reads Manchu or Mongol script, i.e. by column, the columns being arranged from left to right. The second line defines an order named `fromOutsideIn`, according to which one must first pick objects from the cells adjacent to the edge of the square, etc, toward the center.
- Any rule line may start with an integer (global counter). If provided, this rule line can be used at most this many times before the control goes to the next line.
- After the optional global counter, the line must have one or several rule "atoms". Each atom has the format

      	  (counter,shape,color,positionList,bucketFunctions)

  For example, the rule

      	    (*,star,*,fromInsideOut,[0])

  says that any number of stars of any color can be picked, as long as they are among the "most inside" pieces of all pieces on the board; once picked, they must be put into bucket no. 0.
- The buckets are numbered clockwise starting from the top left. This is in agreement with the current functionality in the GUI app. This, bucket 0 is (7, 0), bucket 1 is (7,7) etc.

For more information, see the detailed guide for the Rule file syntax and semantics.

## Commands (input) and output

The input to CGS consists of one-line commands, some with arguments. The output consists of "comment lines" (intended for debugging or human consumption), preceded with '#', and data lines, which do not have a '#'. Your ML program should ignore all comment lines.

Three output modes are available: brief, standard, and full. The full mode contains a large number of comment lines (in particular, a graphic board display); the other two modes don't have comment lines, or only have very few of them. The CGS can be started in any of these modes using one of the 3 scripts provided (captive-full.sh, captive-standard.sh, or captive-brief.sh).

## The CGS API

The following are the commands you'll need

The implicit "NEW" command: when you start the CGS, an episode starts immediately, and you get 2 lines of output right away which are in the same format as for the "NEW" command (below).

    NEW

Starts a new episode. You don't need this command at the very beginning of a session, since the first episode starts automatically. Use this command for every subsequent game. This command can be used after the previous episode has completed (with a "win" (clearing the board) or a stalemate (no piece can be moved anymore); it can also be used in the middle of an episode if you give up and want to start a new one.

Response: two lines. The first line contains 3 numbers, as described in the "MOVE" section below, reflecting the acceptance of the command and the current state. The second line describes the current display. It is in JSON format, and looks as follows:
`{"id":0,"value":[{"id":0,"color":"BLUE","shape":"CIRCLE","x":4,"y":1,"buckets":[]},{"id":0,"color":"RED","shape":"CIRCLE","x":4,"y":3,"buckets":[0]},{"id":0,"color":"BLUE","shape":"SQUARE","x":3,"y":5,"buckets":[]},{"id":0,"color":"YELLOW","shape":"CIRCLE","x":3,"y":6,"buckets":[]}]}`
Here, at the top level the only field that matters is "value". Its value is an array, each elements represents a piece. For example, the piece described as `{"id":0,"color":"RED","shape":"CIRCLE","x":4,"y":3,"buckets":[0]}` has color RED, shape CIRCLE, is located in row 3, column 4. The field "buckets" is an array containing the list of buckets (see above for numbering!) into which this piece can be moved. If the array size is zero, it means that the piece is not moveable. It is up to your program and its "honor system" to which extent it wants to look into this array!

    FEATURES

Response: one line, containing a JSON structure listing all properties (features) that game pieces may have, with the set of all possible values for each one. In a game with "legacy" objects (described by the 4 legacy shapes and 4 legacy colors), the response will be as follows:

      {"shape":["SQUARE","STAR","CIRCLE","TRIANGLE"],"color":["RED","BLACK","BLUE","YELLOW"]}

In a game with Image-and-property-based objects, the response will be based on all the properties and their values occurring in the property list file(s) mentioned in the game's parameter set, e.g. for the experiment plan `/opt/w2020/game-data/trial-lists/RU/JF/tht/exp2/simpleVcomp.csv` (para set line 1), we have

      {"names":["shape_1_1_1","shape_1_1_2","shape_1_1_3", ...,"shape_4_4_4"],
      "size_indices":[1,2,3,4],"shape_indices":[1,2,3,4],"color_indices":[1,2,3,4]}

(The "names" property has a lot of possible values, because each object has its own unique value of that property in that experiment plan). In games with Composite image objects, the properties are computed dynamically, as per Composite image objects | properties.

In more typical experiment plans every object has the same set of features; however it is possible to create experiment plans with IPB objects in which some features are only present in some but not all objects. (That can be achieved by having empty cells in the properties file, or by including into your parameter set objects from more than one directory, the properties files in different directories having different feature sets). In this case the JSON structure returned by `FEATURE` will include all properties that may occur in at least one object in some episode, even if some of these properties don't occur in all objects.

The set of values that appears in the returned JSON structure for a particular property (feature) includes all values that may ever appear for that feature in some objects in some episode played under the current parameter set. Any particular episode may not necessarily have objects with all of these values.

It is advised that you use the `FEATURES` command just once for any given parameter set. You can do it as you start playing your first episode. Start the CGS (as per item No. 7 in the discussion of command lines above), issue the `FEATURES` command so that you can allocate your data structures, and then play the first episode using the `DISPLAY` and `MOVE` commands. After that, you can use the `NEW` command to start the second and subsequent episodes, without ever repeating the `FEATURES` command.

    DISPLAY

Response: one line, displaying the current board in the JSON format, in the same format as in the NEW command.

    MOVE piece_id bucket_id

or

    MOVE row col B_row B_col

This command attempts to pick the game piece with the specified ID, and to move it to the bucket with the specified bucket_ID (in the range 0 through 3). There is also a legacy format, where you specify the game piece by its coordinates (row,col), and the bucket by its location at (B_row, B_col). In this legacy format, the values for the first two coordinates can be in the range [1..6]; the values for each of the last two coordinates must be 0 or 7.

Response: two lines (in the standard mode) or one line (in the brief mode). The first line contains 3 numbers, as follows:

      response_code game_state move_count

The response_code is 0 for acceptance (successful move), positive for rejection (command is understood and is legal, but the move is denied), negative for an error (command arguments are not legal). More specifically:

        public static class CODE {
    	public static final int
    	// move accepted and processed
    	    ACCEPT = 0,
    	// Move rejected, and no other move is possible
    	// (stalemate). This means that the rule set is bad, and we
    	// owe an apology to the player
    	    STALEMATE=2,
    	// move rejected, because there is no piece in the cell
    	    EMPTY_CELL= 3,
            // Move rejected, because this destination is not allowed
            // (even though the piece can perhaps be moved to some other bucket)
    	    DENY = 4,
    	// Exit requested
    	    EXIT = 5,
    	// New game requested
                NEW_GAME = 6,
            // Move rejected, because this game piece is immovable (cannot
            // be moved to any bucket).
    	    IMMOVABLE = 7;

    	public static final int
    	    INVALID_COMMAND= -1,
    	    INVALID_ARGUMENTS= -2,
    	    INVALID_POS= -3,
    	// No game is on now. Start a game first!
    	    NO_GAME = -4,
    	// Used in socket server GAME  command
    	    INVALID_RULES = -5,
    	// Used in web app, when trying to access a non-existent episode
    	    NO_SUCH_EPISODE = -6,
    	// The number of preceding attempts does not match. This may indicate
    	// that some HTTP requests have been lost, or a duplicate request
                ATTEMPT_CNT_MISMATCH = -7,
        	// This code is returned on successful DISPLAY calls, to
    	// indicate that it was a display (no actual move requested)
    	// and not a MOVE
    	    JUST_A_DISPLAY = -8;

       }

When a "competent" (human or robotic) player (i.e. one who does not mistype command, does not grab at empty cells, etc) plays with the CGS, the only response code that can come back in response to a `MOVE` command are 0 (`ACCEPT`, indicating a successful move), 4 (`DENY`), and 7 (`IMMOVABLE`), the last two indicating a failed move attempt.

Note: Prior to GS 5.007 (July 2022), response code 7 (`IMMOVABLE`) did not exist, and attempts to move an immovable game piece resulted in response code 4 (`DENY`). These two codes have been "split" since GS 5.007 in order to enable a ML program to identify an immovable game piece in a single move attempt (rather than 4 attempts). This will make robots' playing experience more similar to that of humans playing via the web GUI, who can identify immovable pieces in a single attempt.

If you are designing a ML algorithm playing the Game of Hidden Rules with the CGS, it is to your advantage to fully use the information provided by these two response code. The `IMMOVABLE` code means that not only the game piece you tried to move cannot be moved to your chosen bucket, but it also cannot be moved to any other bucket at this point in the game. On the other hand, the `DENY` code tells you that the game piece can be moved to some other bucket.

The second number, the finish code reports the current state: 0=can play (there are pieces on the board, and some can be moved), 1=finish (no pieces left on the board), 2=stalemate (there are pieces on the board, but none of them can be moved anymore).

The third number is the move count, i.e. the total number of attempted and successful moves in this episode so far.

In the standard mode, the status line is followed by a line with the description of the current display, in the same format as in the NEW command. In the brief mode, this line is omitted. You can use the brief mode if your program keeps track of the board itself, and you want to reduce the cost of communication with the CGS.

    COND train

    COND test

Starting with CGS ver. 6.010, these commands can be used to switch the server between the training mode and the testing mode. (Or back, although that's unlikely to be needed). For the explanation of the training and testing modes, see Example 9. Train/test. As that example indicates, it only makese sense to talk about the training and testing modes when a condition file has been provided to the CGS, so that it actually will behave differently in the two modes.

Response: `#OK, COND=train` or `#OK, COND=test`, as appropriate, indicating the new mode.

    COND

The `COND` command with no argument simply reports the current mode, in the same format as `COND` with an argument does.

    EXIT

Exits the CGS immediately.

    HELP

Prints some human-readable help info. An ML program is unlikely to ever use this command.

    VERSION

Prints the version number.

## Human-readable output

In the "full" output mode, human-readable display is printed with each "DISPLAY", "NEW", or "MOVE" command, as a number of comment lines. In the other modes, the same display is available with the "DISPLAYFULL" command.

The following "ASCII art" notation is used: O, #, T, * are circles, squares, triangle, and stars, respectively. The color is either not marked at all, or is expressed by a lowercase letter (bLACK, yELLOW, rED, and g for BLUE). Dots are empty cells. Round parentheses () surround pieces that can be moved presently. Square bracket surround the cell to which the last MOVE was applied; the cell will be empty [.] if the move was successful (the piece has been removed), or non-empty, e.g. [O], if the move was rejected.

## Logging

Until ver 5.003, there was no logging. The ML program was to count its games, and to record displays (e.g. the initial boards) and the playing statistics if it so desired.

Some elementary logging (one line per episode) was introduced in CGS 5.003; see above.

## Socket interface

An alternative way of running CGS is as a process in a separate console window (or even by a different user, or on a different host) and communicating with it over the socket interface. Unlike the "normal" CGS, the socket game server can serve multiple clients, with a different game rule set for each one; however, the client-server session facing each client (and running in a separate thread) is still completely controlled by the client and thus can still be described as "captive".

### Starting the socket-based CGS

In a new console window, run the script `socket-server.sh` with the desired port number as an argument, e.g.

    	~/w2020/game>    ./socket-server.sh 7501

The socket server will normally not produce any messages, other than reports on rule set files being read at the beginning of each session, if everything goes on normally. Any error messages will go to the screen.

At this point (ver 1.003) there is no inactive session management in the server, so the clients ought to close their sessions as appropriate. When you don't need the server running anymore, you can kill it with Ctrl-C, or with a `kill` command.

### The socket-based CGS API

The only difference from the normal (pipe-based) CGS API is that the socket CGS has one more command,

    GAME "rule-file.txt" nPieces

e.g.

    GAME "rules/rules-01.txt" 5

(The quotes around the file name are optional)

This command must be used as the first command of the session. It specifies the rule set file to use (the rule file name can specify the absolute file name on the server, or a path relative to the directory where the server was started), and the number of pieces. These arguments are analogous to those used on the command line when starting a pipe-based CGS; however, the rule file name must be double-quoted.

As of ver. 4.002, the GAME command in the socket CGS API can also use various other arguments, in the same way as they can be used on the command line of a pipe-based CGS (See Examples 1 thru 7 in Command-line parameters). For example:

    GAME rules/rules-01.txt 5 1:2 1:3

or

    GAME /opt/w2020/game-data/trial-lists/vmColorTest/trial_1.csv 1

After the `GAME` command is sent, the socket CGS behaves exactly like the pipe-based CGS does; it reads in a rule set file and any other required control files, and starts the first episode, sending back to the client the status line and the JSON display line. Thereafter, the same commands (`MOVE`, `NEW`, and finally `EXIT`) should be used by the client to play a desired number of episodes, exactly as their are in the pipe-based CGS.

### Talking to the socket CGS from the console

You can test the socket CGS by running the telnet command on the appropriate port, e.g.

    	telnet localhost 7501

You can then enter the `GAME` command, followed by `MOVE`, `NEW`, and `EXIT` as appropriate. For example:

    :~> telnet localhost 7501
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    GAME "rules/rules-01.txt" 2
    6 0 0
    # Hello. This is Captive Game Server ver. 1.003. Starting a new game (no. 1)
    {"id":0,"value":[{"id":0,"color":"BLUE","shape":"TRIANGLE","x":6,"y":5,"buckets":[]},{"id":0,"color":"RED","shape":"TRIANGLE","x":1,"y":6,"buckets":[0]}]}
    MOVE 6 1 7 0
    0 0 1
    {"id":0,"value":[{"id":0,"color":"BLUE","shape":"TRIANGLE","x":6,"y":5,"buckets":[1]}]}
    MOVE 5 6 7 7
    0 1 2
    # Game finished - the board is clear
    {"id":0,"value":[]}
    NEW
    6 0 0
    # Hello. This is Captive Game Server ver. 1.003. Starting a new game (no. 2)
    {"id":0,"value":[{"id":0,"color":"BLUE","shape":"TRIANGLE","x":5,"y":1,"buckets":[2]},{"id":0,"color":"YELLOW","shape":"CIRCLE","x":6,"y":5,"buckets":[1]}]}
    ....
    EXIT
    5 0 0
    # Goodbye
    Connection closed by foreign host.

### Talking to the socket CGS from a Python client

For the convenience of ML researchers who may want their ML application written in Python communicate with the socket CGS, we provide a sample Python client doing exactly that.

To see how this works, run the script `captive-python-socket.sh`, indicating the host and port to connect, and the game to play, e.g.:

    	 ./captive-python-socket.sh localhost 7501 /opt/w2020/game-data/rules/Rule-001.txt 4

It will set the CLASSPATH as needed to include all relevant JAR files, and will then invoke `python/client-socket.py` with the same arguments (host name, port number, rule file and piece count), which opens a socket connection and plays an episode of the specified game.

You may want to modify the script `captive-python-socket.sh` as needed to use a different host, port, or rule file.

## Special note about games with Composite objects

As of ver. 6.040, when the CGS loads a parameter set from a trial list file, it pre-computes the list of features and their possible values, so that it can be later returned in response to the `FEATURES` command. While for most parameter sets this procedure is easy, for some games with Composite image objects the set of possible feature values may be very large ("combinatorially large"). (The parameter set no. 1 in trial list `trial-lists/vm/composite-02/trial_1.csv`, in which each object is composed out of 25 elements, is one example). Therefore, an attempt to start CGS on such a parameter set may cause a `java.lang.OutOfMemoryError`.

This means that at present some of the games with Composite image objects cannot be played on the CGS. Should it become desirable to play such games, the situation can be partially rectified by modifying the server so that it, for example, returns the feature sets in a "wildcard" format, leaving it up to the ML player to figure what the specific values of a particular feature may be.