
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;

public class ComradesFrame implements MouseListener, ActionListener, FocusListener
{
    BoardPanel BOARD_PANEL;
    Font chess_font;
    Font chess_font_small;
    String FONT_FILE_NAME;
    int SIZE;
    BoardPosition BOARD_POSITION;
    boolean REVERSE = false;
    JFrame j_frame;
    JTextArea TEXT_INFO;
    JScrollPane TEXT_INFO_JSP;
    JTextField FEN_AREA;
    JButton FEN_BUTTON;
    boolean POSITION_SEND = false;
    boolean SET_UP = false;
    boolean LOAD_INSTANCE = false;
    boolean[] INSTANCES_ON_COPY;
    int NUMBER_OF_MOVES = 0;
    int COMMUNICATOR_COUNT;
    Communicator[] COMMUNICATOR_LIST;
    CommunicatorInstance[] INSTANCES;
    int instances;
    boolean READY_OK = false;
    boolean CHANGING_INSTANCES;
    JButton LOAD_BUTTON, DEFAULTS_BUTTON;
    Box INSTANCE_BOX;
    Color WHITE_PIECES, BLACK_PIECES, LIGHT_SQUARES, DARK_SQUARES;
    Color BACK_GROUND;
    Color CASTLING_COLOR, MOVE_ARROWS, YELLOW_BUTTON, CLICKED_COLOR;
    Color WHITE_MOVE_INDICATOR, BLACK_MOVE_INDICATOR, EN_PASSANT_COLOR;
    boolean WHITE_ALL_OUTLINE, BLACK_ALL_OUTLINE;
    boolean WHITE_HALF_OUTLINE, BLACK_HALF_OUTLINE;
    boolean WHITE_MATERIAL_OUTLINE, BLACK_MATERIAL_OUTLINE;
    Color SMALL_WHITE_PIECES, SMALL_BLACK_PIECES, SMALL_LIGHT_SQUARES, SMALL_DARK_SQUARES;
    Color SMALL_BACK_GROUND, SMALL_WHITE_MOVE_INDICATOR, SMALL_BLACK_MOVE_INDICATOR, SMALL_EN_PASSANT_COLOR;
    boolean SMALL_WHITE_ALL_OUTLINE, SMALL_BLACK_ALL_OUTLINE;
    boolean SMALL_WHITE_HALF_OUTLINE, SMALL_BLACK_HALF_OUTLINE;
    boolean SMALL_WHITE_MATERIAL_OUTLINE, SMALL_BLACK_MATERIAL_OUTLINE;
    JPanel MOVE_PANEL;

    public ComradesFrame ()
    {
	SetColors ();
	OnLoadComradesOptions ();
	SIZE = 40;
	MOVE_PANEL = new JPanel (); // order
	BOARD_POSITION = new BoardPosition (this);
	String FEN_STRING = BOARD_POSITION.GetFEN ();
	BOARD_PANEL = new BoardPanel (this);
	BOARD_PANEL.setSize (10 * SIZE, 10 * SIZE);
	BOARD_PANEL.addMouseListener (this);
	MakeFrame ();
	FEN_AREA.setText (FEN_STRING);
	this.redraw();
	COMMUNICATOR_COUNT = 0;
	COMMUNICATOR_LIST = new Communicator[256]; // limit
	instances = 0;
	INSTANCES = new CommunicatorInstance[256]; // limit
	INSTANCES_ON_COPY = new boolean[256];
	for (int i = 0; i < 256; i++)
	    INSTANCES_ON_COPY[i] = false;
	OnLoadCommunicators ();
    }
    
    public void SetColors ()
    {
	WHITE_PIECES = new Color (250, 240, 225);
        BLACK_PIECES = new Color (25, 15, 10);
	LIGHT_SQUARES = new Color (150, 170, 190);
        DARK_SQUARES = new Color (140, 120, 100);
	BACK_GROUND = new Color (180, 180, 180);
	CASTLING_COLOR = new Color (128, 96, 64);
        MOVE_ARROWS = new Color (32, 32, 255);
        YELLOW_BUTTON = Color.yellow;
        CLICKED_COLOR = Color.red;
        WHITE_MOVE_INDICATOR = Color.white;
        BLACK_MOVE_INDICATOR = Color.black;
        EN_PASSANT_COLOR = Color.orange;
	WHITE_ALL_OUTLINE = BLACK_ALL_OUTLINE = false;
	WHITE_HALF_OUTLINE = BLACK_HALF_OUTLINE = false;
	WHITE_MATERIAL_OUTLINE = BLACK_MATERIAL_OUTLINE = false;
	SMALL_WHITE_PIECES = Color.white;
	SMALL_BLACK_PIECES = Color.black;
	SMALL_LIGHT_SQUARES = Color.white;
	SMALL_DARK_SQUARES = Color.cyan;
	SMALL_BACK_GROUND = new Color (230, 190, 180);
	SMALL_WHITE_MOVE_INDICATOR = Color.white;
	SMALL_BLACK_MOVE_INDICATOR = Color.black;
	SMALL_EN_PASSANT_COLOR = Color.orange;
	SMALL_WHITE_ALL_OUTLINE = true;
	SMALL_BLACK_ALL_OUTLINE = false;
	SMALL_WHITE_HALF_OUTLINE = false;
	SMALL_BLACK_HALF_OUTLINE = false;
	SMALL_WHITE_MATERIAL_OUTLINE = true;
	SMALL_BLACK_MATERIAL_OUTLINE = false;
	FONT_FILE_NAME = new String ("MERIFONT.TTF"); // HACK
    }

