2 Copyright (c) 1993 Richard V. Nash.
3 Copyright (c) 2000 Dan Papasian
4 Copyright (C) Andrew Tridgell 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 int GameNumFromParam(int p, int *p1, parameter *param)
25 if (param->type == TYPE_WORD) {
26 *p1 = player_find_part_login(param->val.word);
28 pprintf(p, "No user named \"%s\" is logged in.\n", param->val.word);
31 if (player_globals.parray[*p1].game < 0)
32 pprintf(p, "%s is not playing a game.\n", player_globals.parray[*p1].name);
33 return player_globals.parray[*p1].game;
34 } else { /* Must be an integer */
36 if (param->val.integer <= 0)
37 pprintf(p, "%d is not a valid game number.\n", param->val.integer);
38 return param->val.integer - 1;
42 static int gamesortfunc(const void *i, const void *j)
44 /* examine mode games moved to top of "games" output */
45 return (GetRating(&player_globals.parray[game_globals.garray[*(int *) i].white], game_globals.garray[*(int *) i].type) +
46 GetRating(&player_globals.parray[game_globals.garray[*(int *) i].black], game_globals.garray[*(int *) i].type) -
47 (((game_globals.garray[*(int *) i].status == GAME_EXAMINE) || (game_globals.garray[*(int *) i].status == GAME_SETUP)) ? 10000 : 0) -
48 GetRating(&player_globals.parray[game_globals.garray[*(int *) j].white], game_globals.garray[*(int *) j].type) -
49 GetRating(&player_globals.parray[game_globals.garray[*(int *) j].black], game_globals.garray[*(int *) j].type) +
50 (((game_globals.garray[*(int *) j].status == GAME_EXAMINE) || (game_globals.garray[*(int *) j].status == GAME_SETUP)) ? 10000 : 0));
54 int com_games(int p, param_list param)
64 int *sortedgames; /* for qsort */
66 totalcount = game_count();
67 if (totalcount == 0) {
68 pprintf(p, "There are no games in progress.\n");
70 sortedgames = malloc(totalcount * sizeof(int)); /* for qsort */
72 if (param[0].type == TYPE_WORD) {
73 s = param[0].val.word;
79 for (i = 0; i < game_globals.g_num; i++) {
80 if ((game_globals.garray[i].status != GAME_ACTIVE) && (game_globals.garray[i].status != GAME_EXAMINE) && (game_globals.garray[i].status != GAME_SETUP))
82 if ((selected) && (selected != i + 1))
83 continue; /* not selected game number */
84 wp = game_globals.garray[i].white;
85 bp = game_globals.garray[i].black;
86 if ((!selected) && s && strncasecmp(s, game_globals.garray[i].white_name, slen) &&
87 strncasecmp(s, game_globals.garray[i].black_name, slen))
88 continue; /* player names did not match */
89 sortedgames[count++] = i;
92 pprintf(p, "No matching games were found (of %d in progress).\n", totalcount);
94 qsort(sortedgames, count, sizeof(int), gamesortfunc);
96 for (j = 0; j < count; j++) {
98 wp = game_globals.garray[i].white;
99 bp = game_globals.garray[i].black;
100 board_calc_strength(&game_globals.garray[i].game_state, &ws, &bs);
101 if ((game_globals.garray[i].status != GAME_EXAMINE) && (game_globals.garray[i].status != GAME_SETUP)) {
102 pprintf_noformat(p, "%3d %4s %-11.11s %4s %-10.10s [%c%c%c%3d %3d] ",
104 ratstrii(GetRating(&player_globals.parray[wp],game_globals.garray[i].type), wp),
105 player_globals.parray[wp].name,
106 ratstrii(GetRating(&player_globals.parray[bp],game_globals.garray[i].type), bp),
107 player_globals.parray[bp].name,
108 (game_globals.garray[i].private) ? 'p' : ' ',
109 *bstr[game_globals.garray[i].type],
110 *rstr[game_globals.garray[i].rated],
111 game_globals.garray[i].wInitTime / 600,
112 game_globals.garray[i].wIncrement / 10);
114 pprintf_noformat(p, "%6s -",
115 tenth_str((game_globals.garray[i].wTime > 0 ? game_globals.garray[i].wTime : 0), 0));
116 pprintf_noformat(p, "%6s (%2d-%2d) %c: %2d\n",
117 tenth_str((game_globals.garray[i].bTime > 0 ? game_globals.garray[i].bTime : 0), 0),
119 (game_globals.garray[i].game_state.onMove == WHITE) ? 'W' : 'B',
120 game_globals.garray[i].game_state.moveNum);
122 pprintf_noformat(p, "%3d (%s %4d %-11.11s %4d %-10.10s) [%c%c%c%3d %3d] ",
124 (game_globals.garray[i].status == GAME_EXAMINE) ? "Exam." : "Setup",
125 game_globals.garray[i].white_rating,
126 game_globals.garray[i].white_name,
127 game_globals.garray[i].black_rating,
128 game_globals.garray[i].black_name,
129 (game_globals.garray[i].private) ? 'p' : ' ',
130 *bstr[game_globals.garray[i].type],
131 *rstr[game_globals.garray[i].rated],
132 game_globals.garray[i].wInitTime / 600,
133 game_globals.garray[i].wIncrement / 10);
134 pprintf_noformat(p, "%c: %2d\n",
135 (game_globals.garray[i].game_state.onMove == WHITE) ? 'W' : 'B',
136 game_globals.garray[i].game_state.moveNum);
139 if (count < totalcount)
140 pprintf(p, "\n %d game%s displayed (of %d in progress).\n", count,
141 (count == 1) ? "" : "s", totalcount);
143 pprintf(p, "\n %d game%s displayed.\n", totalcount, (totalcount == 1) ? "" : "s");
150 static int do_observe(int p, int obgame)
152 struct player *pp = &player_globals.parray[p];
153 if ((game_globals.garray[obgame].private) && (pp->adminLevel < ADMIN_ADMIN)) {
154 pprintf(p, "Sorry, game %d is a private game.\n", obgame + 1);
157 if ((game_globals.garray[obgame].white == p) || (game_globals.garray[obgame].black == p)) {
158 if ((game_globals.garray[obgame].status != GAME_EXAMINE) || (game_globals.garray[obgame].status != GAME_SETUP)) {
159 pprintf(p, "You cannot observe a game that you are playing.\n");
163 if (player_is_observe(p, obgame)) {
164 pprintf(p, "Removing game %d from observation list.\n", obgame + 1);
165 player_remove_observe(p, obgame);
167 if (!player_add_observe(p, obgame)) {
168 pprintf(p, "You are now observing game %d.\n", obgame + 1);
169 send_board_to(obgame, p);
171 pprintf(p, "You are already observing the maximum number of games.\n");
177 void unobserveAll(int p)
179 struct player *pp = &player_globals.parray[p];
182 for (i = 0; i < pp->num_observe; i++) {
183 pprintf(p, "Removing game %d from observation list.\n",
184 pp->observe_list[i] + 1);
190 int com_unobserve(int p, param_list param)
194 if (param[0].type == TYPE_NULL) {
198 gNum = GameNumFromParam(p, &p1, ¶m[0]);
201 if (!player_is_observe(p, gNum)) {
202 pprintf(p, "You are not observing game %d.\n", gNum);
204 player_remove_observe(p, gNum);
205 pprintf(p, "Removing game %d from observation list.\n", gNum + 1);
210 int com_observe(int p, param_list param)
212 struct player *pp = &player_globals.parray[p];
216 if (param[0].type == TYPE_NULL)
217 return COM_BADPARAMETERS;
218 if ((pp->game >=0) &&(game_globals.garray[pp->game].status == GAME_EXAMINE)) {
219 pprintf(p, "You are still examining a game.\n");
222 if ((pp->game >=0) &&(game_globals.garray[pp->game].status == GAME_SETUP)) {
223 pprintf(p, "You are still setting up a position.\n");
226 if (param[0].type == TYPE_NULL) {
230 obgame = GameNumFromParam(p, &p1, ¶m[0]);
234 if ((obgame >= game_globals.g_num) || ((game_globals.garray[obgame].status != GAME_ACTIVE) &&
235 (game_globals.garray[obgame].status != GAME_EXAMINE) &&
236 (game_globals.garray[obgame].status != GAME_SETUP))) {
237 pprintf(p, "There is no such game.\n");
240 if ((p1 >= 0) && (player_globals.parray[p1].simul_info != NULL) && (player_globals.parray[p1].simul_info->numBoards)) {
241 for (i = 0; i < player_globals.parray[p1].simul_info->numBoards; i++)
242 if (player_globals.parray[p1].simul_info->boards[i] >= 0)
243 do_observe(p, player_globals.parray[p1].simul_info->boards[i]);
245 do_observe(p, obgame);
249 int com_allobservers(int p, param_list param)
251 struct player *pp = &player_globals.parray[p];
258 if (param[0].type == TYPE_NULL) {
261 obgame = GameNumFromParam(p, &p1, ¶m[0]);
267 end = game_globals.g_num;
268 } else if ((obgame >= game_globals.g_num) || ((obgame < game_globals.g_num)
269 && ((game_globals.garray[obgame].status != GAME_ACTIVE)
270 && (game_globals.garray[obgame].status != GAME_EXAMINE)
271 && (game_globals.garray[obgame].status != GAME_SETUP)))) {
272 pprintf(p, "There is no such game.\n");
279 /* list games being played */
281 for (g = start; g < end; g++) {
282 if ((game_globals.garray[g].status == GAME_ACTIVE) &&
283 ((pp->adminLevel > 0) || (game_globals.garray[g].private == 0))) {
284 for (first = 1, p1 = 0; p1 < player_globals.p_num; p1++) {
285 if ((player_globals.parray[p1].status != PLAYER_EMPTY) && (player_is_observe(p1, g))) {
287 pprintf(p, "Observing %2d [%s vs. %s]:",
289 player_globals.parray[game_globals.garray[g].white].name,
290 player_globals.parray[game_globals.garray[g].black].name);
293 pprintf(p, " %s%s", (player_globals.parray[p1].game >=0) ? "#" : "", player_globals.parray[p1].name);
301 /* list games being examined last */
303 for (g = start; g < end; g++) {
304 if (((game_globals.garray[g].status == GAME_EXAMINE) || (game_globals.garray[g].status == GAME_SETUP)) &&
305 ((pp->adminLevel > 0) || (game_globals.garray[g].private == 0))) {
306 for (first = 1, p1 = 0; p1 < player_globals.p_num; p1++) {
307 if ((player_globals.parray[p1].status != PLAYER_EMPTY) && (player_is_observe(p1, g) ||
308 (player_globals.parray[p1].game == g))) {
310 if (strcmp(game_globals.garray[g].white_name, game_globals.garray[g].black_name)) {
311 pprintf(p, "Examining %2d [%s vs %s]:", g + 1,
312 game_globals.garray[g].white_name, game_globals.garray[g].black_name);
314 pprintf(p, "Examining %2d (scratch):", g + 1);
318 pprintf(p, " %s%s", (player_globals.parray[p1].game == g) ? "#" : "", player_globals.parray[p1].name);
328 int com_unexamine(int p, param_list param)
330 struct player *pp = &player_globals.parray[p];
333 if ((pp->game <0) || ((game_globals.garray[pp->game].status != GAME_EXAMINE) && (game_globals.garray[pp->game].status != GAME_SETUP))) {
334 pprintf(p, "You are not examining any games.\n");
339 for (p1 = 0; p1 < player_globals.p_num; p1++) {
340 if (player_globals.parray[p1].status != PLAYER_PROMPT)
342 if ((player_globals.parray[p1].game == g) &&(p != p1)) {
343 /* ok - there are other examiners to take over the game */
346 if ((player_is_observe(p1, g)) || (player_globals.parray[p1].game == g)) {
347 pprintf(p1, "%s stopped examining game %d.\n", pp->name, g + 1);
351 for (p1 = 0; p1 < player_globals.p_num; p1++) {
352 if (player_globals.parray[p1].status != PLAYER_PROMPT)
354 if (player_is_observe(p1, g)) {
355 pprintf(p1, "There are no examiners.\n");
356 pcommand(p1, "unobserve %d", g + 1);
361 pprintf(p, "You are no longer examining game %d.\n", g + 1);
366 int com_mexamine(int p, param_list param)
368 struct player *pp = &player_globals.parray[p];
372 ((game_globals.garray[pp->game].status != GAME_EXAMINE) &&
373 (game_globals.garray[pp->game].status != GAME_SETUP))) {
374 pprintf(p, "You are not examining any games.\n");
377 p1 = player_find_part_login(param[0].val.word);
379 pprintf(p, "No user named \"%s\" is logged in.\n", param[0].val.word);
383 if (!player_is_observe(p1, g)) {
384 pprintf(p, "%s must observe the game you are analysing.\n", player_globals.parray[p1].name);
387 if (player_globals.parray[p1].game >=0) {
388 pprintf(p, "%s is already analysing the game.\n", player_globals.parray[p1].name);
391 /* if we get here - let's make him examiner of the game */
392 unobserveAll(p1); /* fix for Xboard */
393 decline_withdraw_offers(p1, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
394 decline_withdraw_offers(p1, -1, PEND_SIMUL,DO_WITHDRAW);
396 player_globals.parray[p1].game = g; /* yep - it really is that easy :-) */
397 pprintf(p1, "You are now examiner of game %d.\n", g + 1);
398 send_board_to(g, p1); /* pos not changed - but fixes Xboard */
399 for (p2 = 0; p2 < player_globals.p_num; p2++) {
400 if (player_globals.parray[p2].status != PLAYER_PROMPT)
404 if ((player_is_observe(p2, g)) || (player_globals.parray[p2].game == g)) {
405 pprintf_prompt(p2, "%s is now examiner of game %d.\n", player_globals.parray[p1].name, g + 1);
409 if (CheckPFlag(p2, PFLAG_OPEN)) /* was open */
410 announce_notavail(p2);
414 int com_moves(int p, param_list param)
416 struct player *pp = &player_globals.parray[p];
420 if (param[0].type == TYPE_NULL) {
423 } else if (pp->num_observe) {
424 for (g = 0; g < pp->num_observe; g++) {
425 pprintf(p, "%s\n", movesToString(pp->observe_list[g], 0));
429 pprintf(p, "You are neither playing, observing nor examining a game.\n");
433 g = GameNumFromParam(p, &p1, ¶m[0]);
437 if ((g < 0) || (g >= game_globals.g_num) || ((game_globals.garray[g].status != GAME_ACTIVE) &&
438 (game_globals.garray[g].status != GAME_EXAMINE) &&
439 (game_globals.garray[g].status != GAME_SETUP))) {
440 pprintf(p, "There is no such game.\n");
443 if ((game_globals.garray[g].white != p) && (game_globals.garray[g].black != p) && (game_globals.garray[g].private) && (pp->adminLevel < ADMIN_ADMIN)) {
444 pprintf(p, "Sorry, that is a private game.\n");
447 pprintf(p, "%s\n", movesToString(g, 0)); /* pgn may break interfaces? */
451 int com_mailmoves(int p, param_list param)
453 struct player *pp = &player_globals.parray[p];
458 if (!CheckPFlag(p, PFLAG_REG)) {
459 pprintf (p,"Unregistered players cannot use mailmoves.\n");
463 if (param[0].type == TYPE_NULL) {
467 pprintf(p, "You are neither playing, observing nor examining a game.\n");
471 g = GameNumFromParam(p, &p1, ¶m[0]);
475 if ((g < 0) || (g >= game_globals.g_num) || ((game_globals.garray[g].status != GAME_ACTIVE) && (game_globals.garray[g].status != GAME_EXAMINE))) {
476 pprintf(p, "There is no such game.\n");
479 if ((game_globals.garray[g].white != p) && (game_globals.garray[g].black != p) && (game_globals.garray[g].private) && (pp->adminLevel < ADMIN_ADMIN)) {
480 pprintf(p, "Sorry, that is a private game.\n");
483 sprintf(subj, "FICS game report %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
484 if (mail_string_to_user(p, subj,
485 movesToString(g, CheckPFlag(p, PFLAG_PGN)))) {
486 pprintf(p, "Moves NOT mailed, perhaps your address is incorrect.\n");
488 pprintf(p, "Moves mailed.\n");
493 static int old_mail_moves(int p,int mail, param_list param)
498 char fname[MAX_FILENAME_SIZE];
502 if (mail && !CheckPFlag(p, PFLAG_REG)) {
503 pprintf (p,"Unregistered players cannot use mailoldmoves.\n");
507 if (param[0].type == TYPE_WORD) {
508 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
515 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR,
516 player_globals.parray[p1].login[0], player_globals.parray[p1].login, STATS_GAMES);
517 fp = fopen_s(fname, "r"); /* old moves now looks in history to save mem - DAV */
520 pprintf (p,"There is no old game for %s.\n", player_globals.parray[p1].name);
527 fgets(tmp, 1024, fp);
528 sscanf(ptmp, "%d", &count);
529 fclose(fp); /* find the last game played in history */
531 pprintf (p,"Last game for %s was history game %d.\n",player_globals.parray[p1].name,count);
534 pcommand (p,"mailstored %s %d",player_globals.parray[p1].name,count);
536 pcommand (p,"smoves %s %d",player_globals.parray[p1].name,count);
544 int com_oldmoves(int p, param_list param)
546 return old_mail_moves(p , 0, param);
549 int com_mailoldmoves(int p, param_list param)
551 return old_mail_moves(p , 1, param);
554 void ExamineScratch(int p, param_list param,int setup)
556 struct player *pp = &player_globals.parray[p];
557 char category[100], board[100], parsebuf[100];
565 if ((param[0].val.string != pp->name) &&
566 (param[1].type == TYPE_WORD)) {
567 strcpy(category, param[0].val.string);
568 strcpy(board, param[1].val.string);
569 } else if (param[1].type != TYPE_NULL) {
571 val = param[1].val.string;
573 while (!confused && (sscanf(val, " %99s", parsebuf) == 1)) {
574 val = eatword(eatwhite(val));
575 if ((category[0] != '\0') && (board[0] == '\0'))
576 strcpy(board, parsebuf);
577 else if (isdigit(*parsebuf)) {
578 pprintf(p, "You can't specify time controls.\n");
580 } else if (category[0] == '\0')
581 strcpy(category, parsebuf);
586 pprintf(p, "Can't interpret %s in match command.\n", parsebuf);
592 if (category[0] && !board[0]) {
593 pprintf(p, "You must specify a board and a category.\n");
601 decline_withdraw_offers(p, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
602 decline_withdraw_offers(p, -1, PEND_SIMUL,DO_WITHDRAW);
604 game_globals.garray[g].wInitTime = game_globals.garray[g].wIncrement = 0;
605 game_globals.garray[g].bInitTime = game_globals.garray[g].bIncrement = 0;
606 game_globals.garray[g].timeOfStart = tenth_secs();
607 game_globals.garray[g].wTime = game_globals.garray[g].bTime = 0;
608 game_globals.garray[g].rated = 0;
609 game_globals.garray[g].clockStopped = 0;
610 game_globals.garray[g].type = TYPE_UNTIMED;
611 game_globals.garray[g].white = game_globals.garray[g].black = p;
612 game_globals.garray[g].startTime = tenth_secs();
613 game_globals.garray[g].lastMoveTime = game_globals.garray[g].startTime;
614 game_globals.garray[g].lastDecTime = game_globals.garray[g].startTime;
615 game_globals.garray[g].totalHalfMoves = 0;
617 pp->side = WHITE; /* oh well... */
622 pprintf(p, "Starting a game in examine (scratch) mode.\n");
624 pprintf(p, "Starting a game in examine (setup) mode.\n");
627 pprintf(p, "Loading from catagory: %s, board: %s.\n", category, board);
631 board_clear(&game_globals.garray[g].game_state);
632 game_globals.garray[g].status = GAME_SETUP;
634 game_globals.garray[g].status = GAME_EXAMINE;
635 if (board_init(g,&game_globals.garray[g].game_state, category, board)) {
636 pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
637 d_printf( "CHESSD: PROBLEM LOADING BOARD. Examine Aborted.\n");
644 game_globals.garray[g].game_state.gameNum = g;
645 strcpy(game_globals.garray[g].white_name, pp->name);
646 strcpy(game_globals.garray[g].black_name, pp->name);
647 game_globals.garray[g].white_rating = game_globals.garray[g].black_rating = pp->s_stats.rating;
650 if (CheckPFlag(p, PFLAG_OPEN)) /*was open */
651 announce_notavail(p);
654 static int ExamineStored(FILE * fp, int p, char type)
656 struct player *pp = &player_globals.parray[p];
658 char category[100], board[100];
663 decline_withdraw_offers(p, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
664 decline_withdraw_offers(p, -1, PEND_SIMUL,DO_WITHDRAW);
667 gg = &game_globals.garray[g];
670 if (board_init(g,&gg->game_state, category, board)) {
671 pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
672 d_printf( "CHESSD: PROBLEM LOADING BOARD %s %s. Examine Aborted.\n",
678 gg->status = GAME_EXAMINE;
680 if (type == 'w' || type == 'n') {
681 if (ReadGameAttrs_exam(fp, g) < 0) {
682 pprintf(p, "Either this is an old wild/nonstandard game or the gamefile is corrupt.\n");
686 } else if (ReadGameAttrs(fp, g) < 0) {
687 pprintf(p, "Gamefile is corrupt; please notify an admin.\n");
692 gg->totalHalfMoves = gg->numHalfMoves;
693 gg->numHalfMoves = 0;
694 gg->revertHalfMove = 0;
697 gg->game_state.gameNum = g;
699 gg->startTime = tenth_secs();
700 gg->lastMoveTime = gg->startTime;
701 gg->lastDecTime = gg->startTime;
703 pp->side = WHITE; /* oh well... */
707 if (CheckPFlag(p, PFLAG_OPEN)) /* was open */
708 announce_notavail(p);
713 static void ExamineAdjourned(int p, int p1, int p2)
716 char *p1Login, *p2Login;
719 p1Login = player_globals.parray[p1].login;
720 p2Login = player_globals.parray[p2].login;
722 fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p1Login, p1Login, p2Login);
723 if (!fp) fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p2Login, p1Login, p2Login);
724 if (!fp) fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p2Login, p2Login, p1Login);
725 if (!fp) fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p1Login, p2Login, p1Login);
727 pprintf(p, "No stored game between \"%s\" and \"%s\".\n",
728 player_globals.parray[p1].name, player_globals.parray[p2].name);
731 /* Assume old wild games are of type blitz - adjudicators should be
733 g = ExamineStored(fp, p,'b');
737 if (game_globals.garray[g].white_name[0] == '\0')
738 strcpy(game_globals.garray[g].white_name, p1Login);
739 if (game_globals.garray[g].black_name[0] == '\0')
740 strcpy(game_globals.garray[g].black_name, p2Login);
744 /* type is now returned because prior to V1.7.1 loading a wild game for
745 examining was impossible since the initial position was not saved.
746 Only types blitz,standard,lightning and untimed may be loaded for
747 examining if the gamefile version is less than 4 */
749 static char *FindHistory(int p, int p1, int game,char* type)
752 static char fileName[MAX_FILENAME_SIZE];
757 sprintf(fileName, "%s/player_data/%c/%s.%s", STATS_DIR,
758 player_globals.parray[p1].login[0], player_globals.parray[p1].login, STATS_GAMES);
759 fpHist = fopen_s(fileName, "r");
760 if (fpHist == NULL) {
761 pprintf(p, "No games in history for %s.\n", player_globals.parray[p1].name);
765 fscanf(fpHist, "%d %*c %*d %*c %*d %*s %s %*d %*d %*d %*d %*s %*s %ld",
766 &index, typestr, &when);
767 } while (!feof(fpHist) && index != game);
770 pprintf(p, "There is no history game %d for %s.\n", game, player_globals.parray[p1].name);
776 if (typestr[0] != 'p')
781 sprintf(fileName, "%s/%ld/%ld", HISTORY_DIR, when % 100, when);
785 /* I want to know how game ended/ECO code */
787 static char *FindHistory2(int p, int p1,int game, char* Eco,char* End)
790 static char fileName[MAX_FILENAME_SIZE];
794 sprintf(fileName, "%s/player_data/%c/%s.%s", STATS_DIR,
795 player_globals.parray[p1].login[0], player_globals.parray[p1].login, STATS_GAMES);
796 fpHist = fopen_s(fileName, "r");
797 if (fpHist == NULL) {
798 pprintf(p, "No games in history for %s.\n", player_globals.parray[p1].name);
802 fscanf(fpHist, "%d %*c %*d %*c %*d %*s %*s %*d %*d %*d %*d %s %s %ld",
803 &index, Eco, End, &when);
804 } while (!feof(fpHist) && index != game);
807 pprintf(p, "There is no history game %d for %s.\n", game, player_globals.parray[p1].name);
813 sprintf(fileName, "%s/%ld/%ld", HISTORY_DIR, when % 100, when);
817 int com_wname(int p, param_list param)
819 struct player *pp = &player_globals.parray[p];
825 !((game_globals.garray[g].status != GAME_EXAMINE) || (game_globals.garray[g].status != GAME_SETUP)))) {
826 pprintf (p, "You are not examining or setting up a game.\n");
830 if (param[0].type == TYPE_NULL)
831 strcpy (game_globals.garray[g].white_name,pp->name);
834 if (strlen (param[0].val.word) > MAX_LOGIN_NAME - 1) {
835 pprintf (p,"The maximum length of a name is %d characters.\n",MAX_LOGIN_NAME - 1);
838 strcpy (game_globals.garray[g].white_name,param[0].val.word);
845 int com_bname(int p, param_list param)
847 struct player *pp = &player_globals.parray[p];
853 !((game_globals.garray[g].status != GAME_EXAMINE) || (game_globals.garray[g].status != GAME_SETUP)))) {
854 pprintf (p, "You are not examining or setting up a game.\n");
858 if (param[0].type == TYPE_NULL)
859 strcpy (game_globals.garray[g].black_name,pp->name);
862 if (strlen (param[0].val.word) > MAX_LOGIN_NAME - 1) {
863 pprintf (p,"The maximum length of a name is %d characters.\n",MAX_LOGIN_NAME - 1);
866 strcpy (game_globals.garray[g].black_name,param[0].val.word);
873 static void ExamineHistory(int p, int p1, int game)
878 fileName = FindHistory(p, p1, game,&type);
880 FILE *fpGame = fopen_p("%s", "r", fileName);
881 if (fpGame == NULL) {
882 pprintf(p, "History game %d not available for %s.\n",
883 game, player_globals.parray[p1].name);
885 ExamineStored(fpGame, p,type);
891 static void ExamineJournal(int p,int p1,char slot)
893 struct player *pp = &player_globals.parray[p];
894 char* name_from = player_globals.parray[p1].login;
898 if (CheckPFlag(p1, PFLAG_JPRIVATE) && (p != p1)
899 && (pp->adminLevel < ADMIN_ADMIN)) {
900 pprintf (p,"Sorry, this journal is private.\n");
904 if ((slot - 'a' + 1) > MAX_JOURNAL &&
905 !check_admin(p1, ADMIN_ADMIN) &&
906 !titled_player(p,player_globals.parray[p1].login)) {
907 pprintf(p,"%s's maximum journal entry is %c\n",
908 player_globals.parray[p1].name,
909 toupper((char)(MAX_JOURNAL + 'A' - 1)));
913 fpGame = fopen_p("%s/%c/%s.%c", "r", JOURNAL_DIR, name_from[0],name_from,slot);
914 if (fpGame == NULL) {
915 pprintf(p, "Journal entry %c is not available for %s.\n", toupper (slot),
916 player_globals.parray[p1].name);
919 asprintf(&fname, "%s/player_data/%c/%s.journal",
920 STATS_DIR, name_from[0],name_from);
921 slot = toupper(slot);
923 if ((type = get_journalgame_type (p,fname,slot)) == '\0') {
924 pprintf(p, "Journal entry %c is not available for %s or is corrupt.\n",
925 slot, player_globals.parray[p1].name);
927 ExamineStored(fpGame, p,type);
935 int com_examine(int p, param_list param)
937 struct player *pp = &player_globals.parray[p];
938 int p1, p2 = p, p1conn, p2conn = 1;
940 char fname[MAX_FILENAME_SIZE];
943 if ((game_globals.garray[pp->game].status == GAME_EXAMINE) ||
944 (game_globals.garray[pp->game].status == GAME_SETUP))
945 pprintf(p, "You are already examining a game.\n");
947 pprintf(p, "You are playing a game.\n");
948 } else if (param[0].type == TYPE_NULL) {
949 ExamineScratch(p, param, 0);
950 } else if (param[0].type != TYPE_NULL) {
951 if ((param[1].type == TYPE_NULL) && (!strcmp(param[0].val.word,"setup"))) {
952 ExamineScratch(p, param, 1);
954 } else if (param[1].type == TYPE_WORD) {
955 sprintf(fname, "%s/%s/%s", BOARD_DIR, param[0].val.word, param[1].val.word);
956 if (file_exists(fname)) {
957 ExamineScratch(p, param, 0);
961 if (!FindPlayer(p, param[0].val.word, &p1, &p1conn))
964 if (param[1].type == TYPE_INT)
965 ExamineHistory(p, p1, param[1].val.integer);
967 if (param[1].type == TYPE_WORD) {
969 /* Lets check the journal */
970 wincstring = param[1].val.word;
971 if ((strlen(wincstring) == 1) && (isalpha(wincstring[0]))) {
972 ExamineJournal(p,p1,wincstring[0]);
977 if (!FindPlayer(p, param[1].val.word, &p2, &p2conn)) {
984 ExamineAdjourned(p, p1, p2);
994 int com_stored(int p, param_list param)
1001 char dname[MAX_FILENAME_SIZE];
1003 if (param[0].type == TYPE_WORD) {
1004 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1011 sprintf(dname, "%s/%c", ADJOURNED_DIR, player_globals.parray[p1].login[0]);
1012 dirp = opendir(dname);
1014 pprintf(p, "Player %s has no games stored.\n", player_globals.parray[p1].name);
1019 pprintf(p, "Stored games for %s:\n", player_globals.parray[p1].name);
1020 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
1021 if (file_has_pname(dp->d_name, player_globals.parray[p1].login)) {
1022 pprintf(p, " %s vs. %s\n", file_wplayer(dp->d_name), file_bplayer(dp->d_name));
1028 pprintf (p,"%d stored game%sfound.\n",count,(count == 1 ? " " : "s "));
1034 static void stored_mail_moves(int p, int mail, param_list param)
1036 struct player *pp = &player_globals.parray[p];
1037 int wp, wconnected, bp, bconnected, gotit = 0;
1039 char type; /* dummy */
1040 char* wincstring = NULL;
1041 char* name_from = NULL;
1042 char* fileName = NULL;
1043 char fileName2[MAX_FILENAME_SIZE];
1046 if (mail && !CheckPFlag(p, PFLAG_REG)) {
1047 pprintf (p,"Unregistered players cannot use mailstored.\n");
1051 if (!FindPlayer(p, param[0].val.word, &wp, &wconnected))
1054 if (param[1].type == TYPE_INT) { /* look for a game from history */
1055 fileName = FindHistory(p, wp, param[1].val.integer,&type);
1056 if (fileName != NULL) {
1057 fpGame = fopen_s(fileName, "r");
1058 if (fpGame == NULL) {
1059 pprintf(p, "History game %d not available for %s.\n", param[1].val.integer, player_globals.parray[wp].name);
1062 if (ReadGameAttrs(fpGame, g) < 0)
1063 pprintf(p, "Gamefile is corrupt; please notify an admin.\n");
1069 } else { /* Let's test for journal */
1070 name_from = param[0].val.word;
1071 wincstring = param[1].val.word;
1072 if ((strlen(wincstring) == 1) && (isalpha(wincstring[0]))) {
1073 if (CheckPFlag(wp, PFLAG_JPRIVATE)
1074 && (pp->adminLevel < ADMIN_ADMIN) && (p != wp)) {
1075 pprintf (p,"Sorry, the journal from which you are trying to fetch is private.\n");
1077 if (((wincstring[0] - 'a' + 1) > MAX_JOURNAL) && (player_globals.parray[wp].adminLevel < ADMIN_ADMIN) && (!titled_player(p,player_globals.parray[wp].login))) {
1078 pprintf (p,"%s's maximum journal entry is %c\n",player_globals.parray[wp].name,toupper((char)(MAX_JOURNAL + 'A' - 1)));
1080 sprintf(fileName2, "%s/%c/%s.%c", JOURNAL_DIR, name_from[0],name_from,wincstring[0]);
1081 fpGame = fopen_s(fileName2, "r");
1082 if (fpGame == NULL) {
1083 pprintf(p, "Journal entry %c is not available for %s.\n", toupper(wincstring[0]),
1084 player_globals.parray[wp].name);
1087 if (ReadGameAttrs(fpGame, g) < 0)
1088 pprintf(p, "Journal entry is corrupt; please notify an admin.\n");
1097 /* look for a stored game between the players */
1099 if (FindPlayer(p, param[1].val.word, &bp, &bconnected)) {
1101 if (game_read(g, wp, bp) >= 0) { /* look for a game white-black, */
1103 } else if (game_read(g, bp, wp) >= 0) { /* or black-white */
1106 pprintf(p, "There is no stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
1114 if (strcasecmp(pp->name, game_globals.garray[g].white_name) && strcasecmp(player_globals.parray[p]
1115 .name, game_globals.garray[g].black_name) && game_globals.garray[g].private && (pp->adminLevel < ADMIN_ADMIN)) {
1116 pprintf(p, "Sorry, that is a private game.\n");
1118 if (mail == 1) { /*Do mailstored */
1120 if (param[1].type == TYPE_INT)
1121 sprintf(subj, "FICS history game: %s %d", player_globals.parray[wp].name, param[1].val.integer);
1123 if ((strlen(wincstring) == 1) && (isalpha(wincstring[0]))) {
1124 sprintf(subj, "FICS journal game %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
1126 sprintf(subj, "FICS adjourned game %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
1128 if (mail_string_to_user(p, subj,
1129 movesToString(g, CheckPFlag(p, PFLAG_PGN))))
1130 pprintf(p, "Moves NOT mailed, perhaps your address is incorrect.\n");
1132 pprintf(p, "Moves mailed.\n");
1134 pprintf(p, "%s\n", movesToString(g, 0));
1144 /* Tidied up a bit but still messy */
1146 int com_mailstored(int p, param_list param)
1148 stored_mail_moves(p, 1, param);
1152 int com_smoves(int p, param_list param)
1154 stored_mail_moves(p, 0, param);
1158 int com_sposition(int p, param_list param)
1160 struct player *pp = &player_globals.parray[p];
1161 int wp, wconnected, bp, bconnected, confused = 0;
1164 if (!FindPlayer(p, param[0].val.word, &wp, &wconnected))
1166 if (!FindPlayer(p, param[1].val.word, &bp, &bconnected)) {
1173 if (game_read(g, wp, bp) < 0) { /* if no game white-black, */
1174 if (game_read(g, bp, wp) < 0) { /* look for black-white */
1176 pprintf(p, "There is no stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
1183 wconnected = bconnected;
1188 if ((wp != p) && (bp != p) && (game_globals.garray[g].private) && (pp->adminLevel < ADMIN_ADMIN)) {
1189 pprintf(p, "Sorry, that is a private game.\n");
1191 game_globals.garray[g].white = wp;
1192 game_globals.garray[g].black = bp;
1193 game_globals.garray[g].startTime = tenth_secs();
1194 game_globals.garray[g].lastMoveTime = game_globals.garray[g].startTime;
1195 game_globals.garray[g].lastDecTime = game_globals.garray[g].startTime;
1196 pprintf(p, "Position of stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
1197 send_board_to(g, p);
1208 int com_forward(int p, param_list param)
1210 struct player *pp = &player_globals.parray[p];
1216 if (!((pp->game >=0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE) || (game_globals.garray[pp->game].status == GAME_SETUP)))) {
1217 pprintf(p, "You are not examining any games.\n");
1220 if (game_globals.garray[pp->game].status == GAME_SETUP) {
1221 pprintf (p,"You can't move forward yet, the position is still being set up.\n");
1225 if (!strcmp(game_globals.garray[g].white_name, game_globals.garray[g].black_name)) {
1226 pprintf(p, "You cannot go forward; no moves are stored.\n");
1229 if (param[0].type == TYPE_INT) {
1230 nHalfMoves = param[0].val.integer;
1232 if (game_globals.garray[g].numHalfMoves > game_globals.garray[g].revertHalfMove) {
1233 pprintf(p, "Game %u: No more moves.\n", g);
1236 if (game_globals.garray[g].numHalfMoves < game_globals.garray[g].totalHalfMoves) {
1237 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1238 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1240 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1241 pprintf(p1, "Game %u: %s goes forward %d move%s.\n",
1243 pp->name, nHalfMoves, (nHalfMoves == 1) ? "" : "s");
1247 for (i = 0; i < nHalfMoves; i++) {
1248 if (game_globals.garray[g].numHalfMoves < game_globals.garray[g].totalHalfMoves) {
1249 execute_move(&game_globals.garray[g].game_state, &game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves], 1);
1250 if (game_globals.garray[g].numHalfMoves + 1 > game_globals.garray[g].examMoveListSize) {
1251 game_globals.garray[g].examMoveListSize += 20; /* Allocate 20 moves at a
1253 game_globals.garray[g].examMoveList = (struct move_t *) realloc(game_globals.garray[g].examMoveList, sizeof(struct move_t) * game_globals.garray[g].examMoveListSize);
1255 game_globals.garray[g].examMoveList[game_globals.garray[g].numHalfMoves] = game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves];
1256 game_globals.garray[g].revertHalfMove++;
1257 game_globals.garray[g].numHalfMoves++;
1259 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1260 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1262 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1263 pprintf(p1, "Game %u: End of game.\n", g);
1269 /* roll back time */
1270 if (game_globals.garray[g].game_state.onMove == WHITE) {
1271 game_globals.garray[g].wTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1273 game_globals.garray[g].bTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1276 if (game_globals.garray[g].numHalfMoves == 0)
1277 game_globals.garray[g].timeOfStart = now;
1278 game_globals.garray[g].lastMoveTime = now;
1279 game_globals.garray[g].lastDecTime = now;
1282 if (game_globals.garray[g].revertHalfMove == game_globals.garray[g].totalHalfMoves) {
1283 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1284 if (player_globals.parray[p1].status != PLAYER_PROMPT) continue;
1285 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1286 pprintf(p1, "Game %u: %s %s\n", g, EndString(g,0), EndSym(g));
1294 int com_backward(int p, param_list param)
1296 struct player *pp = &player_globals.parray[p];
1302 if (!((pp->game >=0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE) || (game_globals.garray[pp->game].status == GAME_SETUP)))) {
1303 pprintf(p, "You are not examining any games.\n");
1306 if (game_globals.garray[pp->game].status == GAME_SETUP) {
1307 pprintf (p,"You can't move backward yet, the postion is still being set up.\n");
1312 if (param[0].type == TYPE_INT) {
1313 nHalfMoves = param[0].val.integer;
1315 if (game_globals.garray[g].numHalfMoves != 0) {
1316 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1317 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1319 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1320 pprintf(p1, "Game %u: %s backs up %d move%s.\n",
1322 pp->name, nHalfMoves, (nHalfMoves == 1) ? "" : "s");
1326 for (i = 0; i < nHalfMoves; i++) {
1327 if (backup_move(g, REL_EXAMINE) != MOVE_OK) {
1328 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1329 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1331 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1332 pprintf(p1, "Game %u: Beginning of game.\n", g);
1339 if (game_globals.garray[g].numHalfMoves < game_globals.garray[g].revertHalfMove) {
1340 game_globals.garray[g].revertHalfMove = game_globals.garray[g].numHalfMoves;
1342 /* roll back time */
1343 if (game_globals.garray[g].game_state.onMove == WHITE) {
1344 game_globals.garray[g].wTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1346 game_globals.garray[g].bTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1349 if (game_globals.garray[g].numHalfMoves == 0)
1350 game_globals.garray[g].timeOfStart = now;
1351 game_globals.garray[g].lastMoveTime = now;
1352 game_globals.garray[g].lastDecTime = now;
1357 int com_revert(int p, param_list param)
1359 struct player *pp = &player_globals.parray[p];
1365 if (!((pp->game >=0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE)|| (game_globals.garray[pp->game].status == GAME_SETUP)))) {
1366 pprintf(p, "You are not examining any games.\n");
1369 if (game_globals.garray[pp->game].status == GAME_SETUP) {
1370 pprintf (p,"You can't move revert yet, the position is still being set up.\n");
1374 nHalfMoves = game_globals.garray[g].numHalfMoves - game_globals.garray[g].revertHalfMove;
1375 if (nHalfMoves == 0) {
1376 pprintf(p, "Game %u: Already at mainline.\n", g);
1379 if (nHalfMoves < 0) { /* eek - should NEVER happen! */
1380 d_printf( "OUCH! in com_revert: nHalfMoves < 0\n");
1383 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1384 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1386 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1387 pprintf(p1, "Game %u: %s reverts to mainline.\n",
1391 for (i = 0; i < nHalfMoves; i++) {
1392 backup_move(g, REL_EXAMINE);/* should never return error */
1394 /* roll back time */
1395 if (game_globals.garray[g].game_state.onMove == WHITE) {
1396 game_globals.garray[g].wTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1398 game_globals.garray[g].bTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1401 if (game_globals.garray[g].numHalfMoves == 0)
1402 game_globals.garray[g].timeOfStart = now;
1403 game_globals.garray[g].lastMoveTime = now;
1404 game_globals.garray[g].lastDecTime = now;
1409 int com_history(int p, param_list param)
1412 char fname[MAX_FILENAME_SIZE];
1414 if (param[0].type == TYPE_WORD) {
1415 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1422 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, player_globals.parray[p1].login[0],
1423 player_globals.parray[p1].login, STATS_GAMES);
1424 pgames(p, p1, fname);
1430 int com_journal(int p, param_list param)
1432 struct player *pp = &player_globals.parray[p];
1434 char fname[MAX_FILENAME_SIZE];
1436 if (param[0].type == TYPE_WORD) {
1437 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1444 if (!CheckPFlag(p1, PFLAG_REG)) {
1445 pprintf (p,"Only registered players may keep a journal.\n");
1450 if (CheckPFlag(p1, PFLAG_JPRIVATE) && (p != p1)
1451 && (pp->adminLevel < ADMIN_ADMIN)) {
1452 pprintf (p,"Sorry, this journal is private.\n");
1457 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, player_globals.parray[p1].login[0],
1458 player_globals.parray[p1].login, STATS_JOURNAL);
1459 pjournal(p, p1, fname);
1465 /* Remove a journal item */
1467 int com_jkill(int p, param_list param)
1469 struct player *pp = &player_globals.parray[p];
1471 char* kill = param[0].val.word;
1472 char fname[MAX_FILENAME_SIZE];
1473 char fname_new[MAX_FILENAME_SIZE];
1476 if (!CheckPFlag(p, PFLAG_REG)) {
1477 pprintf (p,"Only registered players may keep a journal.\n");
1481 if ((strlen(kill) != 1) || (!(isalpha(kill[0])))) {
1482 pprintf (p,"Journal entries are referenced by single letters.\n");
1486 if (((kill[0] - 'a' + 1) > MAX_JOURNAL) && (pp->adminLevel < ADMIN_ADMIN)
1487 && (!titled_player(p,pp->login))) {
1488 pprintf (p,"Your maximum journal entry is %c\n",toupper ((char)(MAX_JOURNAL
1493 sprintf(fname, "%s/player_data/%c/%s.journal",
1494 STATS_DIR, pp->login[0],pp->login);
1495 sprintf (fname_new,"%s.w",fname);
1497 Journal = fopen_s(fname, "r");
1498 if (Journal == NULL) {
1499 pprintf(p, "You don't have a journal.\n");
1503 kill[0] = toupper(kill[0]);
1505 if (removejournalitem(p, kill[0], Journal,fname_new,&empty)) {
1507 rename (fname_new,fname);
1510 sprintf(fname, "%s/%c/%s.%c",
1511 JOURNAL_DIR, pp->login[0],pp->login,tolower(kill[0]));
1513 pprintf (p,"Journal entry %c deleted.\n",kill[0]);
1515 pprintf (p,"You have no journal entry %c.\n",kill[0]);
1522 static void jsave_journalentry(int p,char save_spot,int p1,char from_spot,char* to_file)
1524 struct player *pp = &player_globals.parray[p];
1526 char fname[MAX_FILENAME_SIZE], fname2[MAX_FILENAME_SIZE];
1527 char* name_from = player_globals.parray[p1].login;
1528 char* name_to = pp->login;
1531 sprintf(fname, "%s/%c/%s.%c", JOURNAL_DIR, name_from[0],name_from,from_spot);
1532 Game = fopen_s(fname, "r");
1534 pprintf(p, "Journal entry %c not available for %s.\n", toupper(from_spot), player_globals.parray[p1].name);
1539 sprintf(fname2, "%s/%c/%s.%c", JOURNAL_DIR, name_to[0],name_to,save_spot);
1541 if (file_copy(fname, fname2) != 0) {
1542 pprintf (p,"Copy in jsave_journalentry failed!\n");
1543 pprintf (p,"Please report this to an admin.\n");
1544 d_printf("CHESSD: Copy failed in jsave_journalentry\n");
1548 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, name_from[0],
1549 name_from, STATS_JOURNAL);
1551 j = (struct journal*) malloc (sizeof(struct journal));
1552 if (!journal_get_info(p,tolower(from_spot),j,fname)) {
1557 j->slot = toupper(save_spot);
1558 addjournalitem(p, j, to_file);
1560 pprintf(p,"Journal entry %s %c saved in slot %c in journal.\n",player_globals.parray[p1].name, toupper(from_spot), toupper(save_spot));
1564 static void jsave_history(int p,char save_spot,int p1,int from,char* to_file)
1566 struct player *pp = &player_globals.parray[p];
1569 char jfname[MAX_FILENAME_SIZE];
1570 char* HistoryFname = FindHistory2(p, p1, from, Eco, End);
1571 /* End symbol Mat Res, etc is the only thing we can't find out */
1572 char command[MAX_FILENAME_SIZE*2+3];
1573 char* name_to = pp->login;
1578 if (HistoryFname == NULL) {
1581 Game = fopen_s(HistoryFname, "r");
1583 pprintf(p, "History game %d not available for %s.\n",
1584 from, player_globals.parray[p1].name);
1588 sprintf(jfname, "%s/%c/%s.%c", JOURNAL_DIR, name_to[0],name_to,save_spot);
1589 unlink(jfname); /* necessary if cp is hard aliased to cp -i */
1590 sprintf(command, "cp %s %s",HistoryFname,jfname);
1591 if (file_copy(HistoryFname, jfname) != 0) {
1592 pprintf (p,"Copy in jsave_history failed!\n");
1593 pprintf (p,"Please report this to an admin.\n");
1594 d_printf("CHESSD: Copy failed in jsave_journalentry\n");
1597 g = game_new(); /* Open a dummy game */
1599 if (ReadGameAttrs(Game, g) < 0) {
1600 pprintf (p,"Gamefile is corrupt. Please tell an admin.\n");
1607 j = (struct journal*) malloc (sizeof(struct journal));
1609 if (game_globals.garray[g].private) {
1614 if (game_globals.garray[g].type == TYPE_BLITZ) {
1616 } else if (game_globals.garray[g].type == TYPE_WILD) {
1618 } else if (game_globals.garray[g].type == TYPE_STAND) {
1620 } else if (game_globals.garray[g].type == TYPE_LIGHT) {
1622 } else if (game_globals.garray[g].type == TYPE_BUGHOUSE) {
1625 if (game_globals.garray[g].type == TYPE_NONSTANDARD)
1630 if (game_globals.garray[g].rated) {
1637 j->slot = toupper(save_spot);
1638 strcpy (j->WhiteName, game_globals.garray[g].white_name);
1639 j->WhiteRating = game_globals.garray[g].white_rating;
1640 strcpy (j->BlackName, game_globals.garray[g].black_name);
1641 j->BlackRating = game_globals.garray[g].black_rating;
1642 j->t = game_globals.garray[g].wInitTime;
1643 j->i = game_globals.garray[g].wIncrement;
1644 strcpy (j->eco, Eco);
1645 strcpy (j->ending, End);
1646 strcpy (j->result, EndSym(g));
1648 addjournalitem(p, j, to_file);
1650 pprintf(p,"Game %s %d saved in slot %c in journal.\n",
1651 player_globals.parray[p1].name, from, toupper(save_spot));
1655 int com_jsave(int p, param_list param)
1657 struct player *pp = &player_globals.parray[p];
1659 char* to = param[0].val.word;
1661 char fname[MAX_FILENAME_SIZE];
1663 if (!CheckPFlag(p, PFLAG_REG)) {
1664 pprintf (p,"Only registered players may keep a journal.\n");
1668 if ((strlen(to) != 1) || (!(isalpha(to[0])))) {
1669 pprintf (p,"Journal entries are referenced by single letters.\n");
1673 if (((to[0] - 'a' + 1) > MAX_JOURNAL) && (pp->adminLevel < ADMIN_ADMIN) && (!titled_player(p,pp->login))) {
1674 pprintf (p,"Your maximum journal entry is %c\n",toupper ((char)(MAX_JOURNAL + 'A' - 1)));
1678 if (!FindPlayer(p, param[1].val.word, &p1, &p1conn))
1681 if (param[2].type == TYPE_INT) {
1683 /* grab from a history */
1684 sprintf (fname,"%s/player_data/%c/%s.%s",STATS_DIR,pp->login[0],pp->login, STATS_JOURNAL);
1685 jsave_history(p, to[0], p1, param[2].val.integer,fname);
1689 from = param[2].val.word;
1691 if ((strlen(from) != 1) || (!(isalpha(from[0])))) {
1692 pprintf (p,"Journal entries are referenced by single letters.\n");
1698 if (CheckPFlag(p1, PFLAG_JPRIVATE)
1699 && (pp->adminLevel < ADMIN_ADMIN) && (p != p1)) {
1700 pprintf (p,"Sorry, the journal from which you are trying to fetch is private.\n");
1707 if (((to[0] - 'a' + 1) > MAX_JOURNAL) && (player_globals.parray[p1].adminLevel < ADMIN_ADMIN) && (!titled_player(p,player_globals.parray[p1].login))) {
1708 pprintf (p,"%s's maximum journal entry is %c\n",player_globals.parray[p1].name,toupper((char)(MAX_JOURNAL + 'A' - 1)));
1713 if (( p == p1) && (to[0] == from [0])) {
1714 pprintf (p,"Source and destination entries are the same.\n");
1718 /* grab from a journal */
1720 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, pp->login[0],
1721 pp->login, STATS_JOURNAL);
1722 jsave_journalentry(p,to[0],p1, from[0], fname);
1730 int com_refresh(int p, param_list param)
1732 struct player *pp = &player_globals.parray[p];
1735 if (param[0].type == TYPE_NULL) {
1736 if (pp->game >= 0) {
1737 send_board_to(pp->game, p);
1738 } else { /* Do observing in here */
1739 if (pp->num_observe) {
1740 for (g = 0; g < pp->num_observe; g++) {
1741 send_board_to(pp->observe_list[g], p);
1744 pprintf(p, "You are neither playing, observing nor examining a game.\n");
1749 g = GameNumFromParam (p, &p1, ¶m[0]);
1752 if ((g >= game_globals.g_num) || ((game_globals.garray[g].status != GAME_ACTIVE)
1753 && ((game_globals.garray[g].status != GAME_EXAMINE)
1754 || (game_globals.garray[g].status != GAME_SETUP)))) {
1755 pprintf(p, "No such game.\n");
1758 int link = game_globals.garray[g].link;
1760 if ((game_globals.garray[g].private && pp->adminLevel==ADMIN_USER) &&
1761 (game_globals.garray[g].white != p) && (game_globals.garray[g].white != p1)) {
1763 if ((game_globals.garray[link].white != p) && (game_globals.garray[link].black != p)) {
1764 pprintf (p, "Sorry, game %d is a private game.\n", g+1);
1770 if (game_globals.garray[g].private)
1771 pprintf(p, "Refreshing static game %d\n", g+1);
1772 send_board_to(g, p);
1778 int com_prefresh(int p, param_list param)
1780 struct player *pp = &player_globals.parray[p];
1781 int retval, part = pp->partner;
1784 pprintf(p, "You do not have a partner.\n");
1787 retval = pcommand (p, "refresh %s", player_globals.parray[part].name);
1788 if (retval == COM_OK)
1789 return COM_OK_NOPROMPT;