
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 RobboFrame implements MouseListener, ActionListener
{
    BoardPanel BOARD_PANEL;
    Font chess_font;
    int SIZE;
    BoardPosition BOARD_POSITION;
    boolean REVERSE = false;
    JFrame j_frame;
    JTextArea TEXT_INFO;
    JScrollPane TEXT_INFO_JSP;
    JTextArea FEN_AREA;
    JList ROBBO_INFO;
    JButton TOT, TRIP, JBRE;
    JButton FEN_BUTTON;
    BufferedReader ROBBO_READER = null;
    PrintWriter ROBBO_WRITER = null;
    DefaultListModel LIST_MODEL = null;
    File ROBBO_EXPLORER_FILE = null;
    File TOTAL_DIRECTORY = null;
    File TRIPLE_DIRECTORY = null;
    boolean POSITION_SEND = false;
    int NUMBER_OF_MOVES = 0;
    String[] ROBBO_LIST_STRING;
    int[] ROBBO_LIST_VALUE;
    int[] ROBBO_LIST_MOVE;
    JTextArea MOVE_LIST_TEXT_AREA;
    Highlighter.HighlightPainter HIGH_LIGHTER;
    MoveList MOVE_LIST;
    boolean READY_OK = false;

    public RobboFrame ()
    {
	BOARD_POSITION = new BoardPosition (this);
	BOARD_PANEL = new BoardPanel (this);
	MakeFrame ();
	this.redraw();
    }
    
    public void redraw ()
    {
	if (!READY_OK)
	    return;
	BOARD_PANEL.repaint();
	TEXT_INFO.repaint ();
	JScrollBar JSB = TEXT_INFO_JSP.getVerticalScrollBar ();
	JSB.setValue (JSB.getMaximum ());
	JSB.repaint ();
	MOVE_LIST_TEXT_AREA.repaint ();
	ROBBO_INFO.repaint ();
    }
    
    public boolean WaitForFact ()
    {
	while (true)
	    {
		String STRING = null;
		try
		    {
			while (!ROBBO_READER.ready ())
			    {
				try
				    {
					Thread.sleep (10);
				    }
				catch (InterruptedException int_exc)
				    {
				    }		
			    }
			STRING = ROBBO_READER.readLine ();
		    }
		catch (IOException io_exc)
		    {
			TellInfo ("Communications are bad");
		    }
		TellInfo (STRING);
		StringTokenizer ST = new StringTokenizer (STRING);
		if (!ST.hasMoreTokens ())
		    continue;
		String S = ST.nextToken ();
		if (S.equals ("Fact:"))
		    return true;
		if (S.equals ("Remand:"))
		    return false;
	    }
    }


    public void WaitForResults ()
    {
	while (true)
	    {
		String STRING = null;
		try
		    {
			while (!ROBBO_READER.ready ())
			    {
				try
				    {
					Thread.sleep (10);
				    }
				catch (InterruptedException int_exc)
				    {
				    }		
			    }
			STRING = ROBBO_READER.readLine ();
		    }
		catch (IOException io_exc)
		    {
			TellInfo ("Communications are bad");
			return;
		    }
		if (STRING.equals ("Result is not possible"))
		{
		    ResultIsNotPossible ();
		    return;
		}
		if (STRING.equals ("Complete with moves"))
		{
		    MakeListResults ();
		    return;
		}
		StringTokenizer ST = new StringTokenizer (STRING);
		String S = ST.nextToken ();
		if (S.equals ("TripleResult"))
		    continue;
		if (S.equals ("TotalResult"))
		    continue;
		if (S.equals ("Fact:"))
		    {
			TellInfo (STRING);
			continue;
		    }
		if (!S.equals ("move"))
		    {
			TellInfo (STRING);
			continue;
		    }	
		String M = ST.nextToken ();
		boolean w = ST.nextToken().equals ("TotalResult");
		int va = Integer.valueOf (ST.nextToken ()).intValue ();
		AddMoveList (M, w, va);
	    }
    }

    public void MainLine ()
    {
	ROBBO_WRITER.println ("mainline");
	ROBBO_WRITER.flush ();
	int l = MOVE_LIST.LENGTH;
	while (true)
	    {
		String STRING = null;
		try
		    {
			while (!ROBBO_READER.ready ())
			    {
				try
				    {
					Thread.sleep (10);
				    }
				catch (InterruptedException int_exc)
				    {
				    }		
			    }
			STRING = ROBBO_READER.readLine ();
		    }
		catch (IOException io_exc)
		    {
			TellInfo ("Communications are bad");
			return;
		    }
		StringTokenizer ST = new StringTokenizer (STRING);
		if (!ST.hasMoreTokens ())
		    continue;
		if (ST.nextToken ().equals ("mainline"))
		{
		    String S = ST.nextToken ();
		    while (ST.hasMoreTokens ())
			{
			    S = ST.nextToken ();
			    int mv = BOARD_POSITION.FindMove (S);
			    if (mv == -1)
				{
				    TellInfo ("Problem with finding move " + S);
				}
			    else
				{
				    MOVE_LIST.ApplyMove (mv);
				    BOARD_POSITION.MakeMove (mv);
				    BOARD_POSITION.MakeNormal ();
				}			    
			}
		    JumpThere (l);
		    return;
		}
		
		if (STRING.equals ("info string Failure in main_line"))
		{
		    TellInfo ("MainLine occurred an problem");
		    return;
		}
		else
		    TellInfo (STRING);
	    }
    }

    public void ResetMoveList ()
    {
	while (LIST_MODEL.getSize () > 0)
	    LIST_MODEL.remove (LIST_MODEL.getSize() - 1);
    }

    public void ResultIsNotPossible ()
    {
	TellInfo ("Result is not possible: no data found");
	LIST_MODEL.insertElementAt ("No moves", 0);
    }

    public void AttendMove (int w, boolean advance, boolean ReDraw)
    {
	if (w > BOARD_POSITION.COUNT_OF_LEGAL_MOVES || w < 0)
	    return;	
	BOARD_POSITION.MakeMove (w);
	if (advance)
	    {
		MOVE_LIST.ApplyMove (w);
		if (ReDraw)
		    {
			MOVE_LIST.ApplyText (MOVE_LIST_TEXT_AREA, HIGH_LIGHTER);
			MOVE_LIST_TEXT_AREA.repaint ();
		    }
	    }
	BOARD_POSITION.MakeNormal ();
    }

    public void JumpThere (int w)
    {
	if (MOVE_LIST.MAX_MOVE == 0)
	    return;
	if (w < 0)
	    w = 0;
	if (w > MOVE_LIST.MAX_MOVE)
	    w = MOVE_LIST.MAX_MOVE;
	MOVE_LIST.LENGTH = w;
	BOARD_POSITION.SetFEN (new StringTokenizer (MOVE_LIST.FEN_START));
	for (int i = 0; i < MOVE_LIST.LENGTH; i++)
	    AttendMove (MOVE_LIST.w[i], false, i == MOVE_LIST.LENGTH - 1);
	MOVE_LIST.ApplyText (MOVE_LIST_TEXT_AREA, HIGH_LIGHTER);
	BOARD_PANEL.repaint ();
    }

    public void AbruptBack ()
    {
	if (MOVE_LIST.LENGTH == 0)
	    return;
	JumpThere (MOVE_LIST.LENGTH - 1);
	SendPosition ();
    }

    public void AbruptForward ()
    {
	if (MOVE_LIST.LENGTH == MOVE_LIST.MAX_MOVE)
	    return;
	AttendMove (MOVE_LIST.w[MOVE_LIST.LENGTH], false, true);
	MOVE_LIST.LENGTH++;
	MOVE_LIST.ApplyText (MOVE_LIST_TEXT_AREA, HIGH_LIGHTER);	
	BOARD_PANEL.repaint ();
	SendPosition ();
    }

    public void AddMoveList (String S, boolean w, int va)
    {
	int mv = BOARD_POSITION.FindMove (S);
	String STRING;
	if (mv == -1)
	    {
		TellInfo ("Problem with finding move " + S);
		STRING = new String (S);
	    }
	else
	    STRING = new String (BOARD_POSITION.move_list_annotated[mv]);
	for (int i = 0; STRING.length () < 6; i++)
	    STRING += " ";
	if (!w) // TRIPLE base
	    {
		if (va == 1)
		    STRING += " Loss";
		if (va == 0)
		    STRING += " Draw";
		if (va == -1)
		    STRING += " Win";
		if (va == -100)
		    STRING += " Unknown";
		else
		    va = -va;
	    }
	else // TOTAL base
	    {
		if (va == 1)
		    {
			STRING += " Loss";
			va = -1;
		    }
		else if (va == 2)
		    {
			STRING += " Draw";
			va = 0;
		    }
		else if (va >= 3 && va < 4000)
		    {
			STRING += " Win in " + (va - 3);
			va = 4000 - va;
		    }
		else if (va >= 4000)
		    {
			STRING += " Loss in " + (va - 4096);
			va = va - 10000;
		    }
		else if (va == -100)
		    {
			STRING += " Unknown";
			va = -10000;
		    }
	    }
	ROBBO_LIST_STRING[NUMBER_OF_MOVES] = STRING;
	ROBBO_LIST_MOVE[NUMBER_OF_MOVES] = mv;
	ROBBO_LIST_VALUE[NUMBER_OF_MOVES++] = va;
    }

    public void SortListElements ()
    {
	for (int i = NUMBER_OF_MOVES - 1; i >= 0; i--)
	    {
		int j;
		String TEMP_STRING = ROBBO_LIST_STRING[i];
		int TEMP_MOVE = ROBBO_LIST_MOVE[i];
		int TEMP_VALUE = ROBBO_LIST_VALUE[i];
		for (j = i + 1; j < NUMBER_OF_MOVES; j++)
		    {
			if (ROBBO_LIST_VALUE[j] <= TEMP_VALUE)
			    break;
			ROBBO_LIST_STRING[j - 1] = ROBBO_LIST_STRING[j];
			ROBBO_LIST_MOVE[j - 1] = ROBBO_LIST_MOVE[j];
			ROBBO_LIST_VALUE[j - 1] = ROBBO_LIST_VALUE[j];
		    }
		ROBBO_LIST_STRING[j - 1] = TEMP_STRING;
		ROBBO_LIST_MOVE[j - 1] = TEMP_MOVE;
		ROBBO_LIST_VALUE[j - 1] = TEMP_VALUE;
	    }
    }
    public void MakeThisMove (int num)
    {
	if (num >= NUMBER_OF_MOVES || num < 0)
	    return;
	MOVE_LIST.ApplyMove (ROBBO_LIST_MOVE[num]);
	MOVE_LIST.ApplyText (MOVE_LIST_TEXT_AREA, HIGH_LIGHTER);
	MOVE_LIST_TEXT_AREA.repaint ();
	BOARD_POSITION.MakeMove (ROBBO_LIST_MOVE[num]);
	BOARD_PANEL.repaint ();
	SendPosition ();
    }

    public void MakeListResults ()
    {
	SortListElements ();
	for (int i = 0; i < NUMBER_OF_MOVES; i++)
	    LIST_MODEL.insertElementAt (ROBBO_LIST_STRING[i], i);
	ROBBO_INFO.setSelectedIndex (0);
	ROBBO_INFO.requestFocusInWindow ();
    }

    public void EmitPGN ()
    {
	JFrame PGN_FRAME = new JFrame ("PGN of this");
        final JTextArea JTA = new JTextArea (1, 30); /* bind final */
	JTA.setFont (new Font ("Monospaced", 0, 12));
	JTA.setEditable (false);
        JScrollPane JSP = new JScrollPane (JTA);
        JSP.getViewport ().add (JTA);
        JScrollBar VERT = JSP.getVerticalScrollBar ();
        VERT.addAdjustmentListener (new AdjustmentListener()
            { public void adjustmentValueChanged (AdjustmentEvent e) { JTA.repaint (); } }); // HACK // HACK
	JTA.setText (MOVE_LIST.DemandPGN (5)); // width
        PGN_FRAME.add (JSP);
        PGN_FRAME.setBackground (Color.lightGray);
        PGN_FRAME.pack ();
        JSP.setPreferredSize (new Dimension (500, 500));
        PGN_FRAME.setSize (600, 600); // demand
        PGN_FRAME.setResizable (false);
        PGN_FRAME.setVisible (true);
    }

    public JTextArea FilesInfoFrame ()
    {
        JFrame FILES_INFO = new JFrame ("FilesInfoFrame");
        final JTextArea JTA = new JTextArea (1, 30); /* bind final */
	JTA.setFont (new Font ("Monospaced", 0, 12));
	JTA.setEditable (false);
        JScrollPane FILES_INFO_JSP = new JScrollPane (JTA);
        FILES_INFO_JSP.getViewport ().add (JTA);
        JScrollBar FILES_INFO_VERT = FILES_INFO_JSP.getVerticalScrollBar ();
        FILES_INFO_VERT.addAdjustmentListener (new AdjustmentListener()
            { public void adjustmentValueChanged (AdjustmentEvent e) { JTA.repaint (); } }); // HACK // HACK
        FILES_INFO.add (FILES_INFO_JSP);
        FILES_INFO.setBackground (Color.lightGray);
        FILES_INFO.pack ();
        FILES_INFO_JSP.setPreferredSize (new Dimension (500, 500));
        FILES_INFO.setSize (600, 600); // demand
        FILES_INFO.setResizable (false);
        FILES_INFO.setVisible (true);
        return JTA;
    }

    public void SendFilesInfo ()
    {
        if (ROBBO_EXPLORER_FILE == null)
            {
                TellInfo ("Must have ROBBO_EXPLORER_FILE set to Inform");
                return;
            }
        JTextArea JTA = FilesInfoFrame ();
	String BUFFER = new String ("");
	int LINES = 0;
	ROBBO_WRITER.println ("files-info");
	ROBBO_WRITER.flush ();
        while (true)
            {
                String STRING = null;
                try
                    {
                        while (!ROBBO_READER.ready ())
                            {
                                try
                                    {
                                        Thread.sleep (10);
                                    }
                                catch (InterruptedException int_exc)
                                    {
                                    }           
                            }
                        STRING = ROBBO_READER.readLine ();
                    }
                catch (IOException io_exc)
                    {
                        TellInfo ("Communications are bad");
                        return;
                    }
                if (STRING.equals ("FilesInfo has completion"))
                    break;
		BUFFER += new String (STRING) + "\n";
		LINES++;
            }
	JTA.setText (BUFFER);
	JTA.setPreferredSize (new Dimension (500, 15 * LINES));
	JTA.repaint ();
    }

    public void SendPosition ()
    {
	BOARD_POSITION.MakeNormal ();
	BOARD_PANEL.repaint ();
	String FEN_STRING = BOARD_POSITION.GetFEN ();
	FEN_AREA.setText (FEN_STRING);
	NUMBER_OF_MOVES = 0;
	if (!BOARD_POSITION.IsOK ())
	    {
		ResetMoveList ();
		ResultIsNotPossible ();
		return;
	    }
	POSITION_SEND = true;
	if (ROBBO_WRITER == null)
	    {
		TellInfo ("No RobboExplorer to communicate");
		POSITION_SEND = false;
		return;
	    }
	ROBBO_WRITER.println ("fen " + FEN_STRING);
	ROBBO_WRITER.flush ();
	if (!WaitForFact ())
	    {
		ResetMoveList ();
		ResultIsNotPossible ();
		return;
	    }
	ROBBO_WRITER.println ("move-results");
	ROBBO_WRITER.flush ();
	ResetMoveList ();
	WaitForResults ();
	POSITION_SEND = false;
    }

    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 ();
	if (x == 0 && y == 0)
	    {
		AbruptBack ();
		return;
	    }
	if (x == 9 && y == 0)
	    {
		AbruptForward ();
		return;
	    }

	if ((y == 0 || y == 9) && (x >= 1 && x <= 7))
	    {
		BOARD_PANEL.CLICKED_x = x; 
		BOARD_PANEL.CLICKED_y = y;
		BOARD_PANEL.repaint ();
		return;
	    }
	if (y == 3 && x == 0)
	    {
		BOARD_PANEL.CLICKED_x = 0;
		BOARD_PANEL.CLICKED_y = 3;	
		BOARD_PANEL.repaint ();
		return;
	    }
	if (x >= 1 && x <= 8 && y >= 1 && y <= 8)
	    {
		MOVE_LIST.Clear ();
		if (BOARD_PANEL.CLICKED_x == 0 && BOARD_PANEL.CLICKED_y == 3)
		    {
			if ((y == 6 && BOARD_POSITION.WTM) || (y == 3 && !BOARD_POSITION.WTM))
			    {
				BOARD_POSITION.EnPassant = x;
				BOARD_PANEL.repaint ();
				return;
			    }
		    }
		if (x == BOARD_PANEL.CLICKED_x && y == BOARD_PANEL.CLICKED_y)
		    {
			BOARD_PANEL.CLICKED_x = 0;
			BOARD_PANEL.CLICKED_y = 0;
			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_x = x;
			BOARD_PANEL.CLICKED_y = y;
			BOARD_PANEL.repaint ();
			return;
		    }
		int cx = BOARD_PANEL.CLICKED_x;
		int cy = BOARD_PANEL.CLICKED_y;
		if (cx == 0 && cy == 0)
		    return;
		if (cy == 0)
		    BOARD_POSITION.AT[x][y] = cx - 1;
		if (cy == 9)
		    BOARD_POSITION.AT[x][y] = 1 - cx;
		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;
	    }
	if (x == 0 && y == 4)
	    {
		MOVE_LIST.Clear ();
		BOARD_POSITION.WTM = true;
		BOARD_POSITION.EnPassant = 0;
		BOARD_PANEL.repaint ();
		return;
	    }
	if (x == 0 && y == 5)
	    {
		MOVE_LIST.Clear ();
		BOARD_POSITION.WTM = false;
		BOARD_POSITION.EnPassant = 0;
		BOARD_PANEL.repaint ();
		return;
	    }
	if (x == 9 && y == 9)
	    {
		MOVE_LIST.Begin ();
		SendPosition ();
	    }
	if (x == 9 && y == 8)
	    {
		SendPosition ();
		if (MOVE_LIST.CLEAR)
		    MOVE_LIST.Begin ();
		if (BOARD_POSITION.IsOK ())
		    MainLine ();
	    }
	if (x == 9 && y == 7)
	    {
		SendPosition ();
		SendFilesInfo ();
	    }
	if (x == 0 && y == 9)
	    {
		BOARD_POSITION.ClearBoard ();
		MOVE_LIST.Clear ();
		ResetMoveList ();
		ResultIsNotPossible ();
		BOARD_PANEL.repaint ();
	    }
    }

    public void mouseEntered (MouseEvent mou_evt) {}
    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);
	if (mou_evt.getComponent () == MOVE_LIST_TEXT_AREA
	    && mou_evt.getClickCount () == 2)
	    {
		int x = mou_evt.getX ();
		int y = mou_evt.getY () / 15; // experimental
		int c = 2 * y;
		if (x >= 104) // draft
		    c++;
		if (!MOVE_LIST.WTM)
		    c--;
		JumpThere (c);
		SendPosition ();
	    }
    }

    public void ParseFEN (String FEN_STRING)
    {
	BOARD_POSITION.SetFEN (new StringTokenizer (FEN_STRING));
	BOARD_PANEL.repaint ();
	MOVE_LIST.Begin ();
	SendPosition ();
    }

    public void SaveConfig ()
    {
	try
	    {
		FileWriter FW = new FileWriter ("RE.config");
		BufferedWriter BW = new BufferedWriter (FW);
		PrintWriter PW = new PrintWriter (BW, true);
		if (TRIPLE_DIRECTORY != null)
		    PW.println ("TripleDirectory " + TRIPLE_DIRECTORY.getAbsolutePath ());
		if (TOTAL_DIRECTORY != null)
		    PW.println ("TotalDirectory " + TOTAL_DIRECTORY.getAbsolutePath ());
		if (ROBBO_EXPLORER_FILE != null)
		    PW.println ("RobboExplorer " + ROBBO_EXPLORER_FILE.getAbsolutePath ());
		PW.close ();
		TellInfo ("RE.config file now saved");
	    }
	catch (IOException io_exc)
	    {
		System.out.println ("Bad I/O with RE.config");
	    }
    }

    public void actionPerformed (ActionEvent act_evt)
    {
	while (POSITION_SEND)
	    {
		try
		    {
			Thread.sleep (10);
		    }
		catch (InterruptedException int_exc)
		    {
		    }
	    }
	if (act_evt.getActionCommand() == "TotalDirectory")
	    ChangeTotalDirectory ();
	if (act_evt.getActionCommand() == "TripleDirectory")
	    ChangeTripleDirectory ();
	if (act_evt.getActionCommand() == "TotalBlockIndex")
	    MakeBlockIndex (TOTAL_DIRECTORY, "TotalBlockIndex");
	if (act_evt.getActionCommand() == "TripleBlockIndex")
	    MakeBlockIndex (TRIPLE_DIRECTORY, "TripleBlockIndex");
	if (act_evt.getActionCommand() == "RobboExplorer")
	    ChangeRobboExplorer ();
	if (act_evt.getActionCommand() == "SAVE")
	    SaveConfig ();
	if (act_evt.getActionCommand() == "Info")
	    DoInform ();
	if (act_evt.getActionCommand() == "FEN")
	    ParseFEN (FEN_AREA.getText ());
	if (act_evt.getActionCommand() == "PGN")
	    EmitPGN ();
    }

    public void ERROR (String STRING)
    {
	System.out.println (STRING);
	System.exit (1234321);
    }
    
    public Font InitChessFont (int SIZE)
    {
     FileInputStream FIS = null;
     Font FONT = null;
     try
	 {
	     FIS = new FileInputStream ("MERIFONT.TTF");
	 }
     catch (IOException io_e)
	 {
	     ERROR ("Cannot find font file");
	 }
     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");
	 }
     return FONT.deriveFont ((float) SIZE);
    }

    public void SetupRobboExplorer (File FILE)
    {
	Process process;
	String FILE_NAME = FILE.getAbsolutePath ();
	ROBBO_EXPLORER_FILE = null;
	try
	    {
		process = Runtime.getRuntime ().exec (FILE_NAME);
	    }
	catch (IOException io_e)
	    {
		TellInfo ("Unable with " + FILE_NAME);
		return;
	    }
	ROBBO_READER = new BufferedReader (new InputStreamReader (process.getInputStream ()));
	ROBBO_WRITER = new PrintWriter (new OutputStreamWriter (process.getOutputStream ()));
	Runtime.getRuntime().addShutdownHook (new KillProcess (process));
	ROBBO_WRITER.println ("setup Robbo check");
	ROBBO_WRITER.flush ();
	try
	    {
		int tries = 0;
		while (true)
		    {
			while (!ROBBO_READER.ready () && tries < 1000)
			    {
				try
				    {
					Thread.sleep (1);
					tries = tries + 1;
				    }
				catch (InterruptedException int_exc)
				    {
				    }		
			    }
			if (tries == 1000)
			    {
				TellInfo ("Tries at 1000 with " + FILE_NAME);
				new KillProcess (process);
				return;
			    }
			String TEST_ME = ROBBO_READER.readLine ();
			if (TEST_ME.equals ("check for Robbo"))
			    break;
			if (TEST_ME.startsWith ("ready in RobboExplorer"))
			    TellInfo (TEST_ME);
		    }
	    }
	catch (IOException io_e)
	    {
		TellInfo ("Communications problem with " + FILE_NAME);
		new KillProcess (process);
		return;
	    }

	TellInfo ("Communications opened " + FILE_NAME);
	ROBBO_EXPLORER_FILE = FILE;
	if (TOTAL_DIRECTORY != null)
	    SetupTotalDirectory (TOTAL_DIRECTORY);
	if (TRIPLE_DIRECTORY != null)
	    SetupTripleDirectory (TRIPLE_DIRECTORY);
	
	JBRE.setBackground (Color.green);
    }


    public void ChangeRobboExplorer ()
    {
	JFileChooser JFC;
	JBRE.setBackground (Color.red);
	if (ROBBO_EXPLORER_FILE == null)
	    JFC = new JFileChooser (System.getProperty ("user.dir")); // HACK
	else
	    JFC = new JFileChooser (ROBBO_EXPLORER_FILE);
	int Value =  JFC.showOpenDialog (JFC);
	if (Value != JFileChooser.APPROVE_OPTION)
	    {
		return;
	    }
	File FILE = JFC.getSelectedFile ();
	if (!FILE.exists())
	    {
		TellInfo ("File does not exist");
		return;
	    }
	SetupRobboExplorer (FILE);
    }

    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 MakeBlockIndex (File DIR, String S)
    {
	JFileChooser JFC;
	if (ROBBO_WRITER == null)
	    {
		TellInfo ("RobboExplorer must exist for BlockIndex");
		return;
	    }
	if (DIR == null)
	    JFC = new JFileChooser (System.getProperty ("user.dir")); // HACK
	else
	    JFC = new JFileChooser (DIR);
	JFC.setFileSelectionMode (JFileChooser.DIRECTORIES_ONLY);
	int Value =  JFC.showOpenDialog (JFC);
	if (Value != JFileChooser.APPROVE_OPTION)
	    {
		return;
	    }
	File FILE = JFC.getSelectedFile ();
	if (!FILE.exists() || !FILE.isDirectory ())
	    {
		TellInfo ("File is not a Directory");
		return;
	    }
	TellInfo ("Command: " + S + " " + FILE.getAbsolutePath ());
	ROBBO_WRITER.println (S + " " + FILE.getAbsolutePath ());
	ROBBO_WRITER.flush ();

	while (true)
	    {
		String STRING = null;
		try
		    {
			while (!ROBBO_READER.ready ())
			    {
				try
				    {
					Thread.sleep (10);
				    }
				catch (InterruptedException int_exc)
				    {
				    }		
			    }
			STRING = ROBBO_READER.readLine ();
		    }
		catch (IOException io_exc)
		    {
			TellInfo ("Communications are bad");
		    }
		TellInfo (STRING);
		StringTokenizer ST = new StringTokenizer (STRING);
		if (!ST.hasMoreTokens ())
		    continue;
		String STR = ST.nextToken ();
		if (STR.equals ("Failure:"))
		    break;
		if (STR.equals ("Finish:"))
		    break;
	    }
    }

    public void SetupTotalDirectory (File FILE)
    {
	TOTAL_DIRECTORY = FILE;
	if (ROBBO_WRITER != null)
	    {
		ROBBO_WRITER.println ("TotalDirectory " + FILE.getAbsolutePath ());
		ROBBO_WRITER.flush ();
	    }
	TellInfo ("Current TotalDirectory " + FILE.getAbsolutePath ());
	if (ROBBO_EXPLORER_FILE != null)
	    WaitForFact ();
	TOT.setBackground (Color.green);
    }

    public void ChangeTotalDirectory ()
    {
	JFileChooser JFC;
	TOT.setBackground (Color.red);
	if (TOTAL_DIRECTORY == null)
	    JFC = new JFileChooser (System.getProperty ("user.dir")); // HACK
	else
	    JFC = new JFileChooser (TOTAL_DIRECTORY);
	JFC.setFileSelectionMode (JFileChooser.DIRECTORIES_ONLY);
	int Value =  JFC.showOpenDialog (JFC);
	if (Value != JFileChooser.APPROVE_OPTION)
	    {
		return;
	    }
	File FILE = JFC.getSelectedFile ();
	if (!FILE.exists() || !FILE.isDirectory ())
	    {
		TellInfo ("File is not a Directory");
		return;
	    }
	SetupTotalDirectory (FILE);
    }

    public void SetupTripleDirectory (File FILE)
    {
	TRIPLE_DIRECTORY = FILE;
	if (ROBBO_WRITER != null)
	    {
		ROBBO_WRITER.println ("TripleDirectory " + FILE.getAbsolutePath ());
		ROBBO_WRITER.flush ();
	    }
	TellInfo ("Current TripleDirectory " + FILE.getAbsolutePath ());
	if (ROBBO_EXPLORER_FILE != null)
	    WaitForFact ();
	TRIP.setBackground (Color.green);
    }

    public void ChangeTripleDirectory ()
    {
	JFileChooser JFC;
	TRIP.setBackground (Color.red);
	if (TRIPLE_DIRECTORY == null)
	    JFC = new JFileChooser (System.getProperty ("user.dir")); // HACK
	else
	    JFC = new JFileChooser (TRIPLE_DIRECTORY);
	JFC.setFileSelectionMode (JFileChooser.DIRECTORIES_ONLY);
	int Value =  JFC.showOpenDialog (JFC);
	if (Value != JFileChooser.APPROVE_OPTION)
	    {
		return;
	    }
	File FILE = JFC.getSelectedFile ();
	if (!FILE.exists() || !FILE.isDirectory ())
	    {
		TellInfo ("File is not a Directory");
		return;
	    }
	SetupTripleDirectory (FILE);
    }

    public Box Make_FEN_Box ()
    {
	Box FEN_BOX = new Box (BoxLayout.X_AXIS);
	FEN_AREA = new JTextArea (1, 45);
	FEN_AREA.setFont (new Font ("Monospaced", 0, 11));
	FEN_AREA.setEditable (true);
	FEN_BOX.add (FEN_AREA);
	FEN_BUTTON = new JButton ("FEN");
	FEN_BUTTON.setActionCommand ("FEN");
	FEN_BUTTON.addActionListener (this);
	FEN_BOX.add (FEN_BUTTON);
	return FEN_BOX;
    }

    public Box MakeButtonBox2 ()
    {
	Box BUTTON_BOX = new Box (BoxLayout.X_AXIS);
	JBRE = new JButton ("RobboExplorer");
	JBRE.setBackground (Color.red);
	JBRE.setActionCommand ("RobboExplorer");
	JBRE.addActionListener (this);
	BUTTON_BOX.add (JBRE);
	TOT = new JButton ("TotalBaseDirectory");
	TOT.setBackground (Color.red);
	TOT.setActionCommand ("TotalDirectory");
	TOT.addActionListener (this);
	BUTTON_BOX.add (TOT);
	TRIP = new JButton ("TripleBaseDirectory");
	TRIP.setBackground (Color.red);
	TRIP.setActionCommand ("TripleDirectory");
	TRIP.addActionListener (this);
	BUTTON_BOX.add (TRIP);
	return BUTTON_BOX;
    }

    public Box MakeButtonBox1 ()
    {
	Box BUTTON_BOX = new Box (BoxLayout.X_AXIS);
	JButton TOT_INDEX = new JButton ("BlockIndex Total");
	TOT_INDEX.setBackground (new Color (175, 200, 225));
	TOT_INDEX.setActionCommand ("TotalBlockIndex");
	TOT_INDEX.addActionListener (this);
	BUTTON_BOX.add (TOT_INDEX);
	JButton TRIP_INDEX = new JButton ("BlockIndex Triple");
	TRIP_INDEX.setBackground (new Color (175, 200, 225));
	TRIP_INDEX.setActionCommand ("TripleBlockIndex");
	TRIP_INDEX.addActionListener (this);
	BUTTON_BOX.add (TRIP_INDEX);
	JButton SAVE = new JButton ("SAVE");
	SAVE.setBackground (new Color (150, 150, 250));
	SAVE.setActionCommand ("SAVE");
	SAVE.addActionListener (this);
	Insets I1 = new Insets (2, 4, 2, 4);
	SAVE.setMargin (I1);
	BUTTON_BOX.add (SAVE);
	JButton INFO = new JButton ("Info");
	INFO.setBackground (new Color (240, 210, 0));
	INFO.setActionCommand ("Info");
	INFO.addActionListener (this);
	BUTTON_BOX.add (INFO);
	JButton PGN = new JButton ("PGN");
	PGN.setBackground (new Color (200, 200, 0));
	PGN.setActionCommand ("PGN");
	PGN.addActionListener (this);
	Insets I2 = new Insets (2, 4, 2, 4);
	PGN.setMargin (I2);
	BUTTON_BOX.add (PGN);
	return BUTTON_BOX;
    }

    public JList MakeRobboInfoList ()
    {
	LIST_MODEL = new DefaultListModel ();
	LIST_MODEL.insertElementAt ("No moves", 0);
	JList LIST = new JList (LIST_MODEL);
	LIST.setFont (new Font ("Monospaced", 0, 12));
	LIST.addKeyListener (new ListPushReturn (LIST));
	LIST.addMouseListener (new ListDoubleClick (LIST));
	LIST.setBackground (new Color (225, 200, 180));
	LIST.setSelectionMode (javax.swing.ListSelectionModel.SINGLE_SELECTION);
	return LIST;
    }

    private class ListPushReturn extends KeyAdapter
    {
	JList JL;
	public ListPushReturn (JList LIST)
	{
	    JL = LIST;
	}
	public void keyTyped (KeyEvent key_evt)
	{
	    if (key_evt.getKeyChar () == '\n')
		{
		    int index = JL.getSelectedIndex ();
		    MakeThisMove (index);
		}
	}
    }

    private class ListDoubleClick extends MouseAdapter
    {
	JList JL;
	public ListDoubleClick (JList LIST)
	{
	    JL = LIST;
	}
	public void mouseClicked (MouseEvent mou_evt)
	{
	    if (mou_evt.getClickCount () == 2)
		{
		    int index = JL.locationToIndex (mou_evt.getPoint ());
		    MakeThisMove (index);
		}
	}
    }

    public void DoGraphics ()
    {
	MOVE_LIST = new MoveList (this);
	HIGH_LIGHTER = new DefaultHighlighter.DefaultHighlightPainter (Color.ORANGE);

	Box LARGE_BOX = new Box (BoxLayout.X_AXIS);
	Box LEFT_BOX = new Box (BoxLayout.Y_AXIS);
	Box RIGHT_BOX = new Box (BoxLayout.Y_AXIS);
	BOARD_PANEL.setSize (10 * SIZE, 10 * SIZE);
	BOARD_PANEL.addMouseListener (this);
	LEFT_BOX.add (BOARD_PANEL);

	Box BUTTON_BOX1 = MakeButtonBox1 ();
	RIGHT_BOX.add (BUTTON_BOX1);
	Box BUTTON_BOX2 = MakeButtonBox2 ();
	RIGHT_BOX.add (BUTTON_BOX2);

	Box FEN_BOX = Make_FEN_Box ();
	LEFT_BOX.add (FEN_BOX);

	TEXT_INFO = new JTextArea (7, 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);

	Box SPLIT_BOX = new Box (BoxLayout.X_AXIS);
	ROBBO_INFO = MakeRobboInfoList ();
	JScrollPane ROBBO_JSP = new JScrollPane (ROBBO_INFO);
	ROBBO_JSP.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	ROBBO_JSP.setPreferredSize (new Dimension (150, 300)); // HACK
	SPLIT_BOX.add (ROBBO_JSP);
	MOVE_LIST_TEXT_AREA = new JTextArea (30, 18);
	MOVE_LIST_TEXT_AREA.setFont (new Font("Monospaced", 0, 12));
	MOVE_LIST_TEXT_AREA.setEditable (false);
	MOVE_LIST_TEXT_AREA.setBackground (new Color (205, 245, 225));
	MOVE_LIST_TEXT_AREA.addMouseListener (this);
	JScrollPane MLTA_JSP = new JScrollPane (MOVE_LIST_TEXT_AREA);
	MLTA_JSP.setPreferredSize (new Dimension (150, 300)); // HACK
	MLTA_JSP.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	SPLIT_BOX.add (MLTA_JSP);

	RIGHT_BOX.add (SPLIT_BOX);
	LARGE_BOX.add (LEFT_BOX);
	LARGE_BOX.add (RIGHT_BOX);
	j_frame.add (LARGE_BOX);
    }

    public InformPanel InformFrame ()
    {
	JFrame INFORM = new JFrame ("InformFrame");
	final InformPanel IP = new InformPanel (this); /* bind final */
	JScrollPane INFORM_JSP = new JScrollPane (IP);
	INFORM_JSP.getViewport ().add (IP);
	JScrollBar JSB_VERT = INFORM_JSP.getVerticalScrollBar ();
	JSB_VERT.addAdjustmentListener (new AdjustmentListener()
	    { public void adjustmentValueChanged (AdjustmentEvent e) { IP.repaint (); } }); // HACK // HACK
	JScrollBar JSB_HORZ = INFORM_JSP.getHorizontalScrollBar ();
	JSB_HORZ.addAdjustmentListener (new AdjustmentListener()
	    { public void adjustmentValueChanged (AdjustmentEvent e) { IP.repaint (); } }); // HACK // HACK
	INFORM.add (INFORM_JSP);
	INFORM.setBackground (Color.lightGray);
	INFORM.pack ();
	INFORM.setSize (600, 600); // demand
	INFORM.setResizable (false);
	INFORM.setVisible (true);	
	return IP;
    }

    public void DoInform ()
    {
	if (ROBBO_EXPLORER_FILE == null)
	    {
		TellInfo ("Must have ROBBO_EXPLORER_FILE set to Inform");
		return;
	    }
	InformPanel IP = InformFrame ();
        ROBBO_WRITER.println ("inform");
        ROBBO_WRITER.flush ();
	IP.DATA_COUNT = 0;
	while (true)
	    {
		String STRING = null;
		try
		    {
			while (!ROBBO_READER.ready ())
			    {
				try
				    {
					Thread.sleep (10);
				    }
				catch (InterruptedException int_exc)
				    {
				    }           
			    }
			STRING = ROBBO_READER.readLine ();
		    }
		catch (IOException io_exc)
		    {
			TellInfo ("Communications are bad");
			return;
		    }
		if (STRING.equals ("Informatory complete"))
		    break;
		IP.DATA_STRINGS[IP.DATA_COUNT++] = new String (STRING);
	    }	
	IP.repaint ();
    }

    public void MakeFrame ()
    {
	j_frame = new JFrame ("RobboExplorative v0.007"); // in value
	SIZE = 40;
	ROBBO_LIST_STRING = new String[256];
	ROBBO_LIST_VALUE = new int[256];
	ROBBO_LIST_MOVE = new int[256];
	j_frame.addWindowListener
	    (new WindowAdapter()
		{
		    public void windowClosing (WindowEvent win_evt)
		    {
			System.exit (0);
		    }
		}
		);
	chess_font = InitChessFont (SIZE);
	DoGraphics ();
	j_frame.setBackground (Color.lightGray);
	j_frame.pack ();
	j_frame.setResizable (false);
	j_frame.setVisible (true);
	READY_OK = true;
    }
}
