//  For information about Neutreeko, visit
//
// http://www.neutreeko.net/neutreeko.htm
//
//     If you want to analyze 7x7, type
//
//          java -mx380m Neutreeko
//
//           to get enough memory


import java.io.*;
// import java.util.*;

class Move
{
   int x1, y1, x2, y2, z1;
   Move prev = null;
}

public class Neutreeko {

static int[][][] s, u;
static int[] v, p;
static int[][] q, t, w, y;
static byte[][] x;
static char[] piece, letter;
static String[] choice;
static Move mv, mv2;

   public static String lesTekst()
     {
    	String s = null;
     	BufferedReader inn= new BufferedReader(new InputStreamReader (System.in));
      	try
      	      {	s = inn.readLine(); }
	catch(IOException e){} 
      	return s;}

   public static int lesInt()
      {
      	int tall = 0;
      	String s = null; 
      	boolean done = false;

      	do
             {	s = lesTekst();   
         	try
         	    {	tall = Integer.parseInt(s);
            		done = true;   }     
         	catch(NumberFormatException e)
                    {   System.out.print("Illegal format! Enter an integer: ");
            		System.out.flush();}}
	while(!done);
        return tall;}


public static void main(String args[])
   {
      int a, b, c, d, e, f, g, h, i, j, k, l, m, c1, f1, g1,
          h1, h2, h3, b1, b2, b3, b4, b5, b6;
      String stripe;

      System.out.println("\nNeutreeko (c) 2001, 2002 J K Haugland");
      System.out.println("\nEnter 0 for standard Neutreeko");
      System.out.println("Enter 1 for the 2006 variant (reach the centre square to win)");
      System.out.println("\nOtherwise, enter board size: ");
      b2 = 0; b6 = 0;
      do {
        System.out.print("Width = ");
        b1 = lesInt();
        if (b1 == 0)
          {
            b1 = 5; b2 = 5; b6 = 1;
            System.out.println("\nWidth = 5");
            System.out.println("Height = 5");
            System.out.println("Orientation = both orthogonal and diagonal");
          }
        if (b1 == 1)
          {
            b1 = 5; b2 = 5; b6 = 5;
            System.out.println("\nWidth = 5");
            System.out.println("Height = 5");
          }
        if (b1 < 3) System.out.println("Too narrow");
        if (b1 > 7) System.out.println("Too wide");
      } while (b1 < 3 || b1 > 7);
      while (b2 < 3 || b2 > 7) {
        System.out.print("Height = ");
        b2 = lesInt();
        if (b2 < 3) System.out.println("Too low");
        if (b2 > 7) System.out.println("Too high");
      }
      if (b6 == 0) System.out.println("");
      if (b6 != 5)
      while (b6 < 1 || (b6 > 3 && (b6 > 4 || (b1 < 5 && b2 < 5)))) {
        System.out.println("Enter orientation of winning lines:");
        System.out.println("1 = both orthogonal and diagonal");
        System.out.println("2 = orthogonal only");
        System.out.println("3 = diagonal only");
        if (b1 > 4 || b2 > 4) System.out.println("4 = all equidistant");
        b6 = lesInt();
      }
      if (b1 == b2) b5 = 8; else b5 = 4;
      b3 = b1 * b2;
      b4 = (b3 * (b3 - 1) * (b3 - 2)) / 6;
      System.out.println("\nCounting positions...");
      s = new int[b3][b3][b3];
      t = new int[b4][4];
      u = new int[b4][b1][b2];
      v = new int[b4];
      w = new int[b1][b2];
      x = new byte[b4][b4];
      y = new int[25][6];
      p = new int[25];
      q = new int[b3][b5];
      piece = new char[3];
      letter = new char[7];
      choice = new String[25];
      for (a = 0; a < b3; a++)
         {
            b = a % b1; c = a / b1;
            q[a][0] = a;
            q[a][1] = (b1 - 1 - b) + b1 * c;
            q[a][2] = b + b1 * (b2 - 1 - c);
            q[a][3] = (b1 - 1 - b) + b1 * (b2 - 1 - c);
            if (b5 == 8)
               {
                  q[a][4] = c + b1 * b;
                  q[a][5] = (b1 - 1 - c) + b1 * b;
                  q[a][6] = c + b1 * (b1 - 1 - b);
                  q[a][7] = (b1 - 1 - c) + b1 * (b1 - 1 - b);
               }
         }
      d = -1;
      for (a = 0; a < b3 - 2; a++)
      for (b = a + 1; b < b3 - 1; b++)
      for (c = b + 1; c < b3; c++)
         {
            d++;
            for (e = 0; e < b1; e++)
            for (f = 0; f < b2; f++)
               u[d][e][f] = 0;
            u[d][a % b1][a / b1] = 1;
            u[d][b % b1][b / b1] = 1;
            u[d][c % b1][c / b1] = 1;
            v[d] = 0;
            if (b6 == 5) {if (a == 12 || b == 12 || c == 12) v[d] = 1;}
            else
            {
            if ((a % b1) + (c % b1) == 2 * (b % b1) && (a / b1) 
              + (c / b1) == 2 * (b / b1))
            if ((a % b1) - (c % b1) <= 2 && (c % b1) - (a % b1) 
              <= 2 && (a / b1) - (c / b1) <= 2 && (c / b1) 
              - (a / b1) <= 2) v[d] = 1;
            if (b6 == 2 && (a % b1) != (c % b1) &&
                            (a / b1) != (c / b1)) v[d] = 0;
            if (b6 == 3 && ((a % b1) == (c % b1) ||
                             (a / b1) == (c / b1))) v[d] = 0;
            if ((a % b1) + (c % b1) == 2 * (b % b1) && (a / b1) 
              + (c / b1) == 2 * (b / b1) && b6 == 4) v[d] = 1;
            }
            s[a][b][c] = d; s[a][c][b] = d; s[b][a][c] = d;
            s[b][c][a] = d; s[c][a][b] = d; s[c][b][a] = d;
            t[d][0] = a; t[d][1] = b; t[d][2] = c; t[d][3] = 2;
         }
      for (a = 0; a < b4; a++)
      for (b = 1; b < b5; b++)
         {
            if (t[a][3] == 1) t[a][3] = 2;
            c = 0;
            while (c < b3 && t[a][3] == 2)
               {
                  if (u[a][c % b1][c / b1] != u[a][q[c][b] % b1][q[c][b] / b1])
                     {
                        if (u[a][c % b1][c / b1] == 1) t[a][3] = 1;
                        else t[a][3] = 0;
                     }
                  c++;
               }
            if (t[a][3] == 2) t[a][3] = 1;
         }
      j = 0;
      for (a = 0; a < b4; a++)
      for (b = 0; b < b4; b++)
         {
            x[a][b] = 124;                  // default value
            if (v[b] == 1) x[a][b] = -120;  // finished game - 0 moves left
            if (v[a] == 1) x[a][b] = 126;   // default value for illegal positions
            if (u[a][t[b][0] % b1][t[b][0] / b1] == 1 ||
                u[a][t[b][1] % b1][t[b][1] / b1] == 1 ||
                u[a][t[b][2] % b1][t[b][2] / b1] == 1) x[a][b] = 126;
            if (x[a][b] == -120)
               {
                  j++;
                  if (j % 100000 == 0) System.out.print("-");
               }
         }
      System.out.println("0  "+j);
      c = -119;
      do                                // find all positions with c+120 moves left
      {
      j = 0;                            // number of such positions
      for (a = 0; a < b4; a++)
      if (t[a][3] == 1)
      for (b = 0; b < b4; b++)
      {
      if (x[a][b] == 124)               // legal and not already assigned
      {
         stop : {
            for (k = 0; k < 3; k++)
            {
            d = t[a][k] % b1; e = t[a][k] / b1;
            for (f = -1; f <= 1; f++)
            for (g = -1; g <= 1; g++)
            if (f * f + g * g > 0)
            if (d + f >= 0 && d + f < b1 && e + g >= 0 && e + g < b2)
            if (u[a][d+f][e+g] == 0 && u[b][d+f][e+g] == 0)
               {
                  f1 = f; g1 = g;
                  while (d + f1 + f >= 0 && d + f1 + f < b1 &&
                         e + g1 + g >= 0 && e + g1 + g < b2 &&
                         u[a][d+f1+f][e+g1+g] == 0 &&
                         u[b][d+f1+f][e+g1+g] == 0)
                     { f1 += f; g1 += g; }
                  for (h = 0; h < 3; h++) p[h] = t[a][h];
                  p[k] = d + f1 + b1 * (e + g1);
                  h = s[p[0]][p[1]][p[2]];
                  if (c % 2 == 0)
                     {
                        if (x[b][h] < c) x[a][b] = (byte)c;
                        else
                           {
                              x[a][b] = 124;
                              break stop;
                           }
                     }
                  else
                     {
                        if (x[b][h] == c - 1)
                           {
                              x[a][b] = (byte)c;
                              break stop;
                           }
                     }
               }
            }
         }
      if (x[a][b] == c)
         {
            j++;
            if (j % 100000 == 0) System.out.print("-");
            for (d = 1; d < b5; d++)
               {
                  e = s[q[t[a][0]][d]][q[t[a][1]][d]][q[t[a][2]][d]];
                  f = s[q[t[b][0]][d]][q[t[b][1]][d]][q[t[b][2]][d]];
                  if (x[e][f] != c)
                     {
                        x[e][f] = (byte)c;
                        j++;
                        if (j % 100000 == 0) System.out.print("-");
                     }
               }
         }
      }
      }
      System.out.println((c+120)+"  "+j);
      c++;
      }
      while (j > 0);
      for (a = 0; a < b4; a++)
      for (b = 0; b < b4; b++)
         if (x[a][b] == 124) j++;
      System.out.println("\nNumber of draws: "+j);

      piece[0] = 'o'; piece[1] = ' '; piece[2] = 'x';
      letter[0] = 'A'; letter[1] = 'B';
      letter[2] = 'C'; letter[3] = 'D';
      letter[4] = 'E'; letter[5] = 'F'; letter[6] = 'G';

      System.out.println("\nPosition(s) leading to maximum length perfect play:");
      for (a = 0; a < b4; a++)
      if (t[a][3] == 1)
      for (b = 0; b < b4; b++)
      if (x[a][b] == c - 2)
         {
            System.out.print("x -");
            for (d = 0; d < 3; d++)
               System.out.print(" "+letter[t[a][d] % b1]+(1+t[a][d] / b1));
            System.out.print("   o -");
            for (d = 0; d < 3; d++)
               System.out.print(" "+letter[t[b][d] % b1]+(1+t[b][d] / b1));
            System.out.println("");
         }

      if (b1 == 5 && b2 == 5 && b6 == 1)
        { a = s[1][3][17]; b = s[7][21][23]; }
      else if (b6 == 5)
        { a = s[2][15][19]; b = s[5][9][22]; }
      else
        { System.out.println("\n(This may not be a suitable opening position)");
          a = s[0][2][b3 - 2];
          b = s[1][b3 - 3][b3 - 1]; }
      for (c = 0; c < b1; c++)
      for (d = 0; d < b2; d++)
         w[c][d] = u[a][c][d] - u[b][c][d];

      mv = new Move();

      stripe = "\n +";
      for (c = 0; c < b1; c++) stripe += "---+";
      while (x[a][b] > -120)
        {
          System.out.println(stripe);
          for (d = b2 - 1; d >= 0; d--)
            {
              System.out.print((d+1)+"|");
              for (c = 0; c < b1; c++)
                System.out.print(" "+piece[1+w[c][d]]+" |");
              System.out.println(stripe);
            }
          for (c = 0; c < b1; c++) System.out.print("   "+letter[c]);
          System.out.println("");
          System.out.println("");
          j = 0;
          if (x[a][b] == 126) System.out.println("Illegal position"); else
          for (k = 0; k < 3; k++)
          {
          d = t[a][k] % b1; e = t[a][k] / b1;
          for (f = -1; f <= 1; f++)
          for (g = -1; g <= 1; g++)
          if (f * f + g * g > 0)
          if (d + f >= 0 && d + f < b1 && e + g >= 0 && e + g < b2)
          if (w[d + f][e + g] == 0)
            {
              f1 = f; g1 = g;
              while (d + f1 + f >= 0 && d + f1 + f < b1 &&
                     e + g1 + g >= 0 && e + g1 + g < b2 &&
                     w[d + f1 + f][e + g1 + g] == 0)
                { f1 += f; g1 += g; }
              for (h = 0; h < 3; h++) p[h] = t[a][h];
              p[k] = d + f1 + b1 * (e + g1);
              h = s[p[0]][p[1]][p[2]];
              j++;
              choice[j] = ". "+letter[d]+(e+1)+" -> "+letter[d+f1]
                        +(e+g1+1)+" : ";
              if (x[b][h] == 124) choice[j] += "Draw";
              else
                {
                  if (x[b][h] % 2 == 0) choice[j] += "Win";
                    else choice[j] += "Loss";
                  if (x[b][h] > -120) choice[j] += " in "+
                    (x[b][h]+121)+" moves";
                }
              y[j][0] = d; y[j][1] = e; y[j][2] = d+f1;
              y[j][3] = e+g1; y[j][4] = h; y[j][5] = 120 + (int)x[b][h];
              if (y[j][5] % 2 == 0)
                y[j][5] = y[j][5] - 244;
              else y[j][5] = 244 - y[j][5];
            }
          }
          for (c = 1; c <= j; c++) p[c] = c;
          for (c = 1; c < j; c++)
          for (d = c + 1; d <= j; d++)
            if (y[p[c]][5] > y[p[d]][5])
              {
                e = p[c];
                p[c] = p[d];
                p[d] = e;
              }
          for (c = 1; c <= j; c++)
          System.out.println(c+choice[p[c]]);
          if (mv.prev != null)
            System.out.println("77. Retract last move");
          if ((b1 == 5 && b2 == 5 && b6 == 1) || (b6 == 5))
            System.out.println("88. Back to start");
          System.out.println("99. Enter new position");
          do {
            System.out.print("Enter alternative: ");
            d = lesInt(); }
          while (d != 99 && (d < 1 || d > j) && (d != 88 ||
            b1 != 5 || b2 != 5 || b6 == 2 || b6 == 3 || b6 == 4) && (d != 77 || mv.prev == null));
          if (d == 77)
            {
              b = a; a = mv.z1;
              for (c = 0; c < b1; c++)
              for (d = 0; d < b2; d++) w[c][d] = -w[c][d];
              piece[1] = piece[0]; piece[0] = piece[2];
              piece[2] = piece[1]; piece[1] = ' ';

              w[mv.x1][mv.y1] = 1;
              w[mv.x2][mv.y2] = 0;
              mv = mv.prev;
            }
          else if (d == 88)
            {
              a = s[1][3][17]; b = s[7][21][23];
              if (b6 == 5) { a = s[2][15][19]; b = s[5][9][22]; }
              for (c = 0; c < b1; c++)
              for (d = 0; d < b2; d++)
                w[c][d] = u[a][c][d] - u[b][c][d];
              piece[0] = 'o'; piece[1] = ' '; piece[2] = 'x';
              mv = new Move();
            }
          else if (d == 99)
            {
              do {
                System.out.println("Enter one "+b1+
                  "-digit number for each row");
                System.out.println("0 = blank; 1 = 'x' (plays first); 2 = 'o'");
                for (e = 0; e < b1; e++)
                for (f = 0; f < b2; f++)
                  w[e][f] = 0;
                for (e = b2 - 1; e >= 0; e--)
                  {
                    f = lesInt();
                    for (g = b1 - 1; g >= 0; g--)
                      {
                        w[g][e] = f % 10;
                        f = f / 10;
                      }
                    for (f = 0; f < b1; f++)
                      if (w[f][e] == 2) w[f][e] = -1;
                  }
                h1 = 0; h2 = 0; h3 = 0;
                for (e = 0; e < b1; e++)
                for (f = 0; f < b2; f++)
                  {
                    if (w[e][f] == 0) h1++;
                    if (w[e][f] == 1) h2++;
                    if (w[e][f] == -1) h3++;
                  }
                if (h1 != b3 - 6) System.out.println
                  ("Error: "+h1+" blanks (should be "+(b3-6)+")");
                if (h2 != 3) System.out.println
                  ("Error: "+h2+" x's (should be 3)");
                if (h3 != 3) System.out.println
                  ("Error: "+h3+" o's (should be 3)");
              }
              while (h1 != b3 - 6 || h2 != 3 || h3 != 3);
              h1 = 0;
              while (w[h1 % b1][h1 / b1] <= 0) h1++;
              h2 = h1 + 1;
              while (w[h2 % b1][h2 / b1] <= 0) h2++;
              h3 = h2 + 1;
              while (w[h3 % b1][h3 / b1] <= 0) h3++;
              a = s[h1][h2][h3];
              h1 = 0;
              while (w[h1 % b1][h1 / b1] >= 0) h1++;
              h2 = h1 + 1;
              while (w[h2 % b1][h2 / b1] >= 0) h2++;
              h3 = h2 + 1;
              while (w[h3 % b1][h3 / b1] >= 0) h3++;
              b = s[h1][h2][h3];
              piece[0] = 'o'; piece[1] = ' '; piece[2] = 'x';
              mv = new Move();
            }
          else
            {
              c = p[d];
              mv2 = new Move();
              mv2 = mv;
              mv = new Move();
              mv.prev = mv2;
              mv.x1 = y[c][0]; mv.y1 = y[c][1];
              mv.x2 = y[c][2]; mv.y2 = y[c][3];
              mv.z1 = a; a = b; b = y[c][4];

              w[y[c][0]][y[c][1]] = 0;
              w[y[c][2]][y[c][3]] = 1;
              for (c = 0; c < b1; c++)
              for (d = 0; d < b2; d++) w[c][d] = -w[c][d];
              piece[1] = piece[0]; piece[0] = piece[2];
              piece[2] = piece[1]; piece[1] = ' ';
            }
        }
      System.out.println(stripe);
      for (d = b2 - 1; d >= 0; d--)
        {
          System.out.print((d+1)+"|");
          for (c = 0; c < b1; c++)
            System.out.print(" "+piece[1+w[c][d]]+" |");
          System.out.println(stripe);
        }
      for (c = 0; c < b1; c++) System.out.print("   "+letter[c]);
      System.out.println("");
      System.out.println("\nGAME OVER\n");
   }
}