    public void redraw ()
    {
	if (!READY_OK)
	    return;
	BOARD_PANEL.repaint();
	TEXT_INFO.repaint ();
	JScrollBar JSB = TEXT_INFO_JSP.getVerticalScrollBar ();
	JSB.setValue (JSB.getMaximum () - 12); // HACK
	JSB.repaint ();
    }
    

////////////////////////////////////////////////////////////////

    public void AdditionalCommunicator (Communicator COMM)
    {
	COMMUNICATOR_LIST[COMMUNICATOR_COUNT++] = COMM;
	TellInfo ("Additional applied for " + COMM.id);
    }

    public void DeleteUnNeededCommunicator (Communicator COMM)
    {
	int i, j;
	for (i = 0; i < COMMUNICATOR_COUNT; i++)
	    if (COMMUNICATOR_LIST[i].id.equals (COMM.id))
		break;
	for (j = COMMUNICATOR_COUNT - 1; j > i; j--)
	    COMMUNICATOR_LIST[j - 1] = COMMUNICATOR_LIST[j];
	COMMUNICATOR_COUNT--;
	TellInfo ("Delete unneeded " + COMM.id);
    }

    public void CommunicatorLineStartUp (Communicator COMM, String S)
    {
	if (S.startsWith ("id "))
	    {
		COMM.id = new String (S.substring (3));
		return;
	    }
	if (S.equals ("ici"))
	    {
		COMM.ICI = true;
		return;
	    }
	if (S.equals ("can MonteCarlo"))
	    {
		COMM.COMRADES_MONTE_CARLO = true;
		return;
	    }
	if (S.startsWith ("Path"))
	    {
		COMM.path = new String (S.substring (5));
		return;		
	    }
	// uggh, UCI allows spaces in names :( // demur StringTokenizer
	int u;
	String NAME = null, TYPE = null, VALUE = null;
	u = S.indexOf (" check");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("check");
		VALUE = S.substring (u + 7);
	    }
	u = S.indexOf (" spin");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("spin");
		VALUE = S.substring (u + 6);
	    }
	u = S.indexOf (" button");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("button");
		VALUE = S.substring (u + 8);
	    }
	u = S.indexOf (" combo");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("combo");
		VALUE = S.substring (u + 7);
	    }
	u = S.indexOf (" string");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("string");
		VALUE = S.substring (u + 8);
	    }
	u = S.indexOf (" file");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("file");
		VALUE = S.substring (u + 6);
	    }
	u = S.indexOf (" directory-multi-reset");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("directory-multi-reset");
		VALUE = S.substring (u + 23);
	    }
	else
	    {
		u = S.indexOf (" directory");
		if (u != -1)
		    {
			NAME = S.substring (0, u);
			TYPE = new String ("directory");
			VALUE = S.substring (u + 11);
		    }
	    }
	u = S.indexOf (" binary");
	if (u != -1)
	    {
		NAME = S.substring (0, u);
		TYPE = new String ("binary");
		VALUE = S.substring (u + 8);
	    }
	COMM.OPT_NAME[COMM.opt_count] = new String (NAME);
	COMM.OPT_TYPE[COMM.opt_count] = new String (TYPE);
	COMM.OPT_VALUE[COMM.opt_count++] = new String (VALUE);
    }

    public void CommunicatorDataLoad (String S)
    {
	File file = new File (S);
	if (!file.exists ())
	    {
		TellInfo ("Defunct file: " + S);
		return;
	    }
	try
	    {
		FileReader FR = new FileReader (file);
		BufferedReader BR = new BufferedReader (FR);
                TellInfo ("Reading " + S);
		Communicator COMM = new Communicator (S, this, false);
		while (!BR.ready ())
		    COMM.SleepFor (10); // HACK
		while (BR.ready ())
		    CommunicatorLineStartUp (COMM, BR.readLine ());
		BR.close ();
		AdditionalCommunicator (COMM);
	    }
	catch (IOException io_exc)
	    {
		TellInfo ("No dispensation unto file: " + S);
	    }
    }

    public void OnLoadCommunicators ()
    {
	File file = new File ("Comrades.StartUp");
	if (!file.exists ())
	    {
		TellInfo ("No emergence for Comrades.StartUp");
		return;
	    }
	try
	    {
		FileReader FR = new FileReader (file);
		BufferedReader BR = new BufferedReader (FR);
                TellInfo ("Reading Comrades.StartUp file");
		while (BR.ready ())
		    CommunicatorDataLoad (BR.readLine ());
		BR.close ();
	    }
	catch (IOException io_exc)
	    {
		TellInfo ("No dispensation unto Comrades.StartUp file");
	    }
    }

    public void DoComradesOption (String S)
    {
	StringTokenizer ST = new StringTokenizer (S);
	String N = ST.nextToken ();
	String V = ST.nextToken ();
	if (N.equals ("WhitePieces"))
	    WHITE_PIECES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("BlackPieces"))
	    BLACK_PIECES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("LightSquares"))
	    LIGHT_SQUARES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("DarkSquares"))
	    DARK_SQUARES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("BackGround"))
	    BACK_GROUND = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("CastlingColor"))
	    CASTLING_COLOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("EnPassantColor"))
	    EN_PASSANT_COLOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("MoveArrows"))
	    MOVE_ARROWS = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("YellowButton"))
	    YELLOW_BUTTON = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("WhiteMoveIndicator"))
	    WHITE_MOVE_INDICATOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("BlackMoveIndicator"))
	    BLACK_MOVE_INDICATOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("WhiteAllOutline"))
	    WHITE_ALL_OUTLINE = V.equals ("true");
	if (N.equals ("BlackAllOutline"))
	    BLACK_ALL_OUTLINE = V.equals ("true");
	if (N.equals ("WhiteHalfOutline"))
	    WHITE_HALF_OUTLINE = V.equals ("true");
	if (N.equals ("BlackHalfOutline"))
	    BLACK_HALF_OUTLINE = V.equals ("true");
	if (N.equals ("WhiteMaterialOutline"))
	    WHITE_MATERIAL_OUTLINE = V.equals ("true");
	if (N.equals ("BlackMaterialOutline"))
	    BLACK_MATERIAL_OUTLINE = V.equals ("true");

	if (N.equals ("SmallWhitePieces"))
	    SMALL_WHITE_PIECES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallBlackPieces"))
	    SMALL_BLACK_PIECES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallLightSquares"))
	    SMALL_LIGHT_SQUARES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallDarkSquares"))
	    SMALL_DARK_SQUARES = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallBackGround"))
	    SMALL_BACK_GROUND = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallEnPassantColor"))
	    SMALL_EN_PASSANT_COLOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallWhiteMoveIndicator"))
	    SMALL_WHITE_MOVE_INDICATOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallBlackMoveIndicator"))
	    SMALL_BLACK_MOVE_INDICATOR = new Color (Integer.valueOf (V).intValue (), true);
	if (N.equals ("SmallWhiteAllOutline"))
	    SMALL_WHITE_ALL_OUTLINE = V.equals ("true");
	if (N.equals ("SmallBlackAllOutline"))
	    SMALL_BLACK_ALL_OUTLINE = V.equals ("true");
	if (N.equals ("SmallWhiteHalfOutline"))
	    SMALL_WHITE_HALF_OUTLINE = V.equals ("true");
	if (N.equals ("SmallBlackHalfOutline"))
	    SMALL_BLACK_HALF_OUTLINE = V.equals ("true");
	if (N.equals ("SmallWhiteMaterialOutline"))
	    SMALL_WHITE_MATERIAL_OUTLINE = V.equals ("true");
	if (N.equals ("SmallBlackMaterialOutline"))
	    SMALL_BLACK_MATERIAL_OUTLINE = V.equals ("true");
	if (N.equals ("FontFile"))
	    FONT_FILE_NAME = new String (V);
    }

    public void OnLoadComradesOptions ()
    {
	File file = new File ("Comrades.Default.Options");
	if (!file.exists ())
	    {
		// TellInfo ("No emergence for Comrades.Default.Options");
		return;
	    }
	try
	    {
		FileReader FR = new FileReader (file);
		BufferedReader BR = new BufferedReader (FR);
                // TellInfo ("Reading Comrades.Default.Options file");
		while (!BR.ready ())
		    Thread.sleep (10);
		while (BR.ready ())
		    DoComradesOption (BR.readLine ());
		BR.close ();
	    }
	catch (IOException io_exc)
	    {
	    }
	catch (InterruptedException int_exc) // HACK
	    {
	    }
    }


    public void SaveApplyStartUp ()
    {
	try
	    {
		FileWriter FW = new FileWriter ("Comrades.StartUp");
		BufferedWriter BW = new BufferedWriter (FW);
		PrintWriter PW = new PrintWriter (BW, true);
		for (int i = 0; i < COMMUNICATOR_COUNT; i++)
		    PW.println (COMMUNICATOR_LIST[i].id);
		PW.close ();
		TellInfo ("Applied to Comrades.StartUp");
	    }
	catch (IOException io_exc)
	    {
		TellInfo ("Error for Comrades.StartUp");
	    }
    }

