View Javadoc
1   /******************************************************************************
2    * CookieMonster.java - Parse messages received from the network.
3    * $Id$
4    * 
5    * BuckoFIBS - Backgammon by BuckoSoft
6    * Copyright(c) 2009,2010 - Dick Balaska - BuckoSoft, Corp.
7    * 
8    * $Log$
9    * Revision 1.18  2013/11/09 06:32:20  dick
10   * Distinguish between "you were banned" vs. "PL was banned".
11   *
12   * Revision 1.17  2013/09/19 08:04:18  dick
13   * Spell the email message correctly.
14   *
15   * Revision 1.16  2013/09/19 07:36:03  dick
16   * Add FIBS_YourEmailChanged.
17   *
18   * Revision 1.15  2012/03/08 19:48:49  dick
19   * Update PlayerLeftGame. It changed on the server.
20   *
21   * Revision 1.14  2011/07/16 02:42:30  dick
22   * Add CantWatchSelf.
23   *
24   * Revision 1.13  2011/07/04 03:35:36  dick
25   * Add DidntDoubleOrResign.
26   *
27   * Revision 1.12  2011/06/22 06:02:31  dick
28   * Define NobodyHeardYou.
29   *
30   * Revision 1.11  2011/06/15 00:41:52  dick
31   * resetFIBSCookieMonster() becomes just reset().
32   *
33   * Revision 1.10  2011/06/05 06:49:09  dick
34   * Fix BearingOff and AcceptDoubles messages.
35   *
36   * Revision 1.9  2011/05/21 06:08:21  dick
37   * Fix FIBS_WantedToResign.
38   *
39   * Revision 1.8  2011/05/21 05:06:58  dick
40   * Add FIBS_WantedToResign.
41   *
42   * Revision 1.7  2011/05/16 21:19:47  dick
43   * Add FIBS_StartingNewGameInMatch.
44   *
45   * Revision 1.6  2011/05/13 15:07:10  dick
46   * IsAway message runs to the end of the line.
47   *
48   * Revision 1.5  2010/12/30 20:56:30  dick
49   * Spell invitation correctly.
50   *
51   * Revision 1.4  2010/12/29 07:46:35  dick
52   * Add WaitForLastInvitation and WaitForAcceptResign.
53   *
54   * Revision 1.3  2010/03/03 13:12:21  inim
55   * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8
56   *
57   * Revision 1.2  2010/03/03 12:19:49  inim
58   * Moved source to UTF8 encoding from CP1252 encoding. To this end all source files' (c) message was updated to "Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.". This replaces the (c) sign to UTF8, and adds the new year 2010.
59   *
60   * Revision 1.1  2010/02/04 05:57:53  inim
61   * Mavenized project folder layout
62   *
63   * Revision 1.27  2009/05/09 03:42:27  dick
64   * Add PlayerBannedWatch and Doesn'tWantYouToWatch.
65   *
66   * Revision 1.26  2009/03/04 18:52:26  dick
67   * Add FIBS_HasNoSavedGames.
68   *
69   * Revision 1.25  2009/02/27 05:47:41  dick
70   * Handle the whois "last logout" line.
71   *
72   * Revision 1.24  2009/02/25 09:41:11  dick
73   * Handle ATTENTION messages from FIBS when it is shutting down.
74   *
75   * Revision 1.23  2009/02/24 05:37:16  dick
76   * Fix FIBS_NoSavedMatch.
77   *
78   * Revision 1.22  2009/02/17 14:45:30  dick
79   * Turn off DEBUG.
80   *
81   * Revision 1.21  2009/02/14 12:29:32  dick
82   * BuckoFIBS is released under the GNU license.
83   *
84   * Revision 1.20  2009/02/11 09:09:43  dick
85   * Better beginning and ending your turn.
86   *
87   * Revision 1.19  2009/02/09 22:47:20  dick
88   * RollOrDouble may or may not have a period.
89   *
90   * Revision 1.18  2009/02/06 07:56:48  dick
91   * Working on doubles.
92   *
93   * Revision 1.17  2009/02/05 05:57:54  dick
94   * Just fixing 7 messages.
95   *
96   * Revision 1.16  2009/02/03 09:48:13  dick
97   * Fix YouResign and YouAcceptAndWin.
98   *
99   * Revision 1.15  2009/02/02 08:37:43  dick
100  * Once upon a time, there were more regex cleanups...
101  *
102  * Revision 1.14  2009/02/01 23:23:31  dick
103  * Fix YouWinGame.
104  *
105  * Revision 1.13  2009/02/01 21:12:41  dick
106  * Fix the SaveMatch regex.
107  *
108  * Revision 1.12  2009/02/01 08:58:58  dick
109  * Fix SavedMatchPlaying, AlreadyPlaying and CantMoveFirstMove
110  *
111  * Revision 1.11  2009/01/31 08:53:44  dick
112  * Even more fixups.
113  *
114  * Revision 1.10  2009/01/31 06:04:54  dick
115  * More regex fixups.
116  *
117  * Revision 1.9  2009/01/29 08:28:05  dick
118  * Try bearing off with a period first.
119  *
120  * Revision 1.8  2009/01/28 22:30:38  dick
121  * Hack up PlayerMoves and BearingOff.  These don't properly regexp, they cheat and go to the end of the line.
122  *
123  * Revision 1.7  2009/01/28 08:30:24  dick
124  * Handle the Malformed Messages (Bad_board) as documented as occuring in http://www.fibs.com/fcm/ .
125  * However, we do begin and end regexp on ALL messages.
126  * ClientConnection now supports a pushback buffer so that CookieMonster can deal with the second message later.
127  *
128  * Revision 1.6  2009/01/18 06:38:00  dick
129  * Sometimes we get 8<sp><sp>name instead of 8<sp>name, so catch that separately.
130  *
131  * Revision 1.5  2009/01/10 05:11:04  dick
132  * Add FIBS_PointsFor, a resuming match message.
133  *
134  * Revision 1.4  2009/01/09 07:33:22  dick
135  * Add FIBS_NotInteresting.
136  *
137  * Revision 1.3  2009/01/07 04:29:16  dick
138  * Javadoc.
139  *
140  * Revision 1.2  2009/01/06 08:05:28  dick
141  * Handle registering a new user.
142  *
143  * Revision 1.1  2008/12/13 06:57:11  dick
144  * Move ClientConnection, CookieMonster, and FIBSMessages to their own network package.
145  *
146  * Revision 1.8  2008/12/11 10:00:00  dick
147  * Add FIBS_BoardstyleSetTo.
148  *
149  * Revision 1.7  2008/12/09 20:02:44  dick
150  * Javadoc cleanup.
151  *
152  * Revision 1.6  2008/12/09 01:51:37  dick
153  * regex working in Java.
154  * I added a constant string PL because my jibs server allows numbers in the name, which fail this regexp.
155  * Rather than change each string, i moved that decl out so that i can change back to fibs,
156  * which disallows numbers.
157  *
158  * Revision 1.5  2008/12/08 06:44:31  dick
159  * Commentality.
160  *
161  * Revision 1.4  2008/12/07 22:52:12  dick
162  * method names start with a lower case character.
163  *
164  * Revision 1.3  2008/10/10 09:02:30  dick
165  * Finish implementing the FIBS CookieMonster.
166  *
167  * Revision 1.2  2008/10/03 06:55:13  dick
168  * Add BuckoHeaders.
169  */
170 
171 /* 
172  * This program is free software: you can redistribute it and/or modify
173  * it under the terms of the GNU General Public License as published by
174  * the Free Software Foundation, either version 3 of the License, or
175  * (at your option) any later version.
176  *
177  * This program is distributed in the hope that it will be useful,
178  * but WITHOUT ANY WARRANTY; without even the implied warranty of
179  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
180  * GNU General Public License for more details.
181  *
182  * You should have received a copy of the GNU General Public License
183  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
184  *
185  * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>.
186  * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp.
187  * 
188  */
189 package com.buckosoft.fibs.net;
190 
191 import java.util.Iterator;
192 import java.util.LinkedList;
193 import java.util.regex.Pattern;
194 
195 
196 /** Implementation of the CookieMonster API from fibs
197  * @author cppc
198  * @author Dick Balaska
199  * @author Original author of C version says not to use his name
200  * @since 2008/04/08
201  * @version $Revision$ <br> $Date$
202  * @see <a href="http://www.fibs.com/fcm/">http://www.fibs.com/fcm/</a> <br>
203  * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/net/CookieMonster.java">cvs CookieMonster.java</a>
204  */
205 public class CookieMonster implements FIBSMessages {
206 	private final static boolean DEBUG = false;
207 	private	ClientConnection	clientConnection;		// needed to pushback any runon strings
208 
209 	private class CookieDough {
210 		public Pattern regex = null;
211 		public int message = 0;
212 	}
213 	
214 	private final int 	FIBS_UNINITIALIZED = 1,
215 						FIBS_LOGIN = 2,
216 						FIBS_MOTD = 3,
217 						FIBS_RUN = 4,
218 						FIBS_LOGOUT = 5,
219 						FIBS_REGISTER = 6;
220 	
221 	private int messageState = FIBS_UNINITIALIZED;
222 
223 	private	LinkedList<CookieDough>	alphaBatch;
224 	private	LinkedList<CookieDough>	starsBatch;
225 	private	LinkedList<CookieDough>	numericBatch;
226 	private	LinkedList<CookieDough>	loginBatch;
227 	private	LinkedList<CookieDough>	registerBatch;
228 	private	LinkedList<CookieDough>	motdBatch;
229 
230 	public void setClientConnection(ClientConnection clientConnection) {
231 		this.clientConnection = clientConnection;
232 	}
233 
234 	/** Parse this message into a fibs cookie
235 	 * @param message A single line from fibs 
236 	 * @return The cookie that matches this string
237 	 */
238 	public int fIBSCookie(String message) {
239 		if (messageState == FIBS_UNINITIALIZED) {
240 			prepareBatches();
241 		}
242 		int result = FIBS_Unknown;
243 		Iterator<CookieMonster.CookieDough> iter;
244 		CookieDough ptr = null;
245 		
246 		switch (messageState) {
247 		case FIBS_UNINITIALIZED:
248 			return(FIBS_BAD_COOKIE);
249 		case FIBS_RUN:
250 			if (message.length() == 0)
251 				return(FIBS_Empty);
252 			char ch = message.charAt(0);
253 			if (ch >= '0' && ch <= '9') {
254 				iter = numericBatch.iterator();
255 				while (iter.hasNext()) {
256 					ptr = iter.next();
257 					//System.out.println("regex=" + ptr.regex.toString());
258 					if (ptr.regex.matcher(message).find()) {
259 						result = ptr.message;
260 						break;
261 					}
262 				}
263 			} else if (ch == '*') {
264 				iter = starsBatch.iterator();
265 				while (iter.hasNext()) {
266 					ptr = iter.next();
267 					if (ptr.regex.matcher(message).find()) {
268 						result = ptr.message;
269 						break;
270 					}
271 				}
272 			} else {
273 				iter = alphaBatch.iterator();
274 				while (iter.hasNext()) {
275 					ptr = iter.next();
276 					if (ptr.regex.matcher(message).find()) {
277 						result = ptr.message;
278 						break;
279 					}
280 				}
281 			}
282 			if (result == FIBS_Goodbye)
283 				messageState = FIBS_LOGOUT;
284 			break;
285 		case FIBS_LOGIN:
286 			result = FIBS_PreLogin;
287 			iter = loginBatch.iterator();
288 			while (iter.hasNext()) {
289 				ptr = iter.next();
290 				if (ptr.regex.matcher(message).find()) {
291 					result = ptr.message;
292 					break;
293 				}
294 			}
295 			if (result == CLIP_MOTD_BEGIN)
296 				messageState = FIBS_MOTD;
297 			if (result == FIBS_WelcomeToFibs)
298 				messageState = FIBS_REGISTER;
299 			break;
300 		case FIBS_MOTD:
301 			result = FIBS_MOTD;
302 			iter = motdBatch.iterator();
303 			while (iter.hasNext()) {
304 				ptr = iter.next();
305 				if (ptr.regex.matcher(message).find()) {
306 					result = ptr.message;
307 					break;
308 				}
309 			}
310 			if (result == CLIP_MOTD_END)
311 				messageState = FIBS_RUN;
312 			break;
313 		case FIBS_REGISTER:
314 			result = FIBS_MOTD;
315 			iter = registerBatch.iterator();
316 			while (iter.hasNext()) {
317 				ptr = iter.next();
318 				if (ptr.regex.matcher(message).find()) {
319 					result = ptr.message;
320 					break;
321 				}
322 			}
323 			break;
324 		case FIBS_LOGOUT:
325 			return(FIBS_PostGoodbye);
326 		}
327 		if (result == FIBS_Unknown)
328 			return(FIBS_Unknown);
329 		String[] ss = ptr.regex.split(message, 2);
330 		if (ss.length > 1 && ss[1].length() > 0) {
331 			if (DEBUG) {
332 				System.out.println("cookie   = " + result);
333 				System.out.println("message  = '" + message + "'");
334 				System.out.println("Leftover = '" + ss[1] + "'");
335 			}
336 			clientConnection.pushBack(ss[1]);
337 		}
338 		return(result);
339 	}
340 
341 	/** Call this function to reset before reconnecting to FIBS.
342 	 * If the batches have already been initialized, just reset the<br>
343 	 * message state, else do the initialization.<br>
344 	 * <br>
345 	 * Note that it is not necessary to call this function before calling<br>
346 	 * fIBSCookie(), which calls prepareBatches() on first use if needed.<br>
347 	 * You can call this function first however, to make sure things<br>
348 	 * are ready to go when you connect.<br>
349 	 */
350 	public void reset()
351 	{
352 		if (messageState == FIBS_UNINITIALIZED)
353 			prepareBatches();
354 		else
355 			messageState = FIBS_LOGIN;
356 	}
357 
358 	
359 	LinkedList<CookieDough>	currentBatchBuild;
360 
361 	private void addDough(int msg, String re) {
362 		CookieDough newDough = new CookieDough();
363 
364 		newDough.regex = Pattern.compile(re);
365 		newDough.message = msg;
366 		currentBatchBuild.add(newDough);
367 		//return newDough;
368 	}
369 
370 	private static String PL = "[a-zA-Z0-9_<>]+";
371 	
372 	private void prepareBatches() {
373 		currentBatchBuild = new LinkedList<CookieDough>();
374 
375 //		addDough(FIBS_Board, 				"^board:" + PL + ":" + PL + ":[0-9:\\-]+$");	// 52 colons
376 		addDough(FIBS_Board, 				"^board:" + PL + ":" + PL + "(:\\-*[0-9]+){49}:[0-9]");	// 52 colons
377 //		addDough(FIBS_BAD_Board,			"^board:");
378 		addDough(FIBS_YouRoll,				"^You roll [1-6] and [1-6]\\.");
379 		addDough(FIBS_PlayerRolls,			"^" + PL + " rolls [1-6] and [1-6]\\.");
380 		
381 		addDough(FIBS_RollOrDouble,			"^It's your turn to roll or double\\.?");
382 		addDough(FIBS_RollOrDouble,			"^It's your turn\\. Please roll or double\\.?");
383 		addDough(FIBS_AcceptRejectDouble,	"doubles\\. Type 'accept' or 'reject'\\.");
384 		addDough(FIBS_Doubles,				"^" + PL + " doubles\\.");
385 		addDough(FIBS_PlayerAcceptsDouble,	"accepts the double\\. The cube shows [0-9]+\\.");
386 		addDough(FIBS_PleaseMove,			"^Please move [1-4] pieces?\\.");
387 //		addDough(FIBS_PlayerMoves,			"^" + PL + " moves .*-off ");
388 		addDough(FIBS_PlayerMoves,			"^" + PL + " moves .*\\. ?");
389 		addDough(FIBS_PlayerMoves,			"^" + PL + " moves .*$");		// XXX: run to the end of line, doesn't handle runons.
390 //		addDough(FIBS_BearingOff,			"^Bearing off: [0-9]+ o .*$");	// XXX: run to the end of line, doesn't handle runons. 
391 		addDough(FIBS_BearingOff,			"^Bearing off: [0-9]+ o [0-9]+ o [0-9]+ o [0-9]+ o ");
392 		addDough(FIBS_BearingOff,			"^Bearing off: [0-9]+ o [0-9]+ o [0-9]+ o ");
393 		addDough(FIBS_BearingOff,			"^Bearing off: [0-9]+ o [0-9]+ o ");
394 		addDough(FIBS_BearingOff,			"^Bearing off: [0-9]+ o ");
395 		addDough(FIBS_YouReject,			"^You reject\\. The game continues\\.");
396 		addDough(FIBS_YouStopWatching,		"You're not watching anymore\\.");		// overloaded	//PLAYER logs out.. You're not watching anymore.
397 		addDough(FIBS_OpponentLogsOut,		"The game was saved\\.");					// PLAYER logs out. The game was saved. ||  PLAYER drops connection. The game was saved.
398 		addDough(FIBS_GameWasSaved,			"Your game with " + PL + " was saved\\.");					// PLAYER logs out. The game was saved. ||  PLAYER drops connection. The game was saved.
399 		addDough(FIBS_OnlyPossibleMove,		"^The only possible move is .* \\.");
400 		addDough(FIBS_FirstRoll,			"" + PL + " rolled [1-6].+rolled [1-6]");
401 		addDough(FIBS_MakesFirstMove,		" makes the first move\\.");
402 		addDough(FIBS_YouDouble,			"^You double\\. Please wait for " + PL + " to accept or reject\\.");	// You double. Please wait for PLAYER to accept or reject.
403 		addDough(FIBS_PlayerWantsToResign,	"^" + PL + " wants to resign\\. You will win [0-9]+ points?\\. Type 'accept' or 'reject'\\.");
404 		addDough(FIBS_WatchResign,			"^" + PL + " wants to resign\\. " + PL + " will win [0-9]+ points?\\.");	// PLAYER wants to resign. PLAYER2 will win 2 points.  (ORDER MATTERS HERE)
405 		addDough(FIBS_YouResign,			"^You want to resign\\. " + PL + " will win [0-9]+ points?\\.");	// You want to resign. PLAYER will win 1 .
406 		addDough(FIBS_ResumeMatchAck5,		"^You are now playing with " + PL + "\\. Your running match was loaded\\.");
407 		addDough(FIBS_JoinNextGame,			"^Type 'join' if you want to play the next game, type 'leave' if you don't\\.");
408 		addDough(FIBS_NewMatchRequest,		"^" + PL + " wants to play a [0-9]+ point match with you\\.");
409 		addDough(FIBS_WARNINGSavedMatch,	"^WARNING: Don't accept if you want to continue .* match\\!");
410 		addDough(FIBS_ResignRefused,		"rejects\\. The game continues\\.");
411 		addDough(FIBS_MatchLength,			"^match length: [0-9]+");
412 		addDough(FIBS_TypeJoin,				"^Type 'join " + PL + "' to accept\\.");
413 		addDough(FIBS_YouAreWatching,		"^You're now watching " + PL + "\\.");
414 		addDough(FIBS_YouStopWatching,		"^You stop watching " + PL + "\\.");		// overloaded
415 		addDough(FIBS_PlayerStartsWatching,	"" + PL + " starts watching " + PL + "\\.");
416 		addDough(FIBS_PlayerStartsWatching,	"" + PL + " is watching you\\.");
417 		addDough(FIBS_PlayerStopsWatching,	"" + PL + " stops watching " + PL + "\\.");
418 		addDough(FIBS_PlayerIsWatching,		"" + PL + " is watching ");
419 		addDough(FIBS_NotInteresting,		"" + PL + " is not doing anything interesting\\.");
420 		
421 		addDough(FIBS_ResignWins,			"^" + PL + " gives up\\. " + PL + " wins [0-9]+ points?\\.");	// PLAYER1 gives up. PLAYER2 wins 1 point.
422 		addDough(FIBS_ResignYouWin,			"^" + PL + " gives up\\. You win [0-9]+ points?\\.");
423 		addDough(FIBS_YouAcceptAndWin,		"^You accept and win [0-9]+ points?\\.");
424 		addDough(FIBS_AcceptWins,			"^" + PL + " accepts and wins [0-9]+ points?\\.");			// PLAYER accepts and wins N points.
425 		addDough(FIBS_PlayersStartingMatch,	"^" + PL + " and " + PL + " start a [0-9]+ point match\\.");	// PLAYER and PLAYER start a <n> point match.
426 		addDough(FIBS_StartingNewGame,		"^Starting a new game with " + PL + "\\.");
427 		addDough(FIBS_StartingNewGameInMatch,"^Starting a new game in the match\\.");
428 		addDough(FIBS_YouGiveUp,			"^You give up\\. " + PL + " wins [0-9]+ points?\\.");
429 		addDough(FIBS_YouWinMatch,			"^You win the [0-9]+ point match [0-9]+-[0-9]+ \\.");
430 		addDough(FIBS_PlayerWinsMatch,		"^" + PL + " wins the [0-9]+ point match [0-9]+-[0-9]+ \\.");	//PLAYER wins the 3 point match 3-0 .
431 		addDough(FIBS_ResumingUnlimitedMatch,"^" + PL + " and " + PL + " are resuming their unlimited match\\.");
432 		addDough(FIBS_ResumingLimitedMatch,	"^" + PL + " and " + PL + " are resuming their [0-9]+-point match\\.");
433 		addDough(FIBS_MatchResult,			"^" + PL + " wins a [0-9]+ point match against " + PL + "  [0-9]+-[0-9]+ \\.");	//PLAYER wins a 9 point match against PLAYER  11-6 .
434 		addDough(FIBS_PlayerWantsToResign,	"wants to resign\\.");		//  Same as a longline in an actual game  This is just for watching.
435 
436 //		addDough(FIBS_BAD_AcceptDouble,		"^" + PL + " accepts? the double\\. The cube shows [0-9]+\\..+");
437 		addDough(FIBS_YouAcceptDouble,		"^You accept the double\\. The cube shows [0-9]+\\.");
438 		addDough(FIBS_PlayerAcceptsDouble,	"^" + PL + " accepts the double\\. The cube shows [0-9]+\\.");
439 		addDough(FIBS_PlayerAcceptsDouble,	"^" + PL + " accepts the double\\.");		// while watching
440 		addDough(FIBS_ResumeMatchRequest,	"^" + PL + " wants to resume a saved match with you\\.");
441 		addDough(FIBS_ResumeMatchAck0,		"has joined you\\. Your running match was loaded\\.");
442 		addDough(FIBS_YouWinGame,			"^You win the game and get [0-9]+ points?\\. Congratulations\\!");	// Jibs spells congratulations wrong.
443 		addDough(FIBS_UnlimitedInvite,		"^" + PL + " wants to play an unlimted match with you\\.");
444 		addDough(FIBS_PlayerWinsGame,		"^" + PL + " wins the game and gets [0-9]+ points?. Sorry.");
445 		addDough(FIBS_PlayerWinsGame,		"^" + PL + " wins the game and gets [0-9]+ points?. ");	// (when watching)
446 //		addDough(FIBS_WatchGameWins,		"wins the game and gets");		// what is this crap? partial message?
447 		addDough(FIBS_PlayersStartingUnlimitedMatch,	"start an unlimited match\\.");	// PLAYER_A and PLAYER_B start an unlimited match.
448 		addDough(FIBS_ReportLimitedMatch,	"^" + PL + " +- +" + PL + " .+ point match");	// PLAYER_A        -       PLAYER_B (5 point match 2-2)
449 		addDough(FIBS_ReportUnlimitedMatch,	"^" + PL + " +- +" + PL + " \\(unlimited");
450 		addDough(FIBS_ShowMovesStart,		"^" + PL + " is X - " + PL + " is O");
451 		addDough(FIBS_ShowMovesRoll,		"^[XO]: \\([1-6]");	// ORDER MATTERS HERE
452 		addDough(FIBS_ShowMovesWins,		"^[XO]: wins");
453 		addDough(FIBS_ShowMovesDoubles,		"^[XO]: doubles");
454 		addDough(FIBS_ShowMovesAccepts,		"^[XO]: accepts");
455 		addDough(FIBS_ShowMovesRejects,		"^[XO]: rejects");
456 		addDough(FIBS_ShowMovesOther,		"^[XO]:");			// AND HERE
457 		addDough(FIBS_ScoreUpdate,			"^score in [0-9]+ point match: " + PL + "-[0-9]+ " + PL + "-[0-9]+");
458 		addDough(FIBS_MatchStart,			"^Score is [0-9]+-[0-9]+ in a [0-9]+ point match\\.");
459 		addDough(FIBS_Settings,				"^Settings of variables:");
460 		addDough(FIBS_Turn,					"^turn: " + PL + "\\.");
461 		addDough(FIBS_Boardstyle,			"^boardstyle:");
462 		addDough(FIBS_Linelength,			"^linelength:");
463 		addDough(FIBS_Pagelength,			"^pagelength:");
464 		addDough(FIBS_Redoubles,			"^redoubles:");
465 		addDough(FIBS_Sortwho,				"^sortwho:");
466 		addDough(FIBS_Timezone,				"^timezone:");
467 		addDough(FIBS_YouCantMove,			"^You can't move\\.");
468 		addDough(FIBS_CantMove,				"^" + PL + " can't move\\.");	// PLAYER can't move
469 		addDough(FIBS_ListOfGames,			"^List of games:");
470 		addDough(FIBS_PlayerInfoStart,		"^Information about " + PL + ":");
471 		addDough(FIBS_EmailAddress,			"^  Email address:.*");
472 		addDough(FIBS_NoEmail,				"^  No email address\\.");
473 		addDough(FIBS_WavesAgain,			"^" + PL + " waves goodbye again\\.");
474 		addDough(FIBS_Waves,				"waves goodbye\\.");
475 		addDough(FIBS_Waves,				"^You wave goodbye\\.");
476 		addDough(FIBS_WavesAgain,			"^You wave goodbye again and log out\\.");
477 		addDough(FIBS_NoSavedGames,			"^no saved games\\.");
478 		addDough(FIBS_HasSavedGames,		"^" + PL + " has [0-9]+ saved games?\\.");
479 		addDough(FIBS_HasNoSavedGames,		"^" + PL + " has no saved games\\.");
480 		addDough(FIBS_TypeBack,				"^You're away\\. Please type 'back'");
481 		addDough(FIBS_SavedMatch,			"^  " + PL + " +[0-9]+ +[0-9]+ +- +[0-9]+");
482 		addDough(FIBS_SavedMatchPlaying,	"^ \\*" + PL + " +[0-9]+ +[0-9]+ +- +[0-9]+");
483 		// NOTE: for FIBS_SavedMatchReady, see the Stars message, because it will appear to be one of those (has asterisk at index 0).
484 		addDough(FIBS_PlayerIsWaitingForYou,"^" + PL + " is waiting for you to log in\\.");
485 		addDough(FIBS_IsAway,				"^" + PL + " is away: .*");
486 		addDough(FIBS_AllowpipTrue,			"^allowpip +YES");
487 		addDough(FIBS_AllowpipFalse,		"^allowpip +NO");
488 		addDough(FIBS_AutoboardTrue,		"^autoboard +YES");
489 		addDough(FIBS_AutoboardFalse,		"^autoboard +NO");
490 		addDough(FIBS_AutodoubleTrue,		"^autodouble +YES");
491 		addDough(FIBS_AutodoubleFalse,		"^autodouble +NO");
492 		addDough(FIBS_AutomoveTrue,			"^automove +YES");
493 		addDough(FIBS_AutomoveFalse,		"^automove +NO");
494 		addDough(FIBS_BellTrue,				"^bell +YES");
495 		addDough(FIBS_BellFalse,			"^bell +NO");
496 		addDough(FIBS_CrawfordTrue,			"^crawford +YES");
497 		addDough(FIBS_CrawfordFalse,		"^crawford +NO");
498 		addDough(FIBS_DoubleTrue,			"^double +YES");
499 		addDough(FIBS_DoubleFalse,			"^double +NO");
500 		addDough(FIBS_MoreboardsTrue,		"^moreboards +YES");
501 		addDough(FIBS_MoreboardsFalse,		"^moreboards +NO");
502 		addDough(FIBS_MovesTrue,			"^moves +YES");
503 		addDough(FIBS_MovesFalse,			"^moves +NO");
504 		addDough(FIBS_GreedyTrue,			"^greedy +YES");
505 		addDough(FIBS_GreedyFalse,			"^greedy +NO");
506 		addDough(FIBS_NotifyTrue,			"^notify +YES");
507 		addDough(FIBS_NotifyFalse,			"^notify +NO");
508 		addDough(FIBS_RatingsTrue,			"^ratings +YES");
509 		addDough(FIBS_RatingsFalse,			"^ratings +NO");
510 		addDough(FIBS_ReadyTrue,			"^ready +YES");
511 		addDough(FIBS_ReadyFalse,			"^ready +NO");
512 		addDough(FIBS_ReportTrue,			"^report +YES");
513 		addDough(FIBS_ReportFalse,			"^report +NO");
514 		addDough(FIBS_SilentTrue,			"^silent +YES");
515 		addDough(FIBS_SilentFalse,			"^silent +NO");
516 		addDough(FIBS_TelnetTrue,			"^telnet +YES");
517 		addDough(FIBS_TelnetFalse,			"^telnet +NO");
518 		addDough(FIBS_WrapTrue,				"^wrap +YES");
519 		addDough(FIBS_WrapFalse,			"^wrap +NO");
520 		addDough(FIBS_Junk,					"^Closed old connection with user");
521 		addDough(FIBS_Done,					"^Done\\.");
522 		addDough(FIBS_YourTurnToMove,		"^It's your turn to move\\.");
523 		addDough(FIBS_SavedMatchesHeader,	"^  opponent          matchlength   score \\(your points first\\)");
524 		addDough(FIBS_MessagesForYou,		"^There are messages for you:");
525 		addDough(FIBS_RedoublesSetTo,		"^Value of 'redoubles' set to [0-9]+\\.");
526 		addDough(FIBS_BoardstyleSetTo,		"^Value of 'boardstyle' set to [0-9]+\\.");
527 		addDough(FIBS_DoublingCubeNow,		"^The number on the doubling cube is now [0-9]+");
528 		addDough(FIBS_FailedLogin,			"^> [0-9]+");							// bogus CLIP messages sent after a failed login
529 		addDough(FIBS_Average,				"^Time (UTC)  average min max");
530 		addDough(FIBS_DiceTest,				"^[nST]: ");
531 		addDough(FIBS_LastLogout,			"^  Last logout:.*");
532 		addDough(FIBS_RatingCalcStart,		"^rating calculation:");
533 		addDough(FIBS_RatingCalcInfo,		"^Probability that underdog wins:");
534 		addDough(FIBS_RatingCalcInfo,		"is 1-Pu if underdog wins");	// P=0.505861 is 1-Pu if underdog wins and Pu if favorite wins
535 		addDough(FIBS_RatingCalcInfo,		"^Experience: ");					// Experience: fergy 500 - jfk 5832
536 		addDough(FIBS_RatingCalcInfo,		"^K=max\\(1");						// K=max(1 ,		-Experience/100+5) for fergy: 1.000000
537 		addDough(FIBS_RatingCalcInfo,		"^rating difference");
538 		addDough(FIBS_RatingCalcInfo,		"^change for");					// change for fergy: 4*K*sqrt(N)*P=2.023443
539 		addDough(FIBS_RatingCalcInfo,		"^match length  ");
540 		addDough(FIBS_WatchingHeader,		"^Watching players:");
541 		addDough(FIBS_SettingsHeader,		"^The current settings are:");
542 		addDough(FIBS_AwayListHeader,		"^The following users are away:");
543 		addDough(FIBS_RatingExperience,		"^  Rating: +[0-9]+\\..*Experience: [0-9]+");				// Rating: 1693.11 Experience: 5781
544 		addDough(FIBS_ReadyWatchingPlaying,	"^  " + PL + ".* playing\\.");				// dickbalaska is ready to play, not watching, not playing.
545 		addDough(FIBS_PlayerLeftGame,		PL + " has left the game with " + PL + "\\.");
546 		
547 		addDough(FIBS_NotLoggedIn,			"^  Not logged in right now\\.");
548 		addDough(FIBS_IsPlayingWith,		"is playing with " + PL + "\\.");
549 		addDough(FIBS_SavedScoreHeader,		"^opponent +matchlength");		//	opponent          matchlength   score (your points first)
550 		addDough(FIBS_StillLoggedIn,		"^  Still logged in\\. .* idle\\.");			//  Still logged in. 2:12 minutes idle.
551 		addDough(FIBS_NoOneIsAway,			"^None of the users is away\\.");
552 		addDough(FIBS_PlayerListHeader,		"^No  S  username        rating  exp login    idle  from");
553 		addDough(FIBS_RatingsHeader,		"^ rank name            rating    Experience");
554 		addDough(FIBS_ClearScreen,			"^.\\[;H.\\[2J");				// ANSI clear screen sequence
555 		addDough(FIBS_Timeout,				"^Connection timed out\\.");
556 		addDough(FIBS_Goodbye,				"           Goodbye\\.");
557 		addDough(FIBS_LastLogin,			"^  Last login: .*");
558 		addDough(FIBS_NoInfo,				"^No information found on user");
559 		addDough(FIBS_PointsFor,			"^points for " + PL + ": [0-9]+");
560 		addDough(FIBS_YouBannedWatch,		"^" + PL + " bans you from watching\\.");
561 		addDough(FIBS_PlayerBannedWatch,	"^" + PL + " bans " + PL + " from watching\\.");
562 		addDough(FIBS_YourEmailChanged,		"^Your email address is .*");
563 
564 		this.alphaBatch = this.currentBatchBuild;
565 
566 		//--- Numeric messages ---------------------------------------------------
567 		currentBatchBuild = new LinkedList<CookieDough>();
568 		addDough(CLIP_WHO_INFO, 			"^5 [^ ]+ - - [01].*");
569 		addDough(CLIP_WHO_INFO,				"^5 [^ ]+ [^ ]+ - [01].*");
570 		addDough(CLIP_WHO_INFO,				"^5 [^ ]+ - [^ ]+ [01].*");
571 
572 		addDough(FIBS_Average,				"^[0-9][0-9]:[0-9][0-9]-");			// output of average command
573 		addDough(FIBS_DiceTest,				"^[1-6]-1 [0-9]");					// output of dicetest command
574 		addDough(FIBS_DiceTest,				"^[1-6]: [0-9]");
575 		addDough(FIBS_Stat,					"^[0-9]+ bytes");					// output from stat command
576 		addDough(FIBS_Stat,					"^[0-9]+ accounts");
577 		addDough(FIBS_Stat,					"^[0-9]+ ratings saved. reset log");
578 		addDough(FIBS_Stat,					"^[0-9]+ registered users.");
579 		addDough(FIBS_Stat,					"^[0-9]+\\([0-9]+\\) saved games check by cron");
580 
581 		addDough(CLIP_WHO_END,				"^6.*$");
582 		addDough(CLIP_SHOUTS,				"^13 " + PL + " .*");
583 		addDough(CLIP_SAYS,					"^12 " + PL + " .*");
584 		addDough(CLIP_WHISPERS,				"^14 " + PL + " .*");
585 		addDough(CLIP_KIBITZES,				"^15 " + PL + " .*");
586 		addDough(CLIP_YOU_SAY,				"^16 " + PL + " .*");
587 		addDough(CLIP_YOU_SHOUT,			"^17 .*");
588 		addDough(CLIP_YOU_WHISPER,			"^18 .*");
589 		addDough(CLIP_YOU_KIBITZ,			"^19 .*");
590 		addDough(CLIP_LOGIN,				"^7 " + PL + " " + PL + " logs in\\.");
591 		addDough(CLIP_LOGIN,				"^7 " + PL + " " + PL + " logs in again\\.");
592 		addDough(CLIP_LOGIN,				"^7 " + PL + " " + PL + " just registered and logs in\\.");
593 		addDough(CLIP_LOGOUT,				"^8 " + PL + " .*");
594 		addDough(CLIP_LOGOUT,				"^8  " + PL + " .*");
595 		addDough(CLIP_MESSAGE,				"^9 " + PL + " [0-9]+ .*");
596 		addDough(CLIP_MESSAGE_DELIVERED,	"^10 " + PL + "$");
597 		addDough(CLIP_MESSAGE_SAVED,		"^11 " + PL + "$");
598 		this.numericBatch = this.currentBatchBuild;
599 		
600 		//--- '**' messages ------------------------------------------------------
601 		currentBatchBuild = new LinkedList<CookieDough>();
602 		addDough(FIBS_Username,				"^\\*\\* User");
603 		addDough(FIBS_Junk,					"^\\*\\* You tell ");				// "** You tell PLAYER: xxxxx"
604 		addDough(FIBS_YouGag,				"^\\*\\* You gag");
605 		addDough(FIBS_YouUngag,				"^\\*\\* You ungag");
606 		addDough(FIBS_YouBlind,				"^\\*\\* You blind");
607 		addDough(FIBS_YouUnblind,			"^\\*\\* You unblind");
608 		addDough(FIBS_UseToggleReady,		"^\\*\\* Use 'toggle ready' first");
609 		addDough(FIBS_NewMatchAck9,			"^\\*\\* You are now playing an unlimited match with ");
610 		addDough(FIBS_NewMatchAck10,		"^\\*\\* You are now playing a [0-9]+ point match with " + PL);	// ** You are now playing a 5 point match with PLAYER
611 		addDough(FIBS_NewMatchAck2,			"^\\*\\* Player " + PL + " has joined you for a [0-9]+ point match\\.");	// ** Player PLAYER has joined you for a 2 point match.
612 		addDough(FIBS_YouTerminated,		"^\\*\\* You terminated the game");
613 		addDough(FIBS_OpponentLeftGame,		"^\\*\\* Player " + PL + " has left the game. The game was saved\\.");
614 		addDough(FIBS_YouInvited,			"^\\*\\* You invited .* match\\.");
615 		addDough(FIBS_YourLastLogin,		"^\\*\\* Last login:");
616 		addDough(FIBS_NoOne,				"^\\*\\* There is no one called " + PL + "\\.");
617 		addDough(FIBS_AllowpipFalse,		"^\\*\\* You don't allow the use of the server's 'pip' command\\.");
618 		addDough(FIBS_AllowpipTrue,			"^\\*\\* You allow the use the server's 'pip' command\\.");
619 		addDough(FIBS_AutoboardFalse,		"^\\*\\* The board won't be refreshed");
620 		addDough(FIBS_AutoboardTrue,		"^\\*\\* The board will be refreshed");
621 		addDough(FIBS_AutodoubleTrue,		"^\\*\\* You agree that doublets");
622 		addDough(FIBS_AutodoubleFalse,		"^\\*\\* You don't agree that doublets");
623 		addDough(FIBS_AutomoveFalse,		"^\\*\\* Forced moves won't");
624 		addDough(FIBS_AutomoveTrue,			"^\\*\\* Forced moves will");
625 		addDough(FIBS_BellFalse,			"^\\*\\* Your terminal won't ring");
626 		addDough(FIBS_BellTrue,				"^\\*\\* Your terminal will ring");
627 		addDough(FIBS_CrawfordFalse,		"^\\*\\* You would like to play without using the Crawford rule\\.");
628 		addDough(FIBS_CrawfordTrue,			"^\\*\\* You insist on playing with the Crawford rule\\.");
629 		addDough(FIBS_DoubleFalse,			"^\\*\\* You won't be asked if you want to double\\.");
630 		addDough(FIBS_DoubleTrue,			"^\\*\\* You will be asked if you want to double\\.");
631 		addDough(FIBS_GreedyTrue,			"^\\*\\* Will use automatic greedy bearoffs\\.");
632 		addDough(FIBS_GreedyFalse,			"^\\*\\* Won't use automatic greedy bearoffs\\.");
633 		addDough(FIBS_MoreboardsTrue,		"^\\*\\* Will send rawboards after rolling\\.");
634 		addDough(FIBS_MoreboardsFalse,		"^\\*\\* Won't send rawboards after rolling\\.");
635 		addDough(FIBS_MovesTrue,			"^\\*\\* You want a list of moves after this game\\.");
636 		addDough(FIBS_MovesFalse,			"^\\*\\* You won't see a list of moves after this game\\.");
637 		addDough(FIBS_NotifyFalse,			"^\\*\\* You won't be notified");
638 		addDough(FIBS_NotifyTrue,			"^\\*\\* You'll be notified");
639 		addDough(FIBS_RatingsTrue,			"^\\*\\* You'll see how the rating changes are calculated\\.");
640 		addDough(FIBS_RatingsFalse,			"^\\*\\* You won't see how the rating changes are calculated\\.");
641 		addDough(FIBS_ReadyTrue,			"^\\*\\* You're now ready to invite or join someone\\.");
642 		addDough(FIBS_ReadyFalse,			"^\\*\\* You're now refusing to play with someone\\.");
643 		addDough(FIBS_ReportFalse,			"^\\*\\* You won't be informed");
644 		addDough(FIBS_ReportTrue,			"^\\*\\* You will be informed");
645 		addDough(FIBS_SilentTrue,			"^\\*\\* You won't hear what other players shout\\.");
646 		addDough(FIBS_SilentFalse,			"^\\*\\* You will hear what other players shout\\.");
647 		addDough(FIBS_TelnetFalse,			"^\\*\\* You use a client program");
648 		addDough(FIBS_TelnetTrue,			"^\\*\\* You use telnet");
649 		addDough(FIBS_WrapFalse,			"^\\*\\* The server will wrap");
650 		addDough(FIBS_WrapTrue,				"^\\*\\* Your terminal knows how to wrap");
651 		addDough(FIBS_PlayerRefusingGames,	"^\\*\\* " + PL + " is refusing games\\.");
652 		addDough(FIBS_NotWatching,			"^\\*\\* You're not watching\\.");
653 		addDough(FIBS_NotWatchingPlaying,	"^\\*\\* You're not watching or playing\\.");
654 		addDough(FIBS_NotPlaying,			"^\\*\\* You're not playing\\.");
655 		addDough(FIBS_EchoJunk,				"^\\*\\* You're not playing, so you can't give up\\.");
656 		addDough(FIBS_EchoJunk,				"^\\*\\* You can't say nothing\\.");
657 		
658 		addDough(FIBS_NoUser,				"^\\*\\* There is no one called " + PL);
659 		addDough(FIBS_AlreadyPlaying,		"is already playing with .*\\.");
660 		addDough(FIBS_BadMove,				"^\\*\\* You can't remove this piece");
661 		addDough(FIBS_YouAlreadyPlaying,	"^\\*\\* You are already playing\\.");
662 		addDough(FIBS_YouAlreadyRolled,		"^\\*\\* You did already roll the dice\\.");
663 		addDough(FIBS_DidntInvite,			"^\\*\\* " + PL + " didn't invite you\\.");
664 		addDough(FIBS_BadMove,				"^\\*\\* You can't remove this piece");
665 		addDough(FIBS_CantMoveFirstMove,	"^\\*\\* You can't move .*move\\.");			// ** You can't move to 14 in your second move.'
666 		addDough(FIBS_CantShout,			"^\\*\\* Please type 'toggle silent' again before you shout\\.");
667 		addDough(FIBS_MustMove,				"^\\*\\* You must give [1-4] moves\\.");
668 		addDough(FIBS_MustComeIn,			"^\\*\\* You have to remove pieces from the bar in your first move\\.");
669 		addDough(FIBS_UsersHeardYou,		"^\\*\\* [0-9]+ users? heard you\\.");
670 		addDough(FIBS_PleaseWaitForJoin,	"^\\*\\* Please wait for " + PL + " to join too\\.");
671 		addDough(FIBS_SavedMatchReady,		"^\\*\\*" + PL + " +[0-9]+ +[0-9]+ +- +[0-9]+");		// double star before a name indicates you have a saved game with this player
672 		addDough(FIBS_NotYourTurnToRoll,	"^\\*\\* It's not your turn to roll the dice\\.");
673 		addDough(FIBS_NotYourTurnToMove,	"^\\*\\* It's not your turn to move\\.");
674 		addDough(FIBS_YouStopWatching,		"^\\*\\* You stop watching " + PL + "\\.");
675 		addDough(FIBS_UnknownCommand,		"^\\*\\* Unknown command: .*");
676 		addDough(FIBS_CantWatch,			"^\\*\\* You can't watch another game while you're playing\\.");
677 		addDough(FIBS_CantInviteSelf,		"^\\*\\* You can't invite yourself\\.");
678 		addDough(FIBS_DontKnowUser,			"^\\*\\* Don't know user");
679 		addDough(FIBS_MessageUsage,			"^\\*\\* usage: message <user> <text>");
680 		addDough(FIBS_PlayerNotPlaying,		"^\\*\\* " + PL + " is not playing\\.");
681 		addDough(FIBS_CantTalk,				"^\\*\\* You can't talk if you won't listen\\.");
682 		addDough(FIBS_WontListen,			"^\\*\\* " + PL + " won't listen to you\\.");
683 		addDough(FIBS_Why,					"Why would you want to do that");		// (not sure about ** vs *** at front of line.)
684 		addDough(FIBS_Ratings,				"^\\* *[0-9]+ +" + PL + " +[0-9]+\\.[0-9]+ +[0-9]+");
685 		addDough(FIBS_NoSavedMatch,			"^\\*\\* There's no saved match with .* length\\.");
686 		addDough(FIBS_WARNINGSavedMatch,	"^\\*\\* WARNING: Don't accept if you want to continue");
687 		addDough(FIBS_CantGagYourself,		"^\\*\\* You talk too much, don't you\\?");
688 		addDough(FIBS_CantBlindYourself,	"^\\*\\* You can't read this message now, can you\\?");
689 		addDough(FIBS_RollBeforeMove,		"^\\*\\* You have to roll the dice before moving\\.");
690 		addDough(FIBS_ATTENTION,			"^\007\\*\\*\\* ATTENTION \\!.*");
691 		addDough(FIBS_ShuttingDown,			"^\\*\\* System administrator causes shutdown\\. FIBS is terminating\\.");
692 		addDough(FIBS_Rebooting,			"^\\*\\* It will be back when the computer is rebooted.");
693 		addDough(FIBS_GamesWillBeSaved,		"^\\*\\* All running games will be saved\\.");
694 		addDough(FIBS_DoesntWantYouToWatch,	"^\\*\\* " + PL + " doesn't want you to watch\\.");
695 		addDough(FIBS_WaitForLastInvitation,"^\\*\\* Wait until " + PL + " accepted or rejected your resign\\.");
696 		addDough(FIBS_WaitForAcceptResign,	"^\\*\\* Please wait for your last invitation to be accepted\\.");
697 		addDough(FIBS_WantedToResign,		"^\\*\\* " + PL + " wanted to resign\\. Type 'accept' or 'reject'\\.");
698 		addDough(FIBS_DidntDoubleOrResign,	"^\\*\\* " + PL + " didn't double or resign\\.");
699 		addDough(FIBS_NobodyHeardYou,		"^\\*\\* But nobody heard you\\.");
700 		addDough(FIBS_CantWatchSelf,		"^\\*\\* Use a mirror to do that\\.");		
701 		
702 				
703 		this.starsBatch = this.currentBatchBuild;
704 
705 		currentBatchBuild = new LinkedList<CookieDough>();
706 		addDough(FIBS_LoginPrompt,			"^login:.*");
707 		addDough(CLIP_WELCOME,				"^1 " + PL + " [0-9]+ .*");			// better EOS could be had
708 		addDough(CLIP_OWN_INFO,				"^2 " + PL + " [01] [01] .*");		// better EOS could be had
709 		addDough(CLIP_MOTD_BEGIN,			"^3$");
710 		addDough(FIBS_FailedLogin,			"^> [0-9]+");		// bogus CLIP messages sent after a failed login
711 		addDough(FIBS_WelcomeToFibs,        "^Welcome to \\w+\\.\\s*You just logged in as guest\\.");
712 		this.loginBatch = this.currentBatchBuild;
713 
714 		currentBatchBuild = new LinkedList<CookieDough>();
715 		addDough(FIBS_OneUserPerPerson,		"^\\s*ONE USERNAME PER PERSON ONLY\\!\\!\\!");
716 		addDough(FIBS_GivePassword,			"^Please give your password: ");
717 		addDough(FIBS_RetypePassword,		"^Please retype your password: ");
718 		addDough(FIBS_YouAreRegistered,		"^You are registered\\.");
719 		addDough(FIBS_UseAnotherName,		"^\\*\\* Please use another name\\.");
720 		this.registerBatch = this.currentBatchBuild;
721 
722 		// Only interested in one message here, but we still use a message list for simplicity and consistency.
723 		currentBatchBuild = new LinkedList<CookieDough>();
724 		addDough(CLIP_MOTD_END, "^4$");
725 		this.motdBatch = this.currentBatchBuild;
726 
727 		messageState = FIBS_LOGIN;
728 		
729 	}
730 }