[gnome-games/glchess-fics] Start work on a FICS interface for chess
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/glchess-fics] Start work on a FICS interface for chess
- Date: Sat, 19 Feb 2011 04:03:57 +0000 (UTC)
commit dee691d7f9b0ad381fc52cca79c4c224a6bc9b83
Author: Robert Ancell <robert ancell canonical com>
Date: Sat Feb 19 15:03:50 2011 +1100
Start work on a FICS interface for chess
glchess/src/Makefile.am | 1 +
glchess/src/fics-client.vala | 507 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 508 insertions(+), 0 deletions(-)
---
diff --git a/glchess/src/Makefile.am b/glchess/src/Makefile.am
index 2fb8831..4cdee33 100644
--- a/glchess/src/Makefile.am
+++ b/glchess/src/Makefile.am
@@ -21,6 +21,7 @@ glchess_SOURCES = \
chess-view-2d.vala \
chess-view-3d.vala \
chess-view-options.vala \
+ fics-client.vala \
history.vala
test_chess_game_SOURCES = \
diff --git a/glchess/src/fics-client.vala b/glchess/src/fics-client.vala
new file mode 100644
index 0000000..9795cc2
--- /dev/null
+++ b/glchess/src/fics-client.vala
@@ -0,0 +1,507 @@
+public class FICSClient
+{
+ private Socket socket;
+
+ //private string buffer = "";
+ //longChat = None
+
+ /* Yuck, regular expression is just horrible. I plan to replace this with something readable
+ * (that compiles to regexp if regexp is faster) */
+ private Regex name_assign_pattern;
+ private Regex chat_pattern;
+ private Regex tell_pattern;
+ private Regex say_pattern;
+ private Regex challenge_pattern;
+ private Regex seek_pattern;
+ private Regex end_seek_pattern;
+ private Regex announce_pattern;
+ private Regex game_result_pattern;
+ private Regex example_game_pattern;
+ private Regex game_pattern;
+
+ public FICSClient()
+ {
+ /* Press return to enter the server as "GuestVRDG": */
+ name_assign_pattern = make_regex ("Press return to enter the server as \"(\\S+)\":");
+
+ /* jibbjibb(U)(53): i like cheese */
+ chat_pattern = make_regex ("^(\\S+)[(](\\d+)[)]: (.*)$");
+ /* GuestTLNX(U) tells you: hello! */
+ tell_pattern = make_regex ("^(\\S+)[(](\\S+)[)] tells you: (.*)$");
+ /* GuestTLNX(U)[26] says: hello */
+ say_pattern = make_regex ("^(\\S+)[(](\\S+)[)][[](\\d+)[]] says: (.*)$");
+
+ /* Challenge: GuestKWWN (----) GuestDRJK (----) unrated blitz 2 12. */
+ challenge_pattern = make_regex ("Challenge: (\\S+) [(](\\S{4})[)] \\S+ [(]\\S{4}[)] (\\w+) (\\w+) (\\d+) (\\d+)[.]$");
+
+ /* 19 716 milkhope 5 14 unrated blitz 0-9999 mf */
+ /* 41 1812 CrazyBeukiBot(C) 2 12 unrated blitz 0-9999 */
+ /* 50 1190 rauschdesign 10 0 unrated blitz [white] 0-9999 f */
+ /* 70 1157 stshot 12 1 unrated blitz 0-1300 */
+ seek_pattern = make_regex ("^\\s*(\\d+)\\s+(\\S{4}) (\\S+)\\s+(\\d+)\\s+(\\d+) (\\S+) (\\S+)\\s+(\\S*)\\s+(\\d+)-\\s*(\\d+)\\s*(\\S*)$");
+
+ /* 1 ad displayed. */
+ /* 9 ads displayed. */
+ end_seek_pattern = make_regex ("^(\\d+) ads? displayed.$");
+
+ /* GuestJXJT (++++) seeking 0 1 unrated lightning ("play 15" to respond) */
+ announce_pattern = make_regex ("^(\\S+) [(](\\S{4})[)] seeking (\\d+) (\\d+) (\\w+) (\\w+)(.*) [(]\"play (\\d+)\" to respond[)]$");
+
+ /* {Game 109 (GuestKSBS vs. GuestXKQX) Creating unrated blitz match.} */
+ /* {Game 109 (GuestKSBS vs. GuestXKQX) GuestXKQX forfeits by disconnection} 1-0 */
+ /* {Game 109 (GuestXKQX vs. GuestKSBS) GuestKSBS resigns} 1-0 */
+ game_result_pattern = make_regex ("^{Game (\\d+) [(](\\S+) vs. (\\S+)[)] (.+)}\\s*(.*)$");
+
+ /* 1 (Exam. 0 Kupreichik 0 talpa ) [ uu 0 0] W: 22 */
+ /* 2 2274 OldManII ++++ Peshkin [ bu 2 12] 2:34 - 1:47 (39-39) B: 3 */
+ example_game_pattern = make_regex ("\\s*(\\d+) [(]Exam[.] (\\S{4}) (\\S+)\\s+(\\S{4}) (\\S+)\\s+ [)] [[]\\s*(\\S+)\\s+(\\d+)\\s+(\\d+)[]] ([WB]):\\s+(\\d+)$");
+ game_pattern = make_regex ("\\s*(\\d+) (\\S{4}) (\\S+)\\s+(\\S{4}) (\\S+)\\s+[[]\\s*(\\S+)\\s+(\\d+)\\s+(\\d+)[]]\\s+(\\d+):(\\d+) -\\s+(\\d+):(\\d+) [(](\\d+)-(\\d+)[)] ([WB]):\\s+(\\d+)$");
+
+ /* TODO: */
+ /* GuestDRJK, whom you were challenging, has departed. */
+ /* Challenge to GuestDRJK withdrawn. */
+ }
+
+ private Regex? make_regex (string pattern)
+ {
+ try
+ {
+ return new Regex (pattern);
+ }
+ catch (RegexError e)
+ {
+ critical ("Failed to make regular expression: %s", e.message);
+ return null;
+ }
+ }
+
+ public void connect (string host = "freechess.org", uint16 port = 5000) throws Error
+ {
+ socket = new Socket (SocketFamily.IPV4, SocketType.STREAM, SocketProtocol.TCP);
+ socket.connect (new InetSocketAddress (new InetAddress.from_string (host), port));
+ var channel = new IOChannel.unix_new (socket.fd);
+ channel.add_watch (IOCondition.IN, read_cb);
+ }
+
+ private bool read_cb (IOChannel source, IOCondition condition)
+ {
+ char data[1024];
+
+ ssize_t n_read;
+ try
+ {
+ n_read = socket.receive ((string) data, data.length);
+ }
+ catch (Error e)
+ {
+ warning ("Error reading from FICS server: %s", e.message);
+ return false;
+ }
+
+ debug ("read %zi", n_read);
+
+#if 0
+ buffer += data;
+
+ callbacks = [];
+ while (true)
+ {
+ index = buffer.find("\n\r");
+ if (index < 0)
+ break;
+
+ line = buffer[:index];
+ buffer = buffer[index+2:];
+
+ /* Strip pesky prompt off the front */
+ if (line.has_prefix (PROMPT))
+ {
+ line = line[len(PROMPT):];
+ callbacks.append((onPrompt, ()));
+ if (len(line) == 0)
+ continue;
+ }
+
+ (callback, data) = parseLine(line);
+ if (callback is not None)
+ callbacks.append((callback, data));
+ }
+
+ (callback, data) = parsePrompt(buffer);
+ if (callback is not None)
+ callbacks.append((callback, data));
+
+ for ((callback, data) in callbacks)
+ callback(*data);
+#endif
+
+ return false;
+ }
+
+ private bool parse_line (string line)
+ {
+#if 0
+ /* Join continuing chat messages */
+ if (longChat != None)
+ {
+ /* Remove leading space ("\ text") */
+ while (line.has_prefix ("\\"))
+ line = line[1:];
+ while (line.has_prefix (" "))
+ line = line[1:];
+ longChat += line;
+
+ /* Continues on the next line too */
+ if (line[-1] == " ")
+ return (None, None);
+
+ text = longChat;
+ longChat = None;
+ return (onChat, (longChatOptions[0], longChatOptions[1], text));
+ }
+#endif
+
+ if (parse_line_game (line) ||
+ parse_line_example_game (line) ||
+ parse_line_name_assign (line) ||
+ parse_line_seek (line) ||
+ parse_line_end_seek (line) ||
+ parse_line_announce (line) ||
+ parse_line_challenge (line) ||
+ parse_line_game_result (line) ||
+ parse_line_chat (line) ||
+ parse_line_tell (line) ||
+ parse_line_say (line) ||
+ parse_line_game_move (line) ||
+ parse_line_seek_add (line) ||
+ parse_line_seek_remove (line) ||
+ parse_line_seek_clear (line) ||
+ parse_prompt (line))
+ return true;
+
+ return false;
+ }
+
+ private bool parse_line_game (string line)
+ {
+ MatchInfo info;
+ if (!game_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ /* Game in progress */
+ white = Player();
+ black = Player();
+ game = Game();
+ (game.number, white.rating, white.name, black.rating, black.name,
+ game.options, game.a, game.b, whiteMin, whiteSec,
+ blackMin, blackSec,
+ white.strength, black.strength,
+ game.colour, game.moveNumber) = result[0];
+ game.isExample = False;
+ white.time = int(whiteMin) * 60 + int(whiteSec);
+ black.time = int(blackMin) * 60 + int(blackSec);
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_example_game (string line)
+ {
+ MatchInfo info;
+ if (!example_game_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ white = Player();
+ black = Player();
+ game = Game();
+ (game.number, white.rating, white.name, black.rating, black.name,
+ game.options, game.a, game.b,
+ game.colour, game.moveNumber) = result[0];
+ game.isExample = True;
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_name_assign (string line)
+ {
+ MatchInfo info;
+ if (!name_assign_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ name = result;
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_seek (string line)
+ {
+ MatchInfo info;
+ if (!seek_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ /* Requested seek */
+ player = Player();
+ game = Game();
+ (number,
+ player.rating, player.name,
+ game.a, game.b, game.rating, game.type, game.colour, game.minRating, game.maxRating, game.options) = result[0];
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_end_seek (string line)
+ {
+ MatchInfo info;
+ if (!end_seek_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ //(nSeeks, ) = result;
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_announce (string line)
+ {
+ MatchInfo info;
+ if (!announce_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ /* Dynamic seek */
+ player = Player();
+ game = Game();
+ //(player.name, player.rating, game.a, game.b, game.rating, game.type, game.options, number) = result[0];
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_challenge (string line)
+ {
+ MatchInfo info;
+ if (!challenge_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ /* Explicit challenge */
+ player = Player();
+ game = Game();
+ //(player.name, player.rating, game.rating, game.type, game.a, game.b) = result[0];
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_game_result (string line)
+ {
+ MatchInfo info;
+ if (!game_result_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ /* Game result */
+ white = Player();
+ black = Player();
+ game = Game();
+ //(game.number, white.name, black.name, text, game.result) = result[0];
+ if (game.result == "")
+ game.result = "*";
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_chat (string line)
+ {
+ MatchInfo info;
+ if (!chat_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ //(playerName, channel, text) = result[0];
+ if (text[-1] == " ")
+ {
+ longChat = text;
+ longChatOptions = (channel, playerName);
+ }
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_tell (string line)
+ {
+ MatchInfo info;
+ if (!tell_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ //(playerName, rating, text) = result[0];
+ if (text[-1] == " ")
+ {
+ longChat = text;
+ longChatOptions = ("", playerName);
+ }
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_say (string line)
+ {
+ MatchInfo info;
+ if (!say_pattern.match_all (line, 0, out info))
+ return false;
+
+#if 0
+ //(playerName, rating, game, text) = result[0];
+ if (text[-1] == " ")
+ {
+ longChat = text;
+ longChatOptions = ("", playerName);
+ }
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_game_move (string line)
+ {
+ /* Game move */
+ if (!line.has_prefix ("<12> "))
+ return false;
+
+#if 0
+ try
+ {
+ move = style12.decode(line);
+ }
+ catch (Error e)
+ {
+ debug ("Invalid move: %s (%s)", line, e.message);
+ return false;
+ }
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_seek_add (string line)
+ {
+ if (!line.has_prefix ("<s> "))
+ return false;
+
+#if 0
+ var words = line.split();
+ //player = Player();
+ //game = Game();
+ try
+ {
+ number = int(words[1]);
+ }
+ catch (Error e)
+ {
+ return false;
+ }
+
+ foreach (var word in words[2:])
+ {
+ try
+ {
+ (name, value) = word.split("=", 1);
+ }
+ catch (Error e)
+ {
+ return false;
+ }
+
+ /* FIXME: Accept errors */
+ if (name == "w")
+ player.name = value;
+ else if (name == "ti")
+ ;
+ else if (name == "rt")
+ {
+ while (!value[-1].isdigit())
+ value = value[:-1];
+ player.rating = int(value);
+ }
+ else if (name == "t")
+ game.time = int(value);
+ else if (name == "i")
+ game.inc = int(value);
+ else if (name == "r")
+ game.isRated = value != "0";
+ else if (name == "tp")
+ game.type = value;
+ else if (name == "c")
+ game.colour = value;
+ else if (name == "rr")
+ {
+ (minRating, maxRating) = value.split("-", 1);
+ game.minRating = int(minRating);
+ game.maxRating = int(maxRating);
+ }
+ else if (name == "a")
+ game.isAutomatic = value != "0";
+ else if (name == "f")
+ game.formulaCheked = value != "0";
+ }
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_seek_remove (string line)
+ {
+ if (!line.has_prefix ("<sr> "))
+ return false;
+
+#if 0
+ adverts = [];
+ foreach (var word in line.split()[1:])
+ {
+ try
+ {
+ adverts.append(int(word));
+ }
+ catch (Error e)
+ {
+ return false;
+ }
+ }
+#endif
+
+ return true;
+ }
+
+ private bool parse_line_seek_clear (string line)
+ {
+ if (!line.has_prefix ("<sc>"))
+ return false;
+
+ return true;
+ }
+
+ private bool parse_prompt (string line)
+ {
+ const string PROMPT = "fics% ";
+ const string PROMPT_LOGIN = "login: ";
+
+ if (line == PROMPT_LOGIN)
+ return true;
+ else if (line == PROMPT)
+ return true;
+
+ return false;
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]