////////////////////////////////////////////////////////////////

    public void AttendMove (BoardPosition BP, int w, boolean advance, boolean ReDraw)
    {
	if (w > BP.COUNT_OF_LEGAL_MOVES || w < 0)
	    return;	
	BP.MakeMove (w);
	BP.MakeNormal ();
	if (ReDraw)
	    FEN_AREA.setText (BP.GetFEN ());
    }

    public void AttendMoveNew (BoardPosition BP, TypeMove tm, boolean ReDraw)
    {
	BP.MakeMove32 (tm.move, tm.fancy); // advance ?
	BP.MakeNormal ();
	if (ReDraw)
	    FEN_AREA.setText (BP.GetFEN ());
    }

    public void DisAttendMoveNew (BoardPosition BP, TypeMove tm, boolean ReDraw)
    {
	//	BP.UnMakeMove32 (tm.move); // advance ?
	BP.MakeNormal ();
	if (ReDraw)
	    FEN_AREA.setText (BP.GetFEN ());
    }

    public void AbruptBack ()
    {
	MoveTree MT = BOARD_POSITION.MOVE_TREE;
	if (MT.NOW == MT.ROOT)
	    return;
	MT.JumpToNode (MT.NOW.MainLineParent); // value for Instances
    }

    public void AbruptForward ()
    {
	MoveTree MT = BOARD_POSITION.MOVE_TREE;
	if (MT.NOW.getChildCount () == 0)
	    return;
	HaltInstances ();
	AttendMoveNew (BOARD_POSITION, MT.NOW.mainline, true);
	BOARD_PANEL.repaint ();
	BoardPositionChanged ();
	EquipInstances ();
    }

    public void TryMove (int cx, int cy, int cb, int x, int y, int b, BoardPosition BP)
    {
	if (cx > 8 || cx < 1 || cy > 8 || cy < 1 ||
	    x < 1 || x > 8 || y < 1 || y > 8)
	    return;
	if (cx == x && cy == y)
	    return; // HACK
	cx--;
	cy--;
	x--; // morph
	y--;
	int m = cx + (cy << 3) + (x << 6) + (y << 9);
	for (int i = 0; i < BP.COUNT_OF_LEGAL_MOVES; i++)
	    {
		int mv = BP.move_list[i];
		if (m == (mv & 07777))
		    {
			if ((mv >> 19) != 0 && cb != 1 && (mv >> 19) != (b + 1))
			    continue;
			HaltInstances ();
			AttendMove (BP, i, true, true);
			BoardPositionChanged ();
			EquipInstances ();
			return;
		    }
	    }
    }

