#include <perms.h>

//          Edinburgh IMP77 Compiler - Version 8.4
//
//     1  %begin

int main(int argc, char **argv) { /*%begin*/
  _imp_initialise(argc, argv);

  //     2      %constant %byte maximising player = 0
  //     3      %constant %byte maximising symbol = 'O'
  //     4
  //     5      %constant %byte minimising player = 1
  //     6      %constant %byte minimising symbol = 'X'
  //     7
  //     8      %constant %byte unused symbol     = '-'
  //     9
  //    10      %constant %byte machine           = maximising player
  //    11      %constant %byte machine symbol    = maximising symbol
  //    12      %constant %byte human             = minimising player
  //    13      %constant %byte human symbol      = minimising symbol
  //    14
  //    15      ! Values to indicate game board layout
  //    16      %constant %byte top left      = 1
  //    17      %constant %byte top centre    = 2
  //    18      %constant %byte top right     = 3
  //    19      %constant %byte middle left   = 4
  //    20      %constant %byte centre        = 5
  //    21      %constant %byte middle right  = 6
  //    22      %constant %byte bottom left   = 7
  //    23      %constant %byte bottom centre = 8
  //    24      %constant %byte bottom right  = 9
  //    25
  //    26      ! Assuming 32-bit integers are used
  //    27      %constant %integer minus infinity = 16_80000000
  //    28      %constant %integer plus infinity  = 16_7fffffff
  //    29
  //    30      %integer game

  int GAME;

  //    31      %string(9) game state

  _imp_string9 GAMESTATE;

  //    32
  //    33      %integer %function max( %integer a, b)

  int MAX(int A, int B) {
    //    34          %result = b %if (b > a)

    if (B <= A) goto L_0001;
    return B;
  L_0001:;

  //    35          %result = a

    return A;

    //    36      %end

  } /* end of MAX */

  //    37
  //    38      %integer %function min( %integer a, b)

  int MIN(int A, int B) {
    //    39          %result = b %if (b < a)

    if (B >= A) goto L_0002;
    return B;
  L_0002:;

  //    40          %result = a

    return A;

    //    41      %end

  } /* end of MIN */

  //    42
  //    43      %string(9) %function reset game

  _imp_string9 RESETGAME(void) {
    //    44          %integer i

    int I;

    //    45          %string(9) initial state

    _imp_string9 INITIALSTATE;

    //    46
    //    47          ! clear the game state
    //    48          initial state = ""

    _imp_strncpy(/*?*/ &INITIALSTATE, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("");
                   (void *)&tmp;
                 }),
                 /*max:*/ 9);

    //    49          ! completely populate the game state with the unused symbol
    //    50          %for i = 1,1,9 %cycle

    // %for I = 1, 1, 9 %cycle
    {
      I = 0;
    L_0003:
      if (I == 9) goto L_0004;
      I += 1;

      //    51              initial state = initial state.to string( unused symbol )

      _imp_strncpy(/*?*/ &INITIALSTATE, ({
                     __typeof__(_imp_string255) tmp; /*B*/
                     tmp = *({
                       _imp_string255 tmp = _imp_join((_imp_string *)/*?*/ &INITIALSTATE, ({
                                                        __typeof__(_imp_string1) tmp; /*E*/
                                                        tmp = _imp_TOSTRING(45);
                                                        (void *)&tmp;
                                                      }));
                       (_imp_string255 *)&tmp;
                     });
                     (void *)&tmp;
                   }),
                   /*max:*/ 9);

      //    52          %repeat

      goto L_0003;
    }

  L_0004:;

  //    53
  //    54          %result = initial state

    return *(_imp_string9 *)/*?*/ &INITIALSTATE;

    //    55      %end

  } /* end of RESETGAME */

  //    56
  //    57      %string(32) %function slot2name( %byte slot )

  _imp_string32 SLOT2NAME(unsigned char SLOT) {
    //    58          %string(32) name

    _imp_string32 NAME;

    //    59          %switch sw(0:255)

    int SW_index;
    int SW_line;
    char *SW_file;
    static const void *SW[256] = {
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
        &&case_SW_missing};

    //    60
    //    61          -> sw( slot )

    SW_line = __LINE__;
    SW_file = __FILE__;
    SW_index = SLOT;
    goto case_SW_dispatch;

    //    62          sw(top left):      name = "top left";          -> esac

  case_SW_1:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("top left");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    63          sw(top centre):    name = "top centre";        -> esac

  case_SW_2:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("top centre");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    64          sw(top right):     name = "top right";         -> esac

  case_SW_3:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("top right");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    65          sw(middle left):   name = "middle left";       -> esac

  case_SW_4:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("middle left");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    66          sw(centre):        name = "centre";            -> esac

  case_SW_5:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("centre");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    67          sw(middle right):  name = "middle right";      -> esac

  case_SW_6:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("middle right");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    68          sw(bottom left):   name = "bottom left";       -> esac

  case_SW_7:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("bottom left");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    69          sw(bottom centre): name = "bottom centre";     -> esac

  case_SW_8:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("bottom centre");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    70          sw(bottom right):  name = "bottom right";      -> esac

  case_SW_9:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("bottom right");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    71          sw(*):             name = "an illegal square"; -> esac

  case_SW_default:;

    _imp_strncpy(/*?*/ &NAME, ({
                   __typeof__(_imp_string255) tmp; /*B*/
                   tmp = _imp_str_literal("an illegal square");
                   (void *)&tmp;
                 }),
                 /*max:*/ 32);

    goto U_1000;

    //    72          esac:

  U_1000:;

  //    73
  //    74          %result = name

    return *(_imp_string32 *)/*?*/ &NAME;

    //    75      %end

  case_SW_dispatch:
    if (SW_index < 0 || SW_index > 255)
      _imp_signalf(6, 3, SW_index, "->SW(%d) out of bounds at %s line %d", SW_index, SW_file, SW_line);
    goto *SW[SW_index - 0];

  case_SW_missing:
    _imp_signalf(8, 2, SW_index, "switch jump to undefined label SW(%d): at %s line %d", SW_index, SW_file, SW_line);
  } /* end of SLOT2NAME */

  //    76
  //    77      %routine show state( %string(9) state )

  void SHOWSTATE(_imp_string9 STATE) {
    //    78          %integer i, j

    int I;
    int J;

    //    79          %byte symbol

    unsigned char SYMBOL;

    //    80          %switch sw(1:9)

    int SW_index;
    int SW_line;
    char *SW_file;
    static const void *SW[9] = {&&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
                                &&case_SW_missing, &&case_SW_missing, &&case_SW_missing,
                                &&case_SW_missing, &&case_SW_missing, &&case_SW_missing};

    //    81
    //    82          select output( 0 )

    _imp_SELECTOUTPUT(0);

    //    83          print string( state )

    _imp_PRINTSTRING(
        *({
          __typeof__(_imp_string9) tmp = STATE /*q*/;
          (_imp_string255 *)&tmp;
        })
    );

    //    84          newline

    _imp_NEWLINE();

    //    85          newline

    _imp_NEWLINE();

    //    86          %for i = 1,1,9 %cycle

    // %for I = 1, 1, 9 %cycle
    {
      I = 0;
    L_0007:
      if (I == 9) goto L_0008;
      I += 1;

      //    87              symbol = charno( state, i )

      SYMBOL = *_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, I);

      //    88              %if (symbol = unused symbol) %then symbol = ' '

      if (SYMBOL != 45) goto L_0009;
      SYMBOL = 32;
    L_0009:;

    //    89
    //    90              -> sw(i)

      SW_line = __LINE__;
      SW_file = __FILE__;
      SW_index = I;
      goto case_SW_dispatch;

      //    91          sw(1): print symbol( symbol ); print symbol( '|' ); -> esac

    case_SW_1:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_PRINTSYMBOL(124);
      goto U_1001;

      //    92          sw(2): print symbol( symbol ); print symbol( '|' ); -> esac

    case_SW_2:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_PRINTSYMBOL(124);
      goto U_1001;

      //    93          sw(3): print symbol( symbol ); newline

    case_SW_3:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_NEWLINE();

      //    94                 print string( "-+-+-" ); newline;            -> esac

      _imp_PRINTSTRING(_imp_str_literal("-+-+-"));
      _imp_NEWLINE();
      goto U_1001;

      //    95          sw(4): print symbol( symbol ); print symbol( '|' ); -> esac

    case_SW_4:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_PRINTSYMBOL(124);
      goto U_1001;

      //    96          sw(5): print symbol( symbol ); print symbol( '|' ); -> esac

    case_SW_5:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_PRINTSYMBOL(124);
      goto U_1001;

      //    97          sw(6): print symbol( symbol ); newline

    case_SW_6:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_NEWLINE();

      //    98                 print string( "-+-+-" ); newline;            -> esac

      _imp_PRINTSTRING(_imp_str_literal("-+-+-"));
      _imp_NEWLINE();
      goto U_1001;

      //    99          sw(7): print symbol( symbol ); print symbol( '|' ); -> esac

    case_SW_7:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_PRINTSYMBOL(124);
      goto U_1001;

      //   100          sw(8): print symbol( symbol ); print symbol( '|' ); -> esac

    case_SW_8:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_PRINTSYMBOL(124);
      goto U_1001;

      //   101          sw(9): print symbol( symbol ); newline;             -> esac

    case_SW_9:;
      _imp_PRINTSYMBOL(SYMBOL);
      _imp_NEWLINE();
      goto U_1001;

      //   102
      //   103          esac:

    U_1001:;

    //   104          %repeat

      goto L_0007;
    }

  L_0008:;

  //   105
  //   106          newline

    _imp_NEWLINE();

    //   107
    //   108      %end

    return;

  case_SW_dispatch:
    if (SW_index < 1 || SW_index > 9)
      _imp_signalf(6, 3, SW_index, "->SW(%d) out of bounds at %s line %d", SW_index, SW_file, SW_line);
    goto *SW[SW_index - 1];

  case_SW_missing:
    _imp_signalf(8, 2, SW_index, "switch jump to undefined label SW(%d): at %s line %d", SW_index, SW_file, SW_line);
  } /* end of SHOWSTATE */

  // ?J unused
  //   109
  //   110      %predicate unused slot( %string(9) state, %byte square )

  int UNUSEDSLOT(_imp_string9 STATE, unsigned char SQUARE) {
    //   111          %true %if (charno( state , square ) = unused symbol)

    if (*_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, SQUARE) != 45) goto L_000B;
    return 1 /*TRUE*/;
  L_000B:;

  //   112          %false

    return 0 /*FALSE*/;

    //   113      %end

  } /* end of UNUSEDSLOT */

  //   114
  //   115      ! Make a game move by storing player's symbol at given slot
  //   116      %string(9) %function make move( %string(9) state, %byte slot, symbol )

  _imp_string9 MAKEMOVE(_imp_string9 STATE, unsigned char SLOT, unsigned char SYMBOL) {
    //   117          %string(9) next state

    _imp_string9 NEXTSTATE;

    //   118
    //   119          next state = state

    _imp_strncpy(/*?*/ &NEXTSTATE, ({
                   __typeof__(_imp_string9) tmp; /*B*/
                   tmp = STATE;
                   (void *)&tmp;
                 }),
                 /*max:*/ 9);

    //   120          %if (top left <= slot <= bottom right) %start

    {
// Double-sided test on SLOT (Part I)
      unsigned char tmp;
      if (1 > (tmp = SLOT)) goto L_000C;
// Double-sided test on SLOT (Part II)
      if (tmp > 9) goto L_000C;
    }

    //   121              %if unused slot( state , slot ) %start

    if (!(UNUSEDSLOT(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            SLOT)))
      goto L_000D;

      //   122                  charno( next state, slot ) = symbol

    *_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &NEXTSTATE, SLOT) = SYMBOL;

    //   123              %finish %else %start

    goto L_000E;
  L_000D:;

  //   124                  select output( 0 )

    _imp_SELECTOUTPUT(0);

    //   125                  print string( "Cheating detected! Player " )

    _imp_PRINTSTRING(_imp_str_literal("Cheating detected! Player "));

    //   126                  print symbol( '"' )

    _imp_PRINTSYMBOL(34);

    //   127                  print symbol( symbol )

    _imp_PRINTSYMBOL(SYMBOL);

    //   128                  print symbol( '"' )

    _imp_PRINTSYMBOL(34);

    //   129                  print string( " tried to overwrite player ")

    _imp_PRINTSTRING(_imp_str_literal(" tried to overwrite player "));

    //   130                  print symbol( '"' )

    _imp_PRINTSYMBOL(34);

    //   131                  print symbol( charno( state, slot ) )

    _imp_PRINTSYMBOL(*_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, SLOT));

    //   132                  print symbol( '"' )

    _imp_PRINTSYMBOL(34);

    //   133                  print string( " at square '".slot2name( slot )."'" )

    _imp_PRINTSTRING(
        *({
          __typeof__(_imp_string255) tmp = *({
            _imp_string255 tmp = _imp_join((_imp_string *)/*?*/ &*({
                                             _imp_string255 tmp =
                                                 _imp_join((_imp_string *)/*?*/ _imp_str_literal_ptr(" at square '"), ({
                                                             __typeof__(_imp_string32) tmp; /*E*/
                                                             tmp = SLOT2NAME(SLOT);
                                                             (void *)&tmp;
                                                           }));
                                             (_imp_string255 *)&tmp;
                                           }),
                                           (_imp_string *)/*?*/ _imp_str_literal_ptr("'"));
            (_imp_string255 *)&tmp;
          }) /*q*/;
          (_imp_string255 *)&tmp;
        })
    );

    //   134                  new line

    _imp_NEWLINE();

    //   135              %finish

  L_000E:;

  //   136          %finish %else %start

    goto L_000F;
  L_000C:;

  //   137              select output( 0 )

    _imp_SELECTOUTPUT(0);

    //   138              print string( "Cheating detected! Player '" )

    _imp_PRINTSTRING(_imp_str_literal("Cheating detected! Player '"));

    //   139              print symbol( symbol )

    _imp_PRINTSYMBOL(SYMBOL);

    //   140              print string( "' tried to move to '" )

    _imp_PRINTSTRING(_imp_str_literal("' tried to move to '"));

    //   141              print string( slot2name( slot ) )

    _imp_PRINTSTRING(
        *({
          __typeof__(_imp_string32) tmp = SLOT2NAME(SLOT) /*q*/;
          (_imp_string255 *)&tmp;
        })
    );

    //   142              print string( "'" )

    _imp_PRINTSTRING(_imp_str_literal("'"));

    //   143              new line

    _imp_NEWLINE();

    //   144              print string( " Only squares 1..9 are valid!" )

    _imp_PRINTSTRING(_imp_str_literal(" Only squares 1..9 are valid!"));

    //   145              new line

    _imp_NEWLINE();

    //   146          %finish

  L_000F:;

  //   147          %result = next state

    return *(_imp_string9 *)/*?*/ &NEXTSTATE;

    //   148      %end

  } /* end of MAKEMOVE */

  //   149
  //   150      %predicate my slot( %string(9) state, %byte slot id, symbol )

  int MYSLOT(_imp_string9 STATE, unsigned char SLOTID, unsigned char SYMBOL) {
    //   151          %true %if (charno( state, slot id ) = unused symbol)

    if (*_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, SLOTID) != 45) goto L_0010;
    return 1 /*TRUE*/;
  L_0010:;

  //   152          %false

    return 0 /*FALSE*/;

    //   153      %end

  } /* end of MYSLOT */

  // ?SYMBOL unused
  //   154
  //   155      ! Would the player win on their next move?
  //   156      %predicate potential win line( %string(9) state, %byte symbol, p1,p2,p3 )

  int POTENTIALWINLINE(_imp_string9 STATE, unsigned char SYMBOL, unsigned char P1, unsigned char P2, unsigned char P3) {
    //   157          %byte pos 1, pos 2, pos 3

    unsigned char POS1;
    unsigned char POS2;
    unsigned char POS3;

    //   158
    //   159          %predicate free slot( %byte slot id )

    int FREESLOT(unsigned char SLOTID) {
      //   160              %true %if (charno( state, slot id ) = unused symbol)

      if (*_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, SLOTID) != 45) goto L_0011;
      return 1 /*TRUE*/;
    L_0011:;

    //   161              %false

      return 0 /*FALSE*/;

      //   162          %end

    } /* end of FREESLOT */

    //   163
    //   164          %predicate my slot( %byte slot id )

    int MYSLOT(unsigned char SLOTID) {
      //   165              %true %if (charno( state, slot id ) = symbol )

      if (*_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, SLOTID) != SYMBOL) goto L_0012;
      return 1 /*TRUE*/;
    L_0012:;

    //   166              %false

      return 0 /*FALSE*/;

      //   167          %end

    } /* end of MYSLOT */

    //   168
    //   169          %true %if free slot( p1 ) %and   my slot( p2 ) %and   my slot( p3 )

    if (!(FREESLOT(P1))) goto L_0013;
    if (!(MYSLOT(P2))) goto L_0013;
    if (!(MYSLOT(P3))) goto L_0013;
    return 1 /*TRUE*/;
  L_0013:;

  //   170          %true %if   my slot( p1 ) %and free slot( p2 ) %and   my slot( p3 )

    if (!(MYSLOT(P1))) goto L_0014;
    if (!(FREESLOT(P2))) goto L_0014;
    if (!(MYSLOT(P3))) goto L_0014;
    return 1 /*TRUE*/;
  L_0014:;

  //   171          %true %if   my slot( p1 ) %and   my slot( p2 ) %and free slot( p3 )

    if (!(MYSLOT(P1))) goto L_0015;
    if (!(MYSLOT(P2))) goto L_0015;
    if (!(FREESLOT(P3))) goto L_0015;
    return 1 /*TRUE*/;
  L_0015:;

  //   172          %false

    return 0 /*FALSE*/;

    //   173      %end

  } /* end of POTENTIALWINLINE */

  // ?POS3 unused
  // ?POS2 unused
  // ?POS1 unused
  //   174
  //   175      ! Check for a potential winning line for the player using the given symbol
  //   176      %predicate next move win( %string(9) state, %byte player symbol )

  int NEXTMOVEWIN(_imp_string9 STATE, unsigned char PLAYERSYMBOL) {
    //   177
    //   178          ! Check for any potential winning lines for player symbol
    //   179
    //   180          ! check for any potential win in a horizontal row for player symbol
    //   181          ! check top row (left,centre,right) == (1,2,3)
    //   182          %true %if potential win line( state, player symbol, 1, 2, 3 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 1, 2, 3)))
      goto L_0016;
    return 1 /*TRUE*/;
  L_0016:;

  //   183
  //   184          ! check middle row (left,centre,right) == (4,5,6)
  //   185          %true %if potential win line( state, player symbol, 4, 5, 6 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 4, 5, 6)))
      goto L_0017;
    return 1 /*TRUE*/;
  L_0017:;

  //   186
  //   187          ! check bottom row (left,centre,right) == (7,8,9)
  //   188          %true %if potential win line( state, player symbol, 7, 8, 9 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 7, 8, 9)))
      goto L_0018;
    return 1 /*TRUE*/;
  L_0018:;

  //   189
  //   190          ! check for any potential win in a vertical column for player symbol
  //   191          ! check left column (top,middle,bottom) == (1,4,7)
  //   192          %true %if potential win line( state, player symbol, 1, 4, 7 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 1, 4, 7)))
      goto L_0019;
    return 1 /*TRUE*/;
  L_0019:;

  //   193
  //   194          ! check middle column (top,middle,bottom) == (2,5,8)
  //   195          %true %if potential win line( state, player symbol, 2, 5, 8 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 2, 5, 8)))
      goto L_001A;
    return 1 /*TRUE*/;
  L_001A:;

  //   196
  //   197          ! check right column (top,middle,bottom) == (3,6,9)
  //   198          %true %if potential win line( state, player symbol, 3, 6, 9 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 3, 6, 9)))
      goto L_001B;
    return 1 /*TRUE*/;
  L_001B:;

  //   199
  //   200          ! check for any potential diagonal win for the player symbol
  //   201          ! check diagonal from top left to bottom right
  //   202          ! diagonal is (top left,middle centre,bottom right) == (1,5,9)
  //   203          %true %if potential win line( state, player symbol, 1, 5, 9 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 1, 5, 9)))
      goto L_001C;
    return 1 /*TRUE*/;
  L_001C:;

  //   204
  //   205          ! check diagonal from top right to bottom left
  //   206          ! diagonal is (top right,middle centre,bottom left) == (3,5,7)
  //   207          %true %if potential win line( state, player symbol, 3, 5, 7 )

    if (!(POTENTIALWINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 3, 5, 7)))
      goto L_001D;
    return 1 /*TRUE*/;
  L_001D:;

  //   208
  //   209          ! no potential win line for symbol player
  //   210          %false

    return 0 /*FALSE*/;

    //   211      %end

  } /* end of NEXTMOVEWIN */

  //   212
  //   213      ! Check for a winning line for the player using the given symbol
  //   214      %predicate win line( %string(9) state, %byte symbol, %byte p1,p2,p3 )

  int WINLINE(_imp_string9 STATE, unsigned char SYMBOL, unsigned char P1, unsigned char P2, unsigned char P3) {
    //   215          %byte pos 1, pos 2, pos 3

    unsigned char POS1;
    unsigned char POS2;
    unsigned char POS3;

    //   216
    //   217          pos 1 = charno( state, p1 )

    POS1 = *_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, P1);

    //   218          pos 2 = charno( state, p2 )

    POS2 = *_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, P2);

    //   219          pos 3 = charno( state, p3 )

    POS3 = *_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, P3);

    //   220
    //   221          %true %if (pos 1 = symbol) %and (pos 2 = symbol) %and (pos 3 = symbol)

    if (POS1 != SYMBOL) goto L_001E;
    if (POS2 != SYMBOL) goto L_001E;
    if (POS3 != SYMBOL) goto L_001E;
    return 1 /*TRUE*/;
  L_001E:;

  //   222          %false

    return 0 /*FALSE*/;

    //   223      %end

  } /* end of WINLINE */

  //   224
  //   225      ! Check for a winning line for the player using the given symbol
  //   226      %predicate player win( %string(9) state, %byte player symbol )

  int PLAYERWIN(_imp_string9 STATE, unsigned char PLAYERSYMBOL) {
    //   227
    //   228          ! Check for any winning lines for player symbol
    //   229
    //   230          ! check for any win in a horizontal row for player symbol
    //   231          ! check top row (left,centre,right) == (1,2,3)
    //   232          %true %if win line( state, player symbol, 1, 2, 3 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 1, 2, 3)))
      goto L_001F;
    return 1 /*TRUE*/;
  L_001F:;

  //   233
  //   234          ! check middle row (left,centre,right) == (4,5,6)
  //   235          %true %if win line( state, player symbol, 4, 5, 6 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 4, 5, 6)))
      goto L_0020;
    return 1 /*TRUE*/;
  L_0020:;

  //   236
  //   237          ! check bottom row (left,centre,right) == (7,8,9)
  //   238          %true %if win line( state, player symbol, 7, 8, 9 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 7, 8, 9)))
      goto L_0021;
    return 1 /*TRUE*/;
  L_0021:;

  //   239
  //   240          ! check for any win in a vertical column for player symbol
  //   241          ! check left column (top,middle,bottom) == (1,4,7)
  //   242          %true %if win line( state, player symbol, 1, 4, 7 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 1, 4, 7)))
      goto L_0022;
    return 1 /*TRUE*/;
  L_0022:;

  //   243
  //   244          ! check middle column (top,middle,bottom) == (2,5,8)
  //   245          %true %if win line( state, player symbol, 2, 5, 8 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 2, 5, 8)))
      goto L_0023;
    return 1 /*TRUE*/;
  L_0023:;

  //   246
  //   247          ! check right column (top,middle,bottom) == (3,6,9)
  //   248          %true %if win line( state, player symbol, 3, 6, 9 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 3, 6, 9)))
      goto L_0024;
    return 1 /*TRUE*/;
  L_0024:;

  //   249
  //   250          ! check for any diagonal win for the player symbol
  //   251          ! check diagonal from top left to bottom right
  //   252          ! diagonal is (top left,centre,bottom right) == (1,5,9)
  //   253          %true %if win line( state, player symbol, 1, 5, 9 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 1, 5, 9)))
      goto L_0025;
    return 1 /*TRUE*/;
  L_0025:;

  //   254
  //   255          ! check diagonal from top right to bottom left
  //   256          ! diagonal is (top right,centre,bottom left) == (3,5,7)
  //   257          %true %if win line( state, player symbol, 3, 5, 7 )

    if (!(WINLINE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            PLAYERSYMBOL, 3, 5, 7)))
      goto L_0026;
    return 1 /*TRUE*/;
  L_0026:;

  //   258
  //   259          ! no win line for symbol player
  //   260          %false

    return 0 /*FALSE*/;

    //   261      %end

  } /* end of PLAYERWIN */

  //   262
  //   263      %predicate game over( %string(9) state )

  int GAMEOVER(_imp_string9 STATE) {
    //   264          %integer i

    int I;

    //   265          %integer unused

    int UNUSED;

    //   266
    //   267          ! Check if there are any unused slots
    //   268          unused = 0

    UNUSED = 0;

    //   269          %for i = 1,1,9 %cycle

    // %for I = 1, 1, 9 %cycle
    {
      I = 0;
    L_0027:
      if (I == 9) goto L_0028;
      I += 1;

      //   270              unused = unused + 1 %if (charno( state, i ) <> unused symbol)

      if (*_imp_CHARNO((_imp_string255 *)/*p*/ /*?*/ &STATE, I) == 45) goto L_0029;
      UNUSED = UNUSED + 1;
    L_0029:;

    //   271          %repeat

      goto L_0027;
    }

  L_0028:;

  //   272
  //   273          ! there are no unused slots so game must be over
  //   274          %true %if (unused = 0)

    if (UNUSED != 0) goto L_002A;
    return 1 /*TRUE*/;
  L_002A:;

  //   275
  //   276          ! there are some unused slots so game is not over
  //   277          %false

    return 0 /*FALSE*/;

    //   278      %end

  } /* end of GAMEOVER */

  //   279
  //   280      %predicate terminal state( %string(9) state )

  int TERMINALSTATE(_imp_string9 STATE) {
    //   281
    //   282          ! Check for win lines for maximising player (machine)
    //   283          %true %if player win( state, maximising symbol )

    if (!(PLAYERWIN(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            79)))
      goto L_002B;
    return 1 /*TRUE*/;
  L_002B:;

  //   284
  //   285          ! Check for win lines for minimising player
  //   286          %true %if player win( state, minimising symbol )

    if (!(PLAYERWIN(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            88)))
      goto L_002C;
    return 1 /*TRUE*/;
  L_002C:;

  //   287
  //   288          ! check to see if the game has reached a state with no more moves
  //   289          %true %if game over( state )

    if (!(GAMEOVER(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                )))
      goto L_002D;
    return 1 /*TRUE*/;
  L_002D:;

  //   290
  //   291          ! At this point:
  //   292          !    there are no win lines for either player
  //   293          !    and there are more moves to make
  //   294          !    hence this is not a terminal node ( or game state )
  //   295          %false

    return 0 /*FALSE*/;

    //   296      %end

  } /* end of TERMINALSTATE */

  //   297
  //   298      %integer %function heuristic( %string(9) state )

  int HEURISTIC(_imp_string9 STATE) {
    //   299          ! check for a current/future win for the maximising player (machine)
    //   300          %result = plus infinity  %if player win( state, machine )

    if (!(PLAYERWIN(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            0)))
      goto L_002E;
    return 2147483647;
  L_002E:;

  //   301          %result = plus infinity  %if next move win( state, machine )

    if (!(NEXTMOVEWIN(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            0)))
      goto L_002F;
    return 2147483647;
  L_002F:;

  //   302
  //   303          ! check for a current/future win for the minimising player (human)
  //   304          %result = minus infinity %if player win( state, human )

    if (!(PLAYERWIN(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            1)))
      goto L_0030;
    return -2147483648;
  L_0030:;

  //   305          %result = minus infinity %if next move win( state, human )

    if (!(NEXTMOVEWIN(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                ,
            1)))
      goto L_0031;
    return -2147483648;
  L_0031:;

  //   306
  //   307          %result = 0

    return 0;

    //   308      %end

  } /* end of HEURISTIC */

  //   309
  //   310      ! maximising player uses the 'maximising symbol' (machine)
  //   311      ! minimising player uses the 'minimising symbol' (humane)
  //   312      %integer %function minimax( %string(9) state,

  int MINIMAX(_imp_string9 STATE, int DEPTH, int PLAYERGO) {
    //   313+                                 %integer depth,
    //   314+                                 %integer player go )
    //   315          %string(9) new state

    _imp_string9 NEWSTATE;

    //   316          %integer value, response

    int VALUE;
    int RESPONSE;

    //   317          %integer i

    int I;

    //   318
    //   319          %if (depth = 0) %or terminal state( state ) %start

    if (DEPTH == 0) goto L_0005;
    if (!(TERMINALSTATE(
            *({
              __typeof__(_imp_string9) tmp = STATE /*q*/;
              (_imp_string9 *)&tmp;
            })
                )))
      goto L_0032;
  L_0005:;

  //   320              value = heuristic( state )

    VALUE = HEURISTIC(
        *({
          __typeof__(_imp_string9) tmp = STATE /*q*/;
          (_imp_string9 *)&tmp;
        })
    );

    //   321          %finish %else %if (player go = machine) %start

    goto L_0033;
  L_0032:;
    if (PLAYERGO != 0) goto L_0034;

      //   322              ! check possible moves for the maximising player (machine)
      //   323              ! set value = - infinity
      //   324              value = minus infinity

    VALUE = -2147483648;

    //   325
    //   326              ! for each potential next game state
    //   327              %for i=1,1,9 %cycle

    // %for I = 1, 1, 9 %cycle
    {
      I = 0;
    L_0035:
      if (I == 9) goto L_0036;
      I += 1;

      //   328                  ! find an empty slot
      //   329                  %if unused slot( state, i) %start

      if (!(UNUSEDSLOT(
              *({
                __typeof__(_imp_string9) tmp = STATE /*q*/;
                (_imp_string9 *)&tmp;
              })
                  ,
              I)))
        goto L_0038;

        //   330                      ! next state after the maximising player (machine) move
        //   331                      new state = make move( state, i, machine symbol )

      _imp_strncpy(/*?*/ &NEWSTATE, ({
                     __typeof__(_imp_string9) tmp; /*B*/
                     tmp = MAKEMOVE(*({
                       __typeof__(_imp_string9) tmp = STATE /*q*/;
                       (_imp_string9 *)&tmp;
                     }),
                                    I, 79);
                     (void *)&tmp;
                   }),
                   /*max:*/ 9);

      //   332                      ! response from the minimising player (human)
      //   333                      response = minimax( new state, depth - 1, human )

      RESPONSE = MINIMAX(
          *({
            __typeof__(_imp_string9) tmp = NEWSTATE /*q*/;
            (_imp_string9 *)&tmp;
          })
              ,
          DEPTH - 1, 1);

      //   334                      value = max( value, response )

      VALUE = MAX(VALUE, RESPONSE);

      //   335                  %finish

    L_0038:;

    //   336              %repeat

      goto L_0035;
    }

  L_0036:;

  //   337          %finish %else %start

    goto L_0033;
  L_0034:;

  //   338              ! Oh! this must be for the minimising player (human)
  //   339              ! set value = + infinity
  //   340              value = plus infinity

    VALUE = 2147483647;

    //   341
    //   342              ! for each potential next game state
    //   343              %for i=1,1,9 %cycle

    // %for I = 1, 1, 9 %cycle
    {
      I = 0;
    L_0039:
      if (I == 9) goto L_003A;
      I += 1;

      //   344                  %if unused slot( state, i ) %start

      if (!(UNUSEDSLOT(
              *({
                __typeof__(_imp_string9) tmp = STATE /*q*/;
                (_imp_string9 *)&tmp;
              })
                  ,
              I)))
        goto L_003B;

        //   345                      ! next state after the minimising player (human) move
        //   346                      new state = make move( state, i, human symbol )

      _imp_strncpy(/*?*/ &NEWSTATE, ({
                     __typeof__(_imp_string9) tmp; /*B*/
                     tmp = MAKEMOVE(*({
                       __typeof__(_imp_string9) tmp = STATE /*q*/;
                       (_imp_string9 *)&tmp;
                     }),
                                    I, 88);
                     (void *)&tmp;
                   }),
                   /*max:*/ 9);

      //   347                      ! response from the maximising player (machine)
      //   348                      response = minimax( new state, depth - 1, machine )

      RESPONSE = MINIMAX(
          *({
            __typeof__(_imp_string9) tmp = NEWSTATE /*q*/;
            (_imp_string9 *)&tmp;
          })
              ,
          DEPTH - 1, 0);

      //   349                      value = min( value, response )

      VALUE = MIN(VALUE, RESPONSE);

      //   350                  %finish

    L_003B:;

    //   351              %repeat

      goto L_0039;
    }

  L_003A:;

  //   352          %finish

  L_0033:;

  //   353          %result = value

    return VALUE;

    //   354      %end

  } /* end of MINIMAX */

  //   355
  //   356      ! form the initial game state
  //   357      game state = reset game

  _imp_strncpy(/*?*/ &GAMESTATE, ({
                 __typeof__(_imp_string9) tmp; /*B*/
                 tmp = RESETGAME();
                 (void *)&tmp;
               }),
               /*max:*/ 9);

  //   358
  //   359      ! make the first move for the minimising player (human)
  //   360      game state = make move( game state, 27, human symbol )

  _imp_strncpy(/*?*/ &GAMESTATE, ({
                 __typeof__(_imp_string9) tmp; /*B*/
                 tmp = MAKEMOVE(*({
                   __typeof__(_imp_string9) tmp = GAMESTATE /*q*/;
                   (_imp_string9 *)&tmp;
                 }),
                                27, 88);
                 (void *)&tmp;
               }),
               /*max:*/ 9);

  //   361
  //   362      ! after the first move
  //   363      ! evaluate the game for the maximising player (machine)
  //   364      game = minimax( game state, 4, machine symbol )

  GAME = MINIMAX(
      *({
        __typeof__(_imp_string9) tmp = GAMESTATE /*q*/;
        (_imp_string9 *)&tmp;
      })
          ,
      4, 79);

  //   365
  //   366      show state( "XO-X--X--")

  SHOWSTATE(_imp_str_literal_size(9, "XO-X--X--"));

  //   367  %end

  _imp_stop(0);
  return 0;
end_0:;
}

// ?MYSLOT unused
//   368  %endoffile