summaryrefslogtreecommitdiffstats
path: root/mbbsd/chc.c
diff options
context:
space:
mode:
authorscw <scw@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-08-28 22:36:54 +0800
committerscw <scw@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-08-28 22:36:54 +0800
commit544b6475f029f5396bea9ebca0994111e74d1200 (patch)
treea118f5effae4482def8d881794bf7ea7f676c381 /mbbsd/chc.c
parentbd3cb69722802ca63edbc0d60a8e07f19ab31359 (diff)
downloadpttbbs-544b6475f029f5396bea9ebca0994111e74d1200.tar
pttbbs-544b6475f029f5396bea9ebca0994111e74d1200.tar.gz
pttbbs-544b6475f029f5396bea9ebca0994111e74d1200.tar.bz2
pttbbs-544b6475f029f5396bea9ebca0994111e74d1200.tar.lz
pttbbs-544b6475f029f5396bea9ebca0994111e74d1200.tar.xz
pttbbs-544b6475f029f5396bea9ebca0994111e74d1200.tar.zst
pttbbs-544b6475f029f5396bea9ebca0994111e74d1200.zip
Chess functions:
* chc machine readable log - http://www.elephantbase.net/protocol/cchess_pgn.htm - http://www.elephantbase.net/protocol/cchess_move.htm * chc and gomoku replay work * key binding 'z' in pmore() for chess replay * avoid crash when watching (the watchee's mateid is empty) git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@3105 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'mbbsd/chc.c')
-rw-r--r--mbbsd/chc.c160
1 files changed, 156 insertions, 4 deletions
diff --git a/mbbsd/chc.c b/mbbsd/chc.c
index 0dbe3514..37831aa1 100644
--- a/mbbsd/chc.c
+++ b/mbbsd/chc.c
@@ -260,7 +260,7 @@ chc_drawline(const ChessInfo* info, int line)
/*
* Start of the log function.
*/
-void
+static void
chc_log_step(FILE* fp, board_t board, const drc_t *step)
{
char buf[80];
@@ -270,6 +270,22 @@ chc_log_step(FILE* fp, board_t board, const drc_t *step)
fputc('\n', fp);
}
+static void
+chc_log_machine_step(FILE* fp, board_t board, const drc_t *step)
+{
+ const static char chess_char[8] = {
+ 0, 'K', 'A', 'B', 'R', 'N', 'C', 'P'
+ };
+ /* We have black at bottom in rc_t but the standard is
+ * the red side at bottom, so that a rotation is needed. */
+ fprintf(fp, "%c%c%d%c%c%d ",
+ chess_char[CHE_P(board[step->from.r][step->from.c])],
+ BRD_COL - step->from.c - 1 + 'a', BRD_ROW - step->from.r - 1,
+ board[step->to.r][step->to.c] ? 'x' : '-',
+ BRD_COL - step->to.c - 1 + 'a', BRD_ROW - step->to.r - 1
+ );
+}
+
static int
#if defined(__linux__)
chc_filter(const struct dirent *dir)
@@ -337,11 +353,60 @@ chc_genlog(ChessInfo* info, FILE* fp, ChessGameResult result)
(info->myturn == RED) == (result== CHESS_RESULT_WIN) ?
"¬õ" : "¶Â");
- fputs("\n--\n\n", fp);
+ /* generate machine readable log.
+ * http://www.elephantbase.net/protocol/cchess_pgn.htm */
+ {
+ /* machine readable header */
+ time_t temp = (time_t)*clock;
+ struct tm *mytm = localtime(&temp);
+
+ fprintf(fp,
+ "\n\n<chclog>\n"
+ "[Game \"Chinese Chess\"]\n"
+ "[Date \"%d.%d.%d\"]\n"
+ "[Red \"%s\"]\n"
+ "[Black \"%s\"]\n"
+ "[Result \"%s\"]\n"
+ "[Notation \"Coord\"]\n"
+ "[FEN \"rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/9/1C5C1/9/RN2K2NR"
+ " r - - 0 1\"]\n",
+ mytm->tm_year + 1900, mytm->tm_mon + 1, mytm->tm_mday,
+ info->myturn == RED ? info->user1.userid : info->user2.userid,
+ info->myturn == RED ? info->user2.userid : info->user1.userid,
+ result == CHESS_RESULT_TIE ? "0.5-0.5" :
+ (info->myturn == RED) == (result== CHESS_RESULT_WIN) ?
+ "1-0" : "0-1"
+ );
+ }
+ chc_init_board(board);
+ for (i = 0; i < nStep - 1; i += 2) {
+ const drc_t *move = (const drc_t*) ChessHistoryRetrieve(info, i);
+ fprintf(fp, "%2d. ", i / 2 + 1);
+ if (move->type == CHESS_STEP_NORMAL) {
+ chc_log_machine_step(fp, board, move);
+ chc_movechess(board, move);
+ }
+
+ fputs(" ", fp);
- /* TODO: generate machine readable log.
- * e.g. http://www.nchess.com/ccff.html */
+ move = (const drc_t*) ChessHistoryRetrieve(info, i + 1);
+ if (move->type == CHESS_STEP_NORMAL) {
+ chc_log_machine_step(fp, board, move);
+ chc_movechess(board, move);
+ }
+
+ fputc('\n', fp);
+ }
+ if (i < nStep) {
+ const drc_t *move = (const drc_t*) ChessHistoryRetrieve(info, i);
+ if (move->type == CHESS_STEP_NORMAL) {
+ fprintf(fp, "%2d. ", i / 2 + 1);
+ chc_log_machine_step(fp, board, move);
+ fputc('\n', fp);
+ }
+ }
+ fputs("</chclog>\n\n--\n\n", fp);
chc_log_poem(fp);
}
/*
@@ -599,6 +664,18 @@ chc_init_user(const userinfo_t *uinfo, ChessUser *user)
user->orig_rating = user->rating;
}
+static void
+chc_init_user_userec(const userec_t *urec, ChessUser *user)
+{
+ strlcpy(user->userid, urec->userid, sizeof(user->userid));
+ user->win = urec->chc_win;
+ user->lose = urec->chc_lose;
+ user->tie = urec->chc_tie;
+ user->rating = urec->chess_elo_rating;
+ if(user->rating == 0)
+ user->rating = 1500; /* ELO initial value */
+ user->orig_rating = user->rating;
+}
static void
chc_prepare_play(ChessInfo* info)
@@ -833,3 +910,78 @@ chc_watch(void)
{
return ChessWatchGame(&chc, CHC, "·¡ªeº~¬É¤§ª§");
}
+
+ChessInfo*
+chc_replay(FILE* fp)
+{
+ ChessInfo *info;
+ char buf[256];
+
+ info = NewChessInfo(&chc_actions, &chc_constants,
+ 0, CHESS_MODE_REPLAY);
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (strcmp("</chclog>\n", buf) == 0)
+ break;
+ if (buf[0] == '[') {
+ if (strncmp(buf + 1, "Red", 3) == 0 ||
+ strncmp(buf + 1, "Black", 5) == 0) {
+ /* /\[(Red|Black) "([a-zA-Z0-9]+)"\]/; $2 */
+ userec_t rec;
+ char *userid;
+ ChessUser *user =
+ (buf[0] == 'R' ? &info->user1 : &info->user2);
+
+ strtok(buf, "\"");
+ userid = strtok(NULL, "\"");
+ if (userid != NULL && getuser(userid, &rec))
+ chc_init_user_userec(&rec, user);
+ }
+ } else {
+ /* " 1. Ch2-e2 Nb9-c7" */
+ drc_t step = { CHESS_STEP_NORMAL };
+ const char *p = strchr(buf, '.');
+
+ if (p == NULL) continue;
+
+ ++p; /* skip '.' */
+ while(*p && isspace(*p)) ++p;
+ if (!*p) continue;
+
+ /* p -> "Ch2-e2 ...." */
+ step.from.c = p[1] - 'a';
+ step.from.r = BRD_ROW - 1 - (p[2] - '0');
+ step.to.c = p[4] - 'a';
+ step.to.r = BRD_ROW - 1 - (p[5] - '0');
+
+#define INVALID_ROW(R) ((R) < 0 || (R) >= BRD_ROW)
+#define INVALID_COL(C) ((C) < 0 || (C) >= BRD_COL)
+#define INVALID_LOC(S) (INVALID_ROW(S.r) || INVALID_COL(S.c))
+ if (INVALID_LOC(step.from) || INVALID_LOC(step.to))
+ continue;
+ ChessHistoryAppend(info, &step);
+
+ p += 6;
+ while(*p && isspace(*p)) ++p;
+ if (!*p) continue;
+
+ /* p -> "Nb9-c7\n" */
+ step.from.c = p[1] - 'a';
+ step.from.r = BRD_ROW - 1 - (p[2] - '0');
+ step.to.c = p[4] - 'a';
+ step.to.r = BRD_ROW - 1 - (p[5] - '0');
+
+ if (INVALID_LOC(step.from) || INVALID_LOC(step.to))
+ continue;
+ ChessHistoryAppend(info, &step);
+ }
+ }
+
+ info->board = malloc(sizeof(board_t));
+ info->tag = malloc(sizeof(chc_tag_data_t));
+
+ chc_init_board(info->board);
+ ((chc_tag_data_t*) info->tag)->selected = 0;
+
+ return info;
+}