////////////////////////////////////////////////////////////////

    public void GoAgain ()
    {
	for (int i = 0; i < instances; i++)
	    if (INSTANCES[i].on)
		{
		    INSTANCES[i].SendHalt ();
		    INSTANCES[i].SendGoInfinite ();
		}
    }

    public void HaltInstances ()
    {
	for (int i = 0; i < instances; i++)
	    if (INSTANCES[i].MONTE_CARLO != null)
		INSTANCES[i].MONTE_CARLO.EndMonteCarlo (); // HACK
	for (int i = 0; i < instances; i++)
	    INSTANCES_ON_COPY[i] = INSTANCES[i].on;	
	for (int i = 0; i < instances; i++)
	    if (INSTANCES[i].on)
		INSTANCES[i].SendHalt ();
    }

    public void EquipInstances ()
    {
	for (int i = 0; i < instances; i++)
	    if (INSTANCES_ON_COPY[i])
		INSTANCES[i].SendGoInfinite ();
    }

    public void NewGameInstances ()
    {
	for (int i = 0; i < instances; i++)
	    INSTANCES[i].UCI_new_game ();
    }

////////////////////////////////////////////////////////////////

    public void ExitSetUp ()
    {
	SET_UP = false;
	BOARD_POSITION.MakeNormal (); // attend
	BOARD_POSITION.NewMoveTree (this);
	BOARD_POSITION.MOVE_TREE.PaintPanel ();
	BoardPositionChanged ();
	BOARD_PANEL.CLICKED = false;
	redraw ();
	NewGameInstances ();
	EquipInstances ();
    }

    public void BoardPanelSetUp (int x, int y, int b, int c)
    {
	if (x == 9 && y == 9)
	    ExitSetUp ();
	if (x == 0 && y == 9 && c == 1)
	    {
		BOARD_POSITION.ClearBoard ();
		BOARD_PANEL.repaint ();
		return;
	    }
	if (x == 0 && y == 9 && c == 2)
	    {
		BOARD_POSITION = new BoardPosition (this); // value ?
		BOARD_PANEL.repaint ();
		return;
	    }
        if ((y == 0 || y == 9) && (x >= 1 && x <= 7))
            {
                BOARD_PANEL.CLICKED_x = x; 
                BOARD_PANEL.CLICKED_y = y;
                BOARD_PANEL.CLICKED = true;
                BOARD_PANEL.repaint ();
                return;
            }
	if (x == 0 && y == 4)
            {
                BOARD_POSITION.WTM = true;
                BOARD_PANEL.repaint ();
                return;
            }
        if (x == 0 && y == 5)
            {
                BOARD_POSITION.WTM = false;
                BOARD_PANEL.repaint ();
                return;
            }
	if (x >= 1 && x <= 8 && y >= 1 && y <= 8)
            {
                if (BOARD_PANEL.CLICKED && x == BOARD_PANEL.CLICKED_x && y == BOARD_PANEL.CLICKED_y)
                    {
                        BOARD_PANEL.CLICKED = false;
                        if (b != 1)
			    BOARD_POSITION.AT[x][y] = 0;
                        BOARD_PANEL.repaint ();
                        return;
                    }
		if (b != 1 && BOARD_POSITION.AT[x][y] != 0)
                    {
			BOARD_PANEL.CLICKED = true;
                        BOARD_PANEL.CLICKED_x = x;
                        BOARD_PANEL.CLICKED_y = y;
                        BOARD_PANEL.repaint ();
                        return;
                    }
		if (!BOARD_PANEL.CLICKED)
		    return;
                int cx = BOARD_PANEL.CLICKED_x;
                int cy = BOARD_PANEL.CLICKED_y;
                if (cy == 0)
                    BOARD_POSITION.AT[x][y] = cx - 1;
                if (cy == 9)
                    BOARD_POSITION.AT[x][y] = 1 - cx; // HACK
                if (cx >= 1 && cx <= 8 && cy >= 1 && cy <= 8)
                    {
                        BOARD_POSITION.AT[x][y] = BOARD_POSITION.AT[cx][cy];
                        BOARD_POSITION.AT[cx][cy] = 0;
                        BOARD_PANEL.CLICKED_x = x;
                        BOARD_PANEL.CLICKED_y = y;
                    }
                BOARD_PANEL.repaint ();
		return;
	    }
    }

    public void StartSetUp ()
    {
	if (SET_UP)
	    return; // HACK
	BOARD_POSITION.NewMoveTree (this);
	BOARD_POSITION.MOVE_TREE.PaintPanel ();
	REVERSE = false; // in simple
	HaltInstances ();
	SET_UP = true;
	BOARD_PANEL.CLICKED = false;
	BoardPositionChanged ();
	redraw ();
    }

    public void BoardPanelPushed (MouseEvent mou_evt)
    {
	int x = mou_evt.getX () / SIZE;
	int y = 9 - (mou_evt.getY () / SIZE); // HACK
	int b = mou_evt.getButton ();
	int c = mou_evt.getClickCount ();
	if (SET_UP)
	    {
		BoardPanelSetUp (x, y, b, c);
		return;
	    }
	if (x == 0 && y == 8 && c == 2)
	    {
		REVERSE = !REVERSE;
		BOARD_PANEL.repaint ();
		for (int i = 0; i < instances; i++)
		    INSTANCES[i].IP.repaint ();
		return;
	    }
	if (x == 0 && y == 0)
	    {
		if (BOARD_POSITION.MOVE_TREE.NOW != BOARD_POSITION.MOVE_TREE.ROOT)
		    {
			AbruptBack ();
			BOARD_PANEL.CLICKED = false;
		    }
		return;
	    }
	if (x == 9 && y == 0)
	    {
		if (BOARD_POSITION.MOVE_TREE.NOW.getChildCount () > 0)
		    {
			AbruptForward ();
			BOARD_PANEL.CLICKED = false;
		    }
		return;
	    }
	if (x < 1 || x > 8 || y < 1 || y > 8)
	    return;
	if (REVERSE)
	    {
		x = 9 - x;
		y = 9 - y;
	    }
	if (BOARD_PANEL.CLICKED)
	    {
		BOARD_PANEL.CLICKED = false;
		TryMove (BOARD_PANEL.CLICKED_x, BOARD_PANEL.CLICKED_y, BOARD_PANEL.CLICKED_b,
			 x, y, b, BOARD_POSITION);
		BOARD_PANEL.repaint ();
	    }
	else
	    {
		int p = BOARD_POSITION.AT[x][y];
		if ((BOARD_POSITION.WTM && p > 0) ||
		    (!BOARD_POSITION.WTM && p < 0))
		    {
			BOARD_PANEL.CLICKED_x = x; 
			BOARD_PANEL.CLICKED_y = y;
			BOARD_PANEL.CLICKED_b = b;
			BOARD_PANEL.CLICKED = true;
			BOARD_PANEL.repaint ();		
		    }
	    }
    }

    public void mouseEntered (MouseEvent mou_evt)
    {
	if (mou_evt.getComponent () == FEN_AREA)
	    BOARD_POSITION.MOVE_TREE.FOCUS = false;
	FEN_AREA.requestFocus ();
    }
    public void mouseExited (MouseEvent mou_evt) {}
    public void mousePressed (MouseEvent mou_evt) {}
    public void mouseReleased (MouseEvent mou_evt) {}
    public void mouseClicked (MouseEvent mou_evt)
    {
	if (mou_evt.getComponent () == BOARD_PANEL)
	    BoardPanelPushed (mou_evt);
    }

    public void BoardPositionChanged ()
    {
	for (int i = 0; i < instances; i++)
	    INSTANCES[i].ClearInformatory ();
	FEN_AREA.setText (BOARD_POSITION.GetFEN ()); // HACK
    }

    public void ParseFEN (String FEN_STRING)
    {
	HaltInstances ();
	BOARD_POSITION.SetFEN (new StringTokenizer (FEN_STRING));
	BOARD_POSITION.NewMoveTree (this);
	BOARD_POSITION.MOVE_TREE.PaintPanel ();
	BoardPositionChanged ();
	BOARD_PANEL.repaint ();
	NewGameInstances ();
	EquipInstances ();
    }

    public void LoadCommunicatorInstance (Communicator COMM)
    {
	while (LOAD_INSTANCE) // one at time
	    COMM.SleepFor (25);
	LOAD_INSTANCE = true;
	TellInfo ("Loading " + COMM.name);
	new CommunicatorInstance (COMM, this); // terminal (infinite)
    }

    public void SetupNewCommunicator (File FILE)
    {
	Communicator COMM = new Communicator (FILE.getAbsolutePath (), this, true);
	COMM.path = new String (COMM.name); // HACK
	if (!COMM.LoadCommunicator ())
	    return;
	COMM.ModifyDefaults ();
    }

    public void EnsueDefaults (Communicator COMM)
    {
	if (!COMM.LoadCommunicator ())
	    return;
	COMM.ModifyDefaults ();
    }

    public void RegisterNew ()
    {
        JFileChooser JFC;
	JFC = new JFileChooser (System.getProperty ("user.dir")); // HACK
        int Value =  JFC.showOpenDialog (JFC);
        if (Value != JFileChooser.APPROVE_OPTION)
            {
                return;
            }
        File FILE = JFC.getSelectedFile ();
        if (!FILE.exists())
            {
                TellInfo ("File does not exist");
                return;
            }
	SetupNewCommunicator (FILE);
    }

    public void MakePopUp (String S)
    {
	JPopupMenu POP_UP = new JPopupMenu (S); // S redundant
	for (int i = 0; i < COMMUNICATOR_COUNT; i++)
	    {
		CJMenuItem MENU_ITEM = new CJMenuItem (COMMUNICATOR_LIST[i]);
		MENU_ITEM.setActionCommand (S);
		MENU_ITEM.addActionListener (this);
		POP_UP.add (MENU_ITEM);
	    }
	if (S.equals ("LOAD"))
	    POP_UP.setInvoker (LOAD_BUTTON);
	if (S.equals ("DEFAULTS"))
	    POP_UP.setInvoker (DEFAULTS_BUTTON);
	POP_UP.show (POP_UP.getInvoker (), 30, 10);
    }

    public void actionPerformed (ActionEvent act_evt)
    {
	String S = act_evt.getActionCommand ();
	if (S.equals ("OPTIONS"))
	    new ComradesOptioner (this); // modal
	if (S.equals ("SetUpPosition"))
	    StartSetUp ();
	if (S.equals ("FEN"))
	    ParseFEN (FEN_AREA.getText ());
	if (S.equals ("RegisterNew"))
	    RegisterNew ();
	if (S.equals ("LOAD"))
	    LoadCommunicatorInstance (((CJMenuItem) (act_evt.getSource ())).COMM);
	if (S.equals ("DEFAULTS"))
	    {
		if ((act_evt.getModifiers () & ActionEvent.CTRL_MASK) != 0 &&
		    (act_evt.getModifiers () & ActionEvent.ALT_MASK) != 0) // HACK
		    {
			DeleteUnNeededCommunicator
			    (((CJMenuItem) (act_evt.getSource ())).COMM);
			SaveApplyStartUp ();
		    }
		else
		    EnsueDefaults (((CJMenuItem) (act_evt.getSource ())).COMM);
	    }
	if (S.equals ("ModifyDefaults"))
	    MakePopUp ("DEFAULTS");
	if (S.equals ("LoadCommunicator"))
	    MakePopUp ("LOAD");
    }

    public void ERROR (String STRING)
    {
	System.out.println (STRING);
	System.exit (123456);
    }
    
    public void InitChessFont (String S, int SIZE)
    {
	FileInputStream FIS = null;
	Font FONT = null;
	try
	    {
		FIS = new FileInputStream (S);
	    }
	catch (IOException io_e)
	    {
		ERROR ("Cannot find font file " + S);
	    }
	try
	    {
		FONT = Font.createFont (Font.TRUETYPE_FONT, FIS);
	    }
	catch (IOException io_e)
	    {
		ERROR ("IOException in font creation");
	    }
	catch (FontFormatException io_e)
	    {
		ERROR("Font format exception");
	    }
	try
	    {
		FIS.close();
	    }
	catch (IOException io_e)
	    {
		ERROR ("Failure to close fonts");
	    }
	FONT_FILE_NAME = new String (S);
	chess_font = FONT.deriveFont ((float) SIZE);
	chess_font_small = chess_font.deriveFont (16.0f); // small
    }

    public void TellInfo (String STRING)
    {
	TEXT_INFO.append (STRING + "\n");
	TEXT_INFO.setCaretPosition (TEXT_INFO.getText ().length ());
	TEXT_INFO.repaint ();
	TEXT_INFO_JSP.repaint ();
	JScrollBar JSB = TEXT_INFO_JSP.getVerticalScrollBar ();
	JSB.setValue (JSB.getMaximum ());
	JSB.repaint ();
    }

    public void focusGained (FocusEvent foc_evt)
    {
	if (BOARD_POSITION.MOVE_TREE.FOCUS)
	    BOARD_POSITION.MOVE_TREE.NOW.LABEL.requestFocus (); // HACK
    }

    public void focusLost (FocusEvent foc_evt) // empty (null)
    {
    }

    public Box Make_FEN_Box ()
    {
	Box FEN_BOX = new Box (BoxLayout.X_AXIS);
	FEN_AREA = new JTextField (50);
	FEN_AREA.setFont (new Font ("Monospaced", 0, 9));
	FEN_AREA.setEditable (true);
	FEN_AREA.addFocusListener (this); // HACK
	FEN_AREA.addMouseListener (this); // HACK
	FEN_AREA.setPreferredSize (new Dimension (410, 20));
	FEN_AREA.setMinimumSize (new Dimension (400, 20));
	FEN_BOX.add (FEN_AREA);
	FEN_AREA.setAlignmentX (0.5f);
	FEN_BUTTON = new JButton ("FEN");
	FEN_BUTTON.setMargin (new Insets (1, 3, 1, 3));
	FEN_BUTTON.setActionCommand ("FEN");
	FEN_BUTTON.addActionListener (this);
	FEN_BOX.add (FEN_BUTTON);
	FEN_BOX.setAlignmentX (0.0f); // query ?
	FEN_BOX.setPreferredSize (new Dimension (430, 20));
	FEN_BOX.setMaximumSize (new Dimension (440, 20));
	return FEN_BOX;
    }

    public JToolBar MakeToolBar ()
    {
	JToolBar TOOL_BAR = new JToolBar ();
	TOOL_BAR.setAlignmentX (0.0f); // HACK ?
	TOOL_BAR.addSeparator (); // fancy
	JButton OPTIONS_BUTTON = new JButton ("OPTIONS");
	OPTIONS_BUTTON.setActionCommand ("OPTIONS");
	OPTIONS_BUTTON.addActionListener (this);
	TOOL_BAR.add (OPTIONS_BUTTON);
	JButton REGISTER_NEW = new JButton ("RegisterNew");
	REGISTER_NEW.setActionCommand ("RegisterNew");
	REGISTER_NEW.addActionListener (this);
	TOOL_BAR.add (REGISTER_NEW);
	LOAD_BUTTON = new JButton ("Load");
	LOAD_BUTTON.setActionCommand ("LoadCommunicator");
	LOAD_BUTTON.addActionListener (this);
	TOOL_BAR.add (LOAD_BUTTON);
	DEFAULTS_BUTTON = new JButton ("Defaults");
	DEFAULTS_BUTTON.setActionCommand ("ModifyDefaults");
	DEFAULTS_BUTTON.addActionListener (this);
	TOOL_BAR.add (DEFAULTS_BUTTON);
	JButton SET_UP_BUTTON = new JButton ("SetUpPosition");
	SET_UP_BUTTON.setActionCommand ("SetUpPosition");
	SET_UP_BUTTON.addActionListener (this);
	TOOL_BAR.add (SET_UP_BUTTON);
	TOOL_BAR.setFloatable (false);
	TOOL_BAR.addSeparator ();
	return TOOL_BAR;
    }

    public void DoGraphics ()
    {
	Box LARGE_BOX = new Box (BoxLayout.X_AXIS);
	Box LEFT_BOX = new Box (BoxLayout.Y_AXIS);
	Box RIGHT_BOX = new Box (BoxLayout.Y_AXIS);
	LEFT_BOX.add (BOARD_PANEL);
	JScrollPane MOVE_PANE = new JScrollPane (MOVE_PANEL);
	MOVE_PANE.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	MOVE_PANE.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	MOVE_PANEL.setPreferredSize (new Dimension (380, 6000));
	MOVE_PANEL.setMinimumSize (new Dimension (380, 6000));
	MOVE_PANEL.setMaximumSize (new Dimension (380, 6000));
	MOVE_PANE.setPreferredSize (new Dimension (400, 250));
	MOVE_PANE.setMinimumSize (new Dimension (400, 250));
	InputMap IM = MOVE_PANE.getInputMap (JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
	IM.put (KeyStroke.getKeyStroke ("UP"), "none");
	IM.put (KeyStroke.getKeyStroke ("DOWN"), "none"); // HACK
	IM.put (KeyStroke.getKeyStroke ("LEFT"), "none");
	IM.put (KeyStroke.getKeyStroke ("RIGHT"), "none");
	LEFT_BOX.add (MOVE_PANE);

	TEXT_INFO = new JTextArea (10, 50);
	TEXT_INFO.setFont (new Font("Monospaced", 0, 12));
	TEXT_INFO.setEditable (false);
	TEXT_INFO_JSP = new JScrollPane (TEXT_INFO);
	//	LEFT_BOX.add (TEXT_INFO_JSP);

	RIGHT_BOX.add (Make_FEN_Box ());
	RIGHT_BOX.add (MakeToolBar ());
	INSTANCE_BOX = new Box (BoxLayout.Y_AXIS);
	INSTANCE_BOX.add (new EmptyPanel ());
	JScrollPane INSTANCE_BOX_PANE = new JScrollPane (INSTANCE_BOX);
	INSTANCE_BOX_PANE.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	INSTANCE_BOX_PANE.setPreferredSize (new Dimension (450, 700));
	INSTANCE_BOX_PANE.setAlignmentX (0.0f);
	RIGHT_BOX.add (INSTANCE_BOX_PANE);
	RIGHT_BOX.setPreferredSize (new Dimension (450, 700));
	LARGE_BOX.add (LEFT_BOX);
	LARGE_BOX.add (RIGHT_BOX);
	j_frame.add (LARGE_BOX);
    }

    public class EmptyPanel extends JPanel // HACK
    {
	public EmptyPanel ()
	{
	}

	public void paintComponent (Graphics G) // Font exemplary
	{
	    G.setColor (Color.cyan);
	    G.fillRect (0, 0, 500, 1000);
	    G.setColor (Color.black);
	    G.setFont (chess_font.deriveFont (20.0f));
	    char[] BUFFER = new char[1];
	    int h = 50, v = 50;
	    for (int i = 0; i < 256; i++)
		{
		    BUFFER[0] = (char) i;
		    G.drawChars (BUFFER, 0, 1, h, v);
		    h += 20;
		    if (h > 300)
			{
			    v += 20;
			    h = 50;
			}
		}
	}


	public Dimension getPreferredSize ()
	{
	    return new Dimension (400, 400);
	}
	
	public Dimension getMinimumSize ()
	{
	    return new Dimension (400, 400);
	}
    }

    public void MakeFrame ()
    {
	j_frame = new JFrame ("ComradesGUI Proto Type IIII");
	j_frame.addWindowListener
	    (new WindowAdapter()
		{
		    public void windowClosing (WindowEvent win_evt)
		    {
			System.exit (0);
		    }
		}
		);
	InitChessFont (FONT_FILE_NAME, SIZE); // void
	DoGraphics ();
	j_frame.setBackground (Color.lightGray);
	j_frame.pack ();
	j_frame.setSize (850, 675);
	j_frame.setResizable (false);
	j_frame.setVisible (true);
	READY_OK = true;
    }
}
