1 /* JChessBoard -- a chess game
2  * Copyright (C) 2000-2004 Claus Divossen <claus.divossen@gmx.de>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 /* $Id: Protocol.java,v 1.6 2004/12/26 23:12:14 cdivossen Exp $ */
20 
21 package jchessboard;
22 
23 import java.util.StringTokenizer;
24 
25 import javax.swing.JOptionPane;
26 
27 /**
28  * @author cd
29  *
30  * To change the template for this generated type comment go to
31  * Window>Preferences>Java>Code Generation>Code and Comments
32  */
33 public class Protocol {
34     public final static String MOVE_MESSAGE = "move";
35     public final static String BATCH_MOVE_MESSAGE = "batch_move";
36     public final static String BATCH_FINISHED_MESSAGE = "batch_finished";
37     public final static String BATCH_CANCELED_MESSAGE = "batch_canceled";
38     public final static String START_UPLOAD_MESSAGE = "start_upload";
39     public final static String NEW_GAME_MESSAGE = "new_game";
40     public final static String REQUEST_NEW_GAME_MESSAGE = "request_new";
41     public final static String NEW_GAME_REJECTED_MESSAGE = "new_rejected";
42     public final static String UNDO_MESSAGE = "undo";
43     public final static String UNDO_REJECTED_MESSAGE = "undo_rejected";
44     public final static String GAME_TIME_MESSAGE = "gametime";
45     public final static String PLAYERS_TIME_MESSAGE = "playerstime";
46     public final static String REQUEST_UNDO_MESSAGE = "request_undo";
47     public final static String REQUEST_CLOCK_CHANGE_MESSAGE = "request_clock_change";
48     public final static String CLOCK_CHANGE_REJECTED_MESSAGE = "clock_change_rejected";
49     public final static String REQUEST_TOGGLE_CLOCK_MESSAGE = "request_enable_clock";
50     public final static String REJECT_TOGGLE_CLOCK_MESSAGE = "reject_enable_clock";
51     public final static String ACCEPT_TOGGLE_CLOCK_MESSAGE = "accept_enable_clock";
52     public final static String REQUEST_DISABLE_CLOCK_MESSAGE = "request_disable_clock";
53     public final static String REJECT_DISABLE_CLOCK_MESSAGE = "reject_disable_clock";
54     public final static String ACCEPT_DISABLE_CLOCK_MESSAGE = "accept_disable_clock";
55     public final static String OFFER_DRAW_MESSAGE = "offer_draw";
56     public final static String DRAW_ACCEPTED_MESSAGE = "draw_accepted";
57     public final static String DRAW_REJECTED_MESSAGE = "draw_rejected";
58     public final static String REQUEST_SIDE_SWITCH_MESSAGE = "request_side_switch";
59     public final static String SIDE_SWITCH_ACCEPTED_MESSAGE = "side_switch_accepted";
60     public final static String SIDE_SWITCH_REJECTED_MESSAGE = "side_switch_rejected";
61     public final static String REQUEST_UPLOAD_MESSAGE = "request_upload";
62     public final static String REJECT_UPLOAD_MESSAGE = "reject_upload";
63     public final static String ACCEPT_UPLOAD_MESSAGE = "accept_upload";
64     public final static String RESIGNED_MESSAGE = "resign";
65     public final static String USER_MESSAGE = "message";
66     public final static String RESTART_MESSAGE = "restart";
67     public final static String QUIT_MESSAGE = "quit";
68     public final static String WELCOME_MESSAGE = "Welcome!";
69     public final static String REJECTED_MESSAGE = "Go away!";
70     public final static String INIT_FROM_FEN_MESSAGE = "init_from_fen";
71     public final static String ERROR_MESSAGE = "error";
72     public final static String PLAYER_NAME_MESSAGE = "playername";
73 
74     protected java.util.LinkedList pendingAcks = new java.util.LinkedList();
75     protected boolean gameIsLoading = false;
76     protected boolean protocolIsConnected = false;
77     protected boolean protocolServer = false;
78     private JChessBoard jcb; // The parent JChessBoard
79     //    private BoardConnector boardConnector;
80     private String otherPlayersName = "Opponent";
81 
isConnected()82     public boolean isConnected() {
83         return protocolIsConnected;
84     }
85 
clearPendingAcks()86     public void clearPendingAcks() {
87         pendingAcks.clear();
88     }
89 
sendWelcome()90     public void sendWelcome() {
91         sendMessage(WELCOME_MESSAGE);
92     }
93 
connectionClosed()94     public void connectionClosed() {
95         protocolIsConnected = false;
96         protocolServer = false;
97         pendingAcks.clear();
98     }
99 
connectionEstablished()100     public void connectionEstablished() {
101         protocolIsConnected = true;
102         clearPendingAcks();
103     }
104 
connecting()105     public void connecting() {
106         protocolServer = false;
107         protocolIsConnected = false;
108     }
109 
sendMove(Move move)110     public void sendMove(Move move) {
111         sendMessage(MOVE_MESSAGE, move.toString());
112     }
113 
sendBatchMove(Move move)114     public void sendBatchMove(Move move) {
115         sendMessage(BATCH_MOVE_MESSAGE, move.toString());
116     }
117 
startUpload()118     public void startUpload() {
119         sendMessage(START_UPLOAD_MESSAGE);
120     }
121 
uploadDone()122     public void uploadDone() {
123         sendMessage(BATCH_FINISHED_MESSAGE);
124     }
125 
requestNewGame()126     public void requestNewGame() {
127         sendMessage(REQUEST_NEW_GAME_MESSAGE);
128     }
129 
offerDraw()130     public void offerDraw() {
131         sendMessage(OFFER_DRAW_MESSAGE);
132     }
133 
resigned()134     public void resigned() {
135         sendMessage(RESIGNED_MESSAGE);
136     }
137 
requestSideSwitch()138     public void requestSideSwitch() {
139         sendMessage(REQUEST_SIDE_SWITCH_MESSAGE);
140     }
141 
requestToggleClock()142     public void requestToggleClock() {
143         sendMessage(REQUEST_TOGGLE_CLOCK_MESSAGE);
144     }
145 
sendPlayersTime(long playersTime)146     public void sendPlayersTime(long playersTime) {
147         sendMessage(PLAYERS_TIME_MESSAGE, "" + playersTime);
148     }
149 
sendError(String message)150     public void sendError(String message) {
151         sendMessage(ERROR_MESSAGE, message);
152     }
153 
requestClockChange(long newWhiteTime, long newBlackTime)154     public void requestClockChange(long newWhiteTime, long newBlackTime) {
155         sendMessage(REQUEST_CLOCK_CHANGE_MESSAGE, "" + newWhiteTime + " " + newBlackTime);
156     }
157 
requestUndo()158     public void requestUndo() {
159         sendMessage(REQUEST_UNDO_MESSAGE);
160     }
161 
requestUpload()162     public void requestUpload() {
163         sendMessage(REQUEST_UPLOAD_MESSAGE);
164     }
165 
initFromFEN(String fen)166     public void initFromFEN(String fen) {
167         sendMessage(INIT_FROM_FEN_MESSAGE, fen);
168     }
169 
sendPlayerName(String name)170 	public void sendPlayerName(String name) {
171 		sendMessage(PLAYER_NAME_MESSAGE,name);
172 	}
173 
174     /**
175      * Handles all the messages from a connected board.  The heart of the
176      * protocol; it must handle all the incoming commands, as well as receive
177      * and send acknowledgements.
178      *
179      * @param line A line of input retrieved from the connected board.
180      */
handleInput(String line)181     public void handleInput(String line) {
182         StringTokenizer st;
183         String message = null;
184         String value = null;
185         String value2 = null;
186 
187         // Pull the first three words out of the line: message, value, value2
188         st = new StringTokenizer(line);
189         if (st.hasMoreTokens())
190             message = st.nextToken();
191         if (st.hasMoreTokens())
192             value = st.nextToken();
193         if (st.hasMoreTokens())
194             value2 = st.nextToken();
195 
196         // That first token tells us what to do
197         if (message != null) {
198             if (message.equals(QUIT_MESSAGE)) {
199                 jcb.showMessage("Opponent has quit!");
200                 jcb.boardConnector.closeConnection();
201                 jcb.connectionClosed();
202             }
203             // Checking the answers:
204             else if (message.equals("?")) // Peer didn't understand.
205                 {
206                 // Reset communications
207                 jcb.showMessage("Out of sync! Trying to restart...");
208                 jcb.boardConnector.sendString(RESTART_MESSAGE);
209                 pendingAcks.clear();
210                 jcb.connectionIndicator.setError();
211             } else if (message.equals("OK " + RESTART_MESSAGE)) {
212                 jcb.newGame();
213                 jcb.connectionIndicator.setReady();
214                 jcb.showMessage("Restarted due to unkown error.");
215                 jcb.beep();
216             } else if (message.equals("OK") && value != null && pendingAcks.size() > 0) {
217                 // Our latest message was received
218                 if (line.equals("OK " + (String) pendingAcks.get(0))) {
219                     pendingAcks.remove(0);
220                     if (pendingAcks.size() == 0) {
221                         jcb.connectionIndicator.setReady();
222                     }
223                 }
224             } else {
225                 // Got new command from peer
226                 if (message.equals(WELCOME_MESSAGE)) {
227                     // Only clients get this message.
228                     // We're connected and ready to go
229                     acknowledge(line);
230                     protocolIsConnected = true;
231                     jcb.connectionIndicator.setReady();
232                     jcb.showMessage("Game accepted.");
233                     jcb.connectionEstablished();
234                 } else if (message.equals(REJECTED_MESSAGE)) {
235                     // We've been rejected
236                     jcb.beep();
237                     jcb.showMessage("Other player doesn't want to play.");
238                     jcb.connectionClosed();
239                 } else if (message.equals(UNDO_MESSAGE)) {
240                     // Undo handling
241                     jcb.undoMove();
242                     jcb.beep();
243                     acknowledge(line);
244                 } else if (message.equals(REQUEST_UNDO_MESSAGE)) {
245                     Object[] options = { "Accept", "Reject" };
246                     int selection =
247                         JOptionPane.showOptionDialog(
248                             null,
249                             "Opponent wants to take back the last move.",
250                             "Undo request",
251                             JOptionPane.YES_NO_OPTION,
252                             JOptionPane.QUESTION_MESSAGE,
253                             null,
254                             options,
255                             options[0]);
256                     acknowledge(line);
257                     if (selection == JOptionPane.YES_OPTION) {
258                         jcb.undoMove();
259                         sendMessage(UNDO_MESSAGE);
260                     } else {
261                         sendMessage(UNDO_REJECTED_MESSAGE);
262                     }
263                 } else if (message.equals(UNDO_REJECTED_MESSAGE)) {
264                     jcb.showMessage("Undo request rejected.");
265                     acknowledge(line);
266                 } else if (message.equals(REQUEST_TOGGLE_CLOCK_MESSAGE)) {
267                     // Enabling the clock
268                     Object[] options = { "Accept", "Reject" };
269                     int selection =
270                         JOptionPane.showOptionDialog(
271                             null,
272                             "Opponent wants to turn " + (jcb.getEnableClock() ? "off" : "on") + " the clock",
273                             "Clock request",
274                             JOptionPane.YES_NO_OPTION,
275                             JOptionPane.QUESTION_MESSAGE,
276                             null,
277                             options,
278                             options[0]);
279                     acknowledge(line);
280                     if (selection == JOptionPane.YES_OPTION) {
281                         jcb.setEnableClock(!jcb.getEnableClock());
282                         jcb.update();
283                         jcb.showMessage("Chess clocks " + (jcb.getEnableClock() ? "enabled" : "disabled") + ".");
284                         sendMessage(ACCEPT_TOGGLE_CLOCK_MESSAGE);
285                     } else {
286                         sendMessage(REJECT_TOGGLE_CLOCK_MESSAGE);
287                     }
288                 } else if (message.equals(ACCEPT_TOGGLE_CLOCK_MESSAGE)) {
289                     jcb.setEnableClock(!jcb.getEnableClock());
290                     //	jcb.setEnableClock(false);
291                     jcb.update();
292                     jcb.showMessage("Chess clocks " + (jcb.getEnableClock() ? "enabled" : "disabled") + ".");
293                     acknowledge(line);
294                 } else if (message.equals(REJECT_TOGGLE_CLOCK_MESSAGE)) {
295                     jcb.showMessage(
296                         "Your wish to turn " + (jcb.getEnableClock() ? "off" : "on") + " the clock was rejected.");
297                     acknowledge(line);
298                 }
299                 // Draw handling
300                 else if (message.equals(OFFER_DRAW_MESSAGE)) {
301                     Object[] options = { "Accept", "Reject" };
302                     int selection =
303                         JOptionPane.showOptionDialog(
304                             null,
305                             "Opponent offers a draw.",
306                             "Draw offered",
307                             JOptionPane.YES_NO_OPTION,
308                             JOptionPane.QUESTION_MESSAGE,
309                             null,
310                             options,
311                             options[0]);
312                     acknowledge(line);
313                     if (selection == JOptionPane.YES_OPTION) {
314                         sendMessage(DRAW_ACCEPTED_MESSAGE);
315                         jcb.showMessage("Draw accepted.");
316                         //                        jcb.stopGame();
317                         jcb.history.setResult("1/2-1/2");
318                     } else {
319                         sendMessage(DRAW_REJECTED_MESSAGE);
320                     }
321                 } else if (message.equals(DRAW_ACCEPTED_MESSAGE)) {
322                     jcb.showMessage("Draw accepted.");
323                     jcb.beep();
324                     //                    jcb.stopGame();
325                     jcb.history.setResult("1/2-1/2");
326                     acknowledge(line);
327                 } else if (message.equals(DRAW_REJECTED_MESSAGE)) {
328                     jcb.showMessage("Draw rejected.");
329                     acknowledge(line);
330                 }
331                 // Resign
332                 else if (message.equals(RESIGNED_MESSAGE)) {
333                     acknowledge(line);
334                     jcb.showMessage("Opponent resigned.");
335                     jcb.beep();
336                     //                    jcb.stopGame();
337                     jcb.history.setResult((jcb.whitePlayer == JChessBoard.HUMAN) ? "1-0" : "0-1");
338                 }
339                 // New Game
340                 else if (message.equals(NEW_GAME_MESSAGE)) {
341                     jcb.beep();
342                     jcb.history.clear();
343                     jcb.newGame();
344                     jcb.showMessage("New game.");
345                     acknowledge(line);
346                 } else if (message.equals(REQUEST_NEW_GAME_MESSAGE)) {
347                     jcb.beep();
348                     Object[] options = { "Accept", "Reject" };
349                     int selection =
350                         JOptionPane.showOptionDialog(
351                             null,
352                             "Opponent requests a new game.",
353                             "New game?",
354                             JOptionPane.YES_NO_OPTION,
355                             JOptionPane.QUESTION_MESSAGE,
356                             null,
357                             options,
358                             options[0]);
359                     acknowledge(line);
360                     if (selection == JOptionPane.YES_OPTION) {
361                         jcb.history.clear();
362                         jcb.newGame();
363                         jcb.showMessage("New game.");
364                         sendMessage(NEW_GAME_MESSAGE);
365                     } else {
366                         sendMessage(NEW_GAME_REJECTED_MESSAGE);
367                     }
368                 } else if (message.equals(NEW_GAME_REJECTED_MESSAGE)) {
369                     jcb.showMessage("New game rejected.");
370                     acknowledge(line);
371                 }
372                 // Time handling
373                 else if (message.equals(REQUEST_CLOCK_CHANGE_MESSAGE)) {
374                     long newWhiteTime = Long.parseLong(value);
375                     long newBlackTime = Long.parseLong(value2);
376                     Object[] options = { "Accept", "Reject" };
377                     int selection =
378                         JOptionPane.showOptionDialog(
379                             null,
380                             "Opponent wants to change the clocks to:\n "
381                                 + "White: "
382                                 + jcb.chessClock.formatTime(newWhiteTime)
383                                 + "  Black: "
384                                 + jcb.chessClock.formatTime(newBlackTime),
385                             "Change clocks?",
386                             JOptionPane.YES_NO_OPTION,
387                             JOptionPane.QUESTION_MESSAGE,
388                             null,
389                             options,
390                             options[0]);
391                     acknowledge(line);
392                     if (selection == JOptionPane.YES_OPTION) {
393                         sendMessage(GAME_TIME_MESSAGE, "" + newWhiteTime + " " + newBlackTime);
394                         jcb.setClocks(newWhiteTime, newBlackTime);
395                     } else {
396                         sendString(CLOCK_CHANGE_REJECTED_MESSAGE);
397                     }
398                 } else if (message.equals(CLOCK_CHANGE_REJECTED_MESSAGE)) {
399                     jcb.showMessage("Clock change rejected.");
400                     acknowledge(line);
401                 } else if (message.equals(GAME_TIME_MESSAGE) && value != null && value2 != null) {
402                     jcb.setClocks(Long.parseLong(value), Long.parseLong(value2));
403                     acknowledge(line);
404                 } else if (message.equals(PLAYERS_TIME_MESSAGE) && value != null) {
405                     // Required to synchronize the clocks.
406                     if (jcb.blackPlayer == JChessBoard.PEER) {
407                         long time = Long.parseLong(value);
408                         jcb.chessClock.setBlackPlayersTime(time);
409                         jcb.checkFinish();
410                     } else if (jcb.whitePlayer == JChessBoard.PEER) {
411                         long time = Long.parseLong(value);
412                         jcb.chessClock.setWhitePlayersTime(time);
413                         jcb.checkFinish();
414                     }
415                     acknowledge(line);
416                     // Restart
417                 } else if (message.equals(RESTART_MESSAGE)) {
418                     // The other board must have detected an error.
419                     pendingAcks.clear();
420                     jcb.newGame();
421                     jcb.showMessage("Restarted due to unkown error.");
422                     jcb.beep();
423                     acknowledge(line);
424                 } else if (message.equals(MOVE_MESSAGE) && value != null) {
425                     // Move
426                     acknowledge(line);
427                     jcb.makePeersMove(new Move(value));
428                 } else if (message.equals(REQUEST_UPLOAD_MESSAGE)) {
429 					Object[] options = { "Accept", "Reject" };
430 					int selection =
431 						JOptionPane.showOptionDialog(
432 							null,
433 							"Opponent wants to upload a saved game.",
434 							"Accept upload?",
435 							JOptionPane.YES_NO_OPTION,
436 							JOptionPane.QUESTION_MESSAGE,
437 							null,
438 							options,
439 							options[0]);
440 					acknowledge(line);
441 					if (selection == JOptionPane.YES_OPTION) {
442 						sendMessage(ACCEPT_UPLOAD_MESSAGE);
443 					} else {
444 						sendString(REJECT_UPLOAD_MESSAGE);
445 					}
446 				} else if (message.equals(ACCEPT_UPLOAD_MESSAGE)) {
447 					acknowledge(line);
448 					jcb.showMessage("Upload accepted.");
449 					jcb.uploadGame();
450 				} else if (message.equals(REJECT_UPLOAD_MESSAGE)) {
451 					acknowledge(line);
452 					jcb.showMessage("Upload rejected.");
453 				} else if (message.equals(START_UPLOAD_MESSAGE)) {
454 					jcb.newGame();
455 					jcb.showMessage("Peer started to upload a game...");
456 					gameIsLoading = true;
457 					jcb.beep();
458 					acknowledge(line);
459                 } else if (message.equals(BATCH_MOVE_MESSAGE) && value != null) {
460                     Move move = new Move(value);
461                     jcb.makeBatchMove(move);
462                     gameIsLoading = true;
463                     acknowledge(line);
464                 } else if (message.equals(BATCH_FINISHED_MESSAGE)) {
465                     acknowledge(line);
466                     jcb.showMessage("Game successfully loaded.");
467 					jcb.whitePlayer=JChessBoard.UNKNOWN;
468 					jcb.blackPlayer=JChessBoard.UNKNOWN;
469 					jcb.gameTable.setNetworkGameIndex(jcb.gameTable.getCurrentGameIndex());
470 					jcb.chessClock.stopClock();
471 					jcb.chessClock.resetClocks();
472 					jcb.update();
473 					jcb.prepareMove();
474                     gameIsLoading = false;
475                 } else if (message.equals(BATCH_CANCELED_MESSAGE)) {
476                     acknowledge(line);
477                     jcb.showMessage("Game upload canceled!");
478                     gameIsLoading = false;
479                 }
480                 // Initializaton from FEN
481                 else if (message.equals(INIT_FROM_FEN_MESSAGE) && value != null) {
482                     acknowledge(line);
483                     VirtualBoard vb = new VirtualBoard();
484                     vb.initFromFEN(value);
485                     jcb.newGame(vb);
486                     jcb.showMessage("Opponent initialized board from FEN.");
487                 }
488                 // Side switch
489                 else if (message.equals(REQUEST_SIDE_SWITCH_MESSAGE)) {
490                     jcb.beep();
491                     Object[] options = { "Accept", "Reject" };
492                     int selection =
493                         JOptionPane.showOptionDialog(
494                             null,
495                             "Opponents wants to switch sides.",
496                             "Switch sides?",
497                             JOptionPane.YES_NO_OPTION,
498                             JOptionPane.QUESTION_MESSAGE,
499                             null,
500                             options,
501                             options[0]);
502                     acknowledge(line);
503                     if (selection == JOptionPane.YES_OPTION) {
504                         jcb.switchSides();
505                         sendMessage(SIDE_SWITCH_ACCEPTED_MESSAGE);
506                     } else {
507                         sendMessage(SIDE_SWITCH_REJECTED_MESSAGE);
508                     }
509                 } else if (message.equals(SIDE_SWITCH_ACCEPTED_MESSAGE)) {
510                     acknowledge(line);
511                     jcb.switchSides();
512                 } else if (message.equals(SIDE_SWITCH_REJECTED_MESSAGE)) {
513                     acknowledge(line);
514                     jcb.showMessage("Side switch rejected");
515                 }
516                 // Message
517                 else if (message.equals(USER_MESSAGE) && value != null) {
518                     acknowledge(line);
519                     jcb.showMessage(otherPlayersName + ": " + stripCmd(line), "chatIn");
520                 }
521                 // Player name
522                 else if (message.equals(PLAYER_NAME_MESSAGE) && value != null) {
523                     acknowledge(line);
524                     otherPlayersName = value;
525                     jcb.showMessage("Opponent set its name to \"" + value + "\".");
526 					jcb.updateSTR();
527                 }
528                 // Error
529                 else if (message.equals(ERROR_MESSAGE)) {
530                     acknowledge(line);
531                     if (value == null) {
532                         jcb.showMessage("An unspecified error occurred.");
533                     } else {
534                         jcb.showMessage("Error message from peer: " + value);
535                     }
536                     //                            history.clear();
537                     //                            newGame();
538                 } else {
539                     // Send outOfSync message
540                     sendString("?\n");
541                 }
542             } // Not an acknowledgement
543         } // Not a null message
544     }
545 
546     /**
547      * Sends string, setting GUI connection indicator and debug output.
548      */
sendString(String s)549     protected void sendString(String s) {
550         jcb.connectionIndicator.setWaiting();
551         if (jcb.settings.debugDumpTraffic) {
552             jcb.showMessage(">>>" + s, "debug");
553         }
554         pendingAcks.add(s);
555         jcb.boardConnector.sendString(s);
556     }
557 
558     /**
559      * Sends a message with values.
560      * @param message The message indicator, one of an enumeration of Strings
561      * @param value_line The values required for the message indicator
562      */
sendMessage(String message, String value_line)563     public void sendMessage(String message, String value_line) {
564         if (value_line == null)
565             value_line = "";
566         sendString(message + " " + value_line);
567     }
568 
569     /**
570      * Sends a message with no values.
571      * @param message The message indicator, one of an enumeration of Strings
572      */
sendMessage(String message)573     public void sendMessage(String message) {
574         sendString(message);
575     }
576 
577     /**
578      * Sends acknowledgement string.  This indicates that we have received
579      * a message send by the connected board.  It <em>does not</em> indicate
580      * that the message has been correctly processed.
581      */
acknowledge(String s)582     protected void acknowledge(String s) {
583         if (jcb.settings.debugDumpTraffic) {
584             jcb.showMessage(">>>OK " + s, "debug");
585         }
586         jcb.boardConnector.sendString("OK " + s);
587     }
588 
589     /**
590     	Strip off the first "word" which is the command, leaving
591     	just the remaining line.
592     */
stripCmd(String line)593     private static String stripCmd(String line) {
594         StringTokenizer st = new StringTokenizer(line);
595         if (st.hasMoreTokens()) {
596             String cmd = st.nextToken();
597             return (line.substring(cmd.length()));
598         } else {
599             return ("EmptyString");
600         }
601     }
602 
Protocol(JChessBoard _jcb)603     public Protocol(JChessBoard _jcb) {
604         jcb = _jcb;
605     }
606 
607     /**
608      * @return
609      */
getOtherPlayersName()610     public String getOtherPlayersName() {
611         return otherPlayersName;
612     }
613 
614     /**
615      * @param string
616      */
setOtherPlayersName(String string)617     public void setOtherPlayersName(String string) {
618         otherPlayersName = string;
619     }
620 
621 }
622