2 * Copyright (C) 2008 Carl Worth
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 3 of the License, or
7 * (at your option) any later version.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see http://www.gnu.org/licenses/ .
17 * Author: Carl Worth <cworth@cworth.org>
30 #include "loa-board.h"
32 typedef struct _loa_game {
38 loa_game_new_game (loa_game_t *game)
40 loa_board_init (&game->board);
44 loa_game_move (loa_game_t *game, const char * peer,
45 int x1, int y1, int x2, int y2)
49 if (! loa_board_move (&game->board, x1, y1, x2, y2, &error)) {
50 loudgame_sendf (&game->lg, peer, "Illegal move: %c%d%c%d: %s",
51 'a' + x1, LOA_BOARD_SIZE - y1,
52 'a' + x2, LOA_BOARD_SIZE - y2,
61 loa_game_handle_show (loa_game_t *game,
65 LmMessageNode *html, *body, *span;
71 reply = lm_message_new (peer, LM_MESSAGE_TYPE_MESSAGE);
72 html = lm_message_node_add_child (reply->node, "html", "");
73 lm_message_node_set_attribute (html,
75 "http://jabber.org/protocol/xhtml-im");
76 body = lm_message_node_add_child (html, "body", "");
77 lm_message_node_set_attribute (body,
79 "http://www.w3.org/1999/xhtml");
81 if (game->board.player == LOA_PLAYER_BLACK)
82 lm_message_node_add_child (body, "span", "Black to move:");
84 lm_message_node_add_child (body, "span", "White to move:");
86 board_string = loa_board_to_string (&game->board);
90 newline = strchr (line, '\n');
93 lm_message_node_add_child (body, "br", "");
94 span = lm_message_node_add_child (body, "span", line);
95 lm_message_node_set_attribute (span, "style",
96 "font-family: Monospace;");
104 result = lm_connection_send (game->lg.connection, reply, &error);
105 lm_message_unref (reply);
108 g_error ("lm_connection_send failed: %s\n",
110 loudgame_quit (&game->lg, 1);
115 loa_game_handle_move (loa_game_t *game,
123 matched = sscanf (move, " %c %d %c %d ", &xc1, &y1, &xc2, &y2);
125 loudgame_sendf (&game->lg, peer,
126 "Error: The 'move' command requires a move of the form 'b1d3'");
130 x1 = tolower (xc1) - 'a';
131 x2 = tolower (xc2) - 'a';
132 /* We use an upper-left origin internally. */
133 y1 = LOA_BOARD_SIZE - y1;
134 y2 = LOA_BOARD_SIZE - y2;
135 if (! loa_game_move (game, peer, x1, y1, x2, y2))
138 loudgame_broadcastf (&game->lg, "%c%d%c%d",
139 'a' + x1, LOA_BOARD_SIZE - y1,
140 'a' + x2, LOA_BOARD_SIZE - y2);
142 if (loa_board_is_won (&game->board, x2, y2))
143 loudgame_broadcastf (&game->lg, "%s wins", peer);
147 loa_game_handle_pass (loa_game_t *game, const char *peer)
149 loudgame_broadcastf (&game->lg, "%s passes", peer);
151 if (loa_board_pass (&game->board))
154 loudgame_sendf (&game->lg, peer,
155 "Error: You cannot pass since you have a legal move available");
159 loa_game_handle_help (loa_game_t *game, const char *peer)
161 loudgame_sendf (&game->lg, peer,
162 "I'm a bot that allows you to play the game Lines of Action.\n"
163 "Here are some generic commands I understand:\n"
166 "And some game-specific commands:\n"
167 "\tshow \t\tShow the current board\n"
168 "\tmove aNbN\tMove a piece, (eg. 'move b1d3')\n"
169 "\tpass \t\tSkip a turn (only legal if no moves are possible)\n"
170 "\tnew \t\tBegin a new game\n"
171 "\thelp \t\tThis help message\n"
172 "\trules \t\tA description of the Lines of Action rules\n"
174 "Lines of Action was invented by Claude Soucie and first made popular\n"
175 "when its rules were published by Sid Sackson in \"A Gamut of Games\" (1969).\n"
177 "If you are new to Lines of Action, type 'rules' now to learn the rules.\n");
181 loa_game_handle_rules (loa_game_t *game, const char *peer)
183 loudgame_sendf (&game->lg, peer,
184 "Lines of Action can be played with a standard (English) checkers set,\n"
185 "that is an 8x8 board and 12 markers each of contrasting colors ('black' and\n"
186 "'white'). The initial placement has 6 each of the black pieces on the top\n"
187 "and bottom rows, and 6 each of the white pieces on the left and right columns\n"
188 "leaving the four corner spaces empty. Play begins with the black player and\n"
191 "On each move a piece is moved in a straight line in any of eight directions,\n"
192 "(similar to a queen's move in chess), but must be moved exactly the same\n"
193 "number of spaces as there are pieces (of either color) in the row, column,\n"
194 "or diagonal of the move. A piece may jump over pieces of its own color, but\n"
195 "may not jump a piece of the opposite color. The final square of the move can\n"
196 "be either empty or can contain a piece of the opposing color, in which case\n"
197 "that piece is removed from the game.\n"
199 "If a player has no possible move, then that player must pass, (but if the\n"
200 "player has a possible move, then the player cannot pass).\n"
202 "The goal of the game is to connect all of your remaining pieces into\n"
203 "a single, connected group. Pieces that are diagonally adjacent are\n"
204 "considered connected.\n"
206 "If a move simultaneously creates a winning condition for both players, this\n"
207 "is considered a win for the player making the move.\n"
209 "Notes on this implementation:\n"
211 "This implementation enforces the move rules described above, but will\n"
212 "allow any person to make moves, (that is, you can control both\n"
213 "colors). Think of it as being somewhat like a physical board where\n"
214 "any person could move the pieces at any time, but generally two people\n"
215 "will take turns and others will politely watch.\n"
217 "Also, the game won't currently show you the board again after a\n"
218 "player makes a move, so you'll need to keep typing 'show' to see\n"
219 "updates. Yes, this is a bug, and yes it will be fixed soon.\n"
221 "Lines of Action was invented by Claude Soucie and first made popular\n"
222 "when its rules were published by Sid Sackson in \"A Gamut of Games\" (1969).\n");
226 loa_game_handle_new (loa_game_t *game, const char *peer)
228 loudgame_broadcastf (&game->lg, "%s has started a new game", peer);
229 loa_game_new_game (game);
233 loa_game_handle_message (loudgame_t *lg,
237 loa_game_t *game = (loa_game_t *) lg;
239 if (strcmp (message, "show") == 0)
240 loa_game_handle_show (game, peer);
241 else if (strncmp (message, "move", 4) == 0)
242 loa_game_handle_move (game, peer, message + 4);
243 else if (strcmp (message, "pass") == 0)
244 loa_game_handle_pass (game, peer);
245 else if (strcmp (message, "new") == 0)
246 loa_game_handle_new (game, peer);
247 else if (strcmp (message, "help") == 0)
248 loa_game_handle_help (game, peer);
249 else if (strcmp (message, "rules") == 0)
250 loa_game_handle_rules (game, peer);
252 loudgame_sendf (lg, peer, "Unknown command: '%s'. Use 'help' to get a list of valid commands.", message);
256 loa_game_init (loa_game_t *game, int argc, char *argv[])
260 err = loudgame_init (&game->lg, argc, argv);
264 loa_game_new_game (game);
270 main (int argc, char **argv)
275 err = loa_game_init (&game, argc, argv);
279 game.lg.handle_message = loa_game_handle_message;
281 err = loudgame_run (&game.lg);