import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Pentago
{
	Grid grid1;
	Grid grid2;
	Grid grid3;
	Grid grid4;

	BufferedReader in;

	public Pentago()
	{
		grid1 = new Grid();
		grid2 = new Grid();
		grid3 = new Grid();
		grid4 = new Grid();

		try {
			in = new BufferedReader(new InputStreamReader(System.in));
		}
		catch(Exception e) {System.out.println("No stdin, you lose");}
	}
		
	public void startGame()
	{
		int moveCount = 0;
		while(!(grid1.isFull() && grid2.isFull() && grid3.isFull() && grid4.isFull())) {
			printBoard();
			int color = moveCount%2 + 1;
			promptMove(color);
			printBoard();
			int wincolor = winner();
			if(wincolor==1) {
				System.out.print("Black ");
				System.out.println("has won the game after "+(moveCount+1)+" moves.");
				return;
			}
			else if(wincolor==2) {
				System.out.print("White ");
				System.out.println("has won the game after "+(moveCount+1)+" moves.");
				return;
			}
			promptRotate();
			wincolor = winner();
			if(wincolor==1) {
				System.out.print("Black ");
				System.out.println("has won the game after "+(moveCount+1)+" moves.");
				return;
			}
			else if(wincolor==2) {
				System.out.print("White ");
				System.out.println("has won the game after "+(moveCount+1)+" moves.");
				return;
			}
			moveCount++;
		}
		System.out.println("The game is a draw");
	}

	public void printBoard()
	{
		System.out.println("  a b c d e f");
		System.out.println("1 "+grid1.printRow(1)+grid2.printRow(1));
		System.out.println("2 "+grid1.printRow(2)+grid2.printRow(2));
		System.out.println("3 "+grid1.printRow(3)+grid2.printRow(3));
		System.out.println("4 "+grid3.printRow(1)+grid4.printRow(1));
		System.out.println("5 "+grid3.printRow(2)+grid4.printRow(2));
		System.out.println("6 "+grid3.printRow(3)+grid4.printRow(3));
		System.out.println();
		System.out.println("Sections |1|2|");
		System.out.println("         |3|4|");
		System.out.println();
	}

	public void promptMove(int color)
	{
		boolean rval = false;

		while(!rval) {
			int realy = 0;
			String move = null;
			char x='.';
			if(color==1) {
				System.out.print("Black, ");
			}
			else {
				System.out.print("White, ");
			}
			System.out.print("enter move (letter,number): ");
			try {
				move = in.readLine();
				x = move.charAt(0);
				char y = move.charAt(1);
				realy = Integer.parseInt(y+"");
			}
			catch(Exception e) {
				move = null;
			}
			if(move!=null) {
				Grid near = grid1;
				Grid far = grid2;
				if(realy>3) {
					near = grid3;
					far = grid4;
					realy = realy-3;
				}
				if(x=='a') {
					rval = near.play(1,realy,color);
				}
				else if(x=='b') {
					rval = near.play(2,realy,color);
				}
				else if(x=='c') {
					rval = near.play(3,realy,color);
				}
				else if(x=='d') {
					rval = far.play(1,realy,color);
				}
				else if(x=='e') {
					rval = far.play(2,realy,color);
				}
				else if(x=='f') {
					rval = far.play(3,realy,color);
				}
			}
			if(!rval) {
				System.out.println("Invalid move, (example: a4)");
				System.out.println();
				printBoard();
			}				
		}
	}

	public void promptRotate()
	{
		boolean rval = false;

		while(!rval) {
			System.out.print("Rotate which grid (1-4) and direction (+ clockwise, - anticlockwise): ");
			int grid = 0;
			boolean clockwise = false;
			try {
				String rotate = in.readLine();
				grid = Integer.parseInt(rotate.charAt(0)+"");
				rotate = rotate.substring(1).trim();
				if(rotate.startsWith("-")) {
					clockwise = false;
				}
				else if(rotate.startsWith("+")) {
					clockwise = true;
				}
				else {
					grid = -1;
				}
			}
			catch(Exception e) {;}
			Grid tmpgrid = null;
			if(grid==1) {
				tmpgrid = grid1;
			}
			else if(grid==2) {
				tmpgrid = grid2;
			}
			else if(grid==3) {
				tmpgrid = grid3;
			}
			else if(grid==4) {
				tmpgrid = grid4;
			}
			if(tmpgrid!=null) {
				tmpgrid.rotate(clockwise);
				tmpgrid.rotate(clockwise);
				rval = true;
			}

			if(!rval) {
				System.out.println("Invalid grid or rotation, (example: 2+)");
				System.out.println();
				printBoard();
			}
		}
	}

	public int winner()
	{
		int rval = 0;
		if(winner(1)) {
			rval = 1;
		}
		else if(winner(2)) {
			rval = 2;
		}
		return(rval);
	}

	public boolean winner(int color)
	{
		return((grid1.row1[0]==color && grid1.row1[1]==color &&grid1.row1[2]==color && grid2.row1[0]==color && grid2.row1[1]==color) ||
				 (grid1.row1[1]==color && grid1.row1[2]==color &&grid2.row1[0]==color && grid2.row1[1]==color && grid2.row1[2]==color) ||
				 (grid1.row2[0]==color && grid1.row2[1]==color &&grid1.row2[2]==color && grid2.row2[0]==color && grid2.row2[1]==color) ||
				 (grid1.row2[1]==color && grid1.row2[2]==color &&grid2.row2[0]==color && grid2.row2[1]==color && grid2.row2[2]==color) ||
				 (grid1.row3[0]==color && grid1.row3[1]==color &&grid1.row3[2]==color && grid2.row3[0]==color && grid2.row3[1]==color) ||
				 (grid1.row3[1]==color && grid1.row3[2]==color &&grid2.row3[0]==color && grid2.row3[1]==color && grid2.row3[2]==color) ||
				 (grid3.row1[0]==color && grid3.row1[1]==color &&grid3.row1[2]==color && grid4.row1[0]==color && grid4.row1[1]==color) ||
				 (grid3.row1[1]==color && grid3.row1[2]==color &&grid4.row1[0]==color && grid4.row1[1]==color && grid4.row1[2]==color) ||
				 (grid3.row2[0]==color && grid3.row2[1]==color &&grid3.row2[2]==color && grid4.row2[0]==color && grid4.row2[1]==color) ||
				 (grid3.row2[1]==color && grid3.row2[2]==color &&grid4.row2[0]==color && grid4.row2[1]==color && grid4.row2[2]==color) ||
				 (grid3.row3[0]==color && grid3.row3[1]==color &&grid3.row3[2]==color && grid4.row3[0]==color && grid4.row3[1]==color) ||
				 (grid3.row3[1]==color && grid3.row3[2]==color &&grid4.row3[0]==color && grid4.row3[1]==color && grid4.row3[2]==color) ||
				 (grid1.row1[0]==color && grid1.row2[0]==color &&grid1.row3[0]==color && grid3.row1[0]==color && grid3.row2[0]==color) ||
				 (grid1.row1[1]==color && grid1.row2[1]==color &&grid1.row3[1]==color && grid3.row1[1]==color && grid3.row2[1]==color) ||
				 (grid1.row1[2]==color && grid1.row2[2]==color &&grid1.row3[2]==color && grid3.row1[2]==color && grid3.row2[2]==color) ||
				 (grid2.row1[0]==color && grid2.row2[0]==color &&grid2.row3[0]==color && grid4.row1[0]==color && grid4.row2[0]==color) ||
				 (grid2.row1[1]==color && grid2.row2[1]==color &&grid2.row3[1]==color && grid4.row1[1]==color && grid4.row2[1]==color) ||
				 (grid2.row1[2]==color && grid2.row2[2]==color &&grid2.row3[2]==color && grid4.row1[2]==color && grid4.row2[2]==color) ||
				 (grid1.row2[0]==color && grid1.row3[0]==color &&grid3.row1[0]==color && grid3.row2[0]==color && grid3.row3[0]==color) ||
				 (grid1.row2[1]==color && grid1.row3[1]==color &&grid3.row1[1]==color && grid3.row2[1]==color && grid3.row3[1]==color) ||
				 (grid1.row2[2]==color && grid1.row3[2]==color &&grid3.row1[2]==color && grid3.row2[2]==color && grid3.row3[2]==color) ||
				 (grid2.row2[0]==color && grid2.row3[0]==color &&grid4.row1[0]==color && grid4.row2[0]==color && grid4.row3[0]==color) ||
				 (grid2.row2[1]==color && grid2.row3[1]==color &&grid4.row1[1]==color && grid4.row2[1]==color && grid4.row3[1]==color) ||
				 (grid2.row2[2]==color && grid2.row3[2]==color &&grid4.row1[2]==color && grid4.row2[2]==color && grid4.row3[2]==color) ||
				 (grid1.row1[0]==color && grid1.row2[1]==color &&grid1.row3[2]==color && grid4.row1[0]==color && grid4.row2[1]==color) ||
				 (grid1.row1[1]==color && grid1.row2[2]==color &&grid2.row3[0]==color && grid4.row1[1]==color && grid4.row2[2]==color) ||
				 (grid1.row2[0]==color && grid1.row3[1]==color &&grid3.row1[2]==color && grid4.row2[0]==color && grid4.row3[1]==color) ||
				 (grid1.row2[1]==color && grid1.row3[2]==color &&grid4.row1[0]==color && grid4.row2[1]==color && grid4.row3[2]==color) ||
				 (grid2.row1[1]==color && grid2.row2[0]==color &&grid1.row3[2]==color && grid3.row1[1]==color && grid3.row2[0]==color) ||
				 (grid2.row1[2]==color && grid2.row2[1]==color &&grid2.row3[0]==color && grid3.row1[2]==color && grid3.row2[1]==color) ||
				 (grid2.row2[1]==color && grid2.row3[0]==color &&grid3.row1[2]==color && grid3.row2[1]==color && grid3.row3[0]==color) ||
				 (grid2.row2[2]==color && grid2.row3[1]==color &&grid4.row1[0]==color && grid3.row2[2]==color && grid3.row3[1]==color));
	}

	class Grid
	{
		int[] row1;
		int[] row2;
		int[] row3;

		public Grid()
		{
			row1 = new int[3];
			row2 = new int[3];
			row3 = new int[3];
		}

		public boolean play(int x, int y, int color)
		{
			boolean rval = false;
			if(!(x<0 || x>3 || y<0 || y>3)) {
				if(y==1 && row1[x-1]==0) {
					row1[x-1]=color;
					rval = true;
				}
				else if(y==2 && row2[x-1]==0) {
					row2[x-1]=color;
					rval = true;
				}
				else if(y==3 && row3[x-1]==0) {
					row3[x-1]=color;
					rval = true;
				}
			}
			return(rval);
		}

		public String printRow(int row)
		{
			StringBuffer rval = new StringBuffer();
			int[] tmprow = row1;
			if(row==2) {
				tmprow = row2;
			}
			else if(row==3) {
				tmprow = row3;
			}
			for(int x=0;x<3;x++) {
				if(tmprow[x]==0) {
					rval.append(". ");
				}
				else if(tmprow[x]==1) {
					rval.append("x ");
				}
				else {
					rval.append("o ");
				}
			}
			return(rval.toString());
		}

		public void rotate(boolean clockwise)
		{
			if(clockwise) {
				int tmp = row2[0];
				row2[0] = row3[0];
				row3[0] = row3[1];
				row3[1] = row3[2];
				row3[2] = row2[2];
				row2[2] = row1[2];
				row1[2] = row1[1];
				row1[1] = row1[0];
				row1[0] = tmp;
			}
			else {
				int tmp = row2[0];
				row2[0] = row1[0];
				row1[0] = row1[1];
				row1[1] = row1[2];
				row1[2] = row2[2];
				row2[2] = row3[2];
				row3[2] = row3[1];
				row3[1] = row3[0];
				row3[0] = tmp;
			}
		}

		public boolean isFull()
		{
			return(row1[0]!=0 && row1[1]!=0 && row1[2]!=0 && row2[0]!=0 && row2[1]!=0 && row2[2]!=0 && row3[0]!=0 && row3[1]!=0 && row3[2]!=0);
		}
	}


	public static void main(String[] args)
	{
		Pentago game = new Pentago();
		game.startGame();
	}
}

