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_noformat(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_noformat(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 (param[1].type == TYPE_NULL) {
459 if (!CheckPFlag(p, PFLAG_REG)) {
460 pprintf (p,"Unregistered players must specify their e-mail address.\n");
463 } else if(!safestring(param[1].val.string)) {
464 pprintf (p,"Bad e-mail address.\n");
468 if (param[0].type == TYPE_NULL) {
472 pprintf(p, "You are neither playing, observing nor examining a game.\n");
476 g = GameNumFromParam(p, &p1, ¶m[0]);
480 if ((g < 0) || (g >= game_globals.g_num) || ((game_globals.garray[g].status != GAME_ACTIVE) && (game_globals.garray[g].status != GAME_EXAMINE))) {
481 pprintf(p, "There is no such game.\n");
484 if ((game_globals.garray[g].white != p) && (game_globals.garray[g].black != p) && (game_globals.garray[g].private) && (pp->adminLevel < ADMIN_ADMIN)) {
485 pprintf(p, "Sorry, that is a private game.\n");
488 sprintf(subj, "FICS game report %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
489 if (param[1].type == TYPE_NULL ? mail_string_to_user(p, subj,
490 movesToString(g, CheckPFlag(p, PFLAG_PGN))) :
491 mail_string_to_address(param[1].val.string, subj,
492 movesToString(g, CheckPFlag(p, PFLAG_PGN)))) {
493 pprintf(p, "Moves NOT mailed, perhaps your address is incorrect.\n");
495 pprintf(p, "Moves mailed.\n");
500 static int old_mail_moves(int p,int mail, param_list param)
505 char fname[MAX_FILENAME_SIZE];
509 if (mail && !CheckPFlag(p, PFLAG_REG)) {
510 pprintf (p,"Unregistered players cannot use mailoldmoves.\n");
514 if (param[0].type == TYPE_WORD) {
515 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
522 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR,
523 player_globals.parray[p1].login[0], player_globals.parray[p1].login, STATS_GAMES);
524 fp = fopen_s(fname, "r"); /* old moves now looks in history to save mem - DAV */
527 pprintf (p,"There is no old game for %s.\n", player_globals.parray[p1].name);
534 fgets(tmp, 1024, fp);
535 sscanf(ptmp, "%d", &count);
536 fclose(fp); /* find the last game played in history */
538 pprintf (p,"Last game for %s was history game %d.\n",player_globals.parray[p1].name,count);
541 pcommand (p,"mailstored %s %d",player_globals.parray[p1].name,count);
543 pcommand (p,"smoves %s %d",player_globals.parray[p1].name,count);
551 int com_oldmoves(int p, param_list param)
553 return old_mail_moves(p , 0, param);
556 int com_mailoldmoves(int p, param_list param)
558 return old_mail_moves(p , 1, param);
561 void ExamineScratch(int p, param_list param,int setup)
563 struct player *pp = &player_globals.parray[p];
564 char category[100], board[100], parsebuf[100];
572 if ((param[0].val.string != pp->name) &&
573 (param[1].type == TYPE_WORD)) {
574 strcpy(category, param[0].val.string);
575 strcpy(board, param[1].val.string);
576 } else if (param[1].type != TYPE_NULL) {
578 val = param[1].val.string;
580 while (!confused && (sscanf(val, " %99s", parsebuf) == 1)) {
581 val = eatword(eatwhite(val));
582 if ((category[0] != '\0') && (board[0] == '\0'))
583 strcpy(board, parsebuf);
584 else if (isdigit(*parsebuf)) {
585 pprintf(p, "You can't specify time controls.\n");
587 } else if (category[0] == '\0')
588 strcpy(category, parsebuf);
593 pprintf(p, "Can't interpret %s in match command.\n", parsebuf);
599 if (category[0] && !board[0]) {
600 pprintf(p, "You must specify a board and a category.\n");
608 decline_withdraw_offers(p, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
609 decline_withdraw_offers(p, -1, PEND_SIMUL,DO_WITHDRAW);
611 game_globals.garray[g].wInitTime = game_globals.garray[g].wIncrement = 0;
612 game_globals.garray[g].bInitTime = game_globals.garray[g].bIncrement = 0;
613 game_globals.garray[g].timeOfStart = tenth_secs();
614 game_globals.garray[g].wTime = game_globals.garray[g].bTime = 0;
615 game_globals.garray[g].rated = 0;
616 game_globals.garray[g].clockStopped = 0;
617 game_globals.garray[g].type = TYPE_UNTIMED;
618 game_globals.garray[g].white = game_globals.garray[g].black = p;
619 game_globals.garray[g].startTime = tenth_secs();
620 game_globals.garray[g].lastMoveTime = game_globals.garray[g].startTime;
621 game_globals.garray[g].lastDecTime = game_globals.garray[g].startTime;
622 game_globals.garray[g].totalHalfMoves = 0;
624 pp->side = WHITE; /* oh well... */
629 pprintf(p, "Starting a game in examine (scratch) mode.\n");
631 pprintf(p, "Starting a game in examine (setup) mode.\n");
634 pprintf(p, "Loading from catagory: %s, board: %s.\n", category, board);
637 game_globals.garray[g].FENstartPos[0] = 0; // [HGM] new shuffle game
639 board_clear(&game_globals.garray[g].game_state);
640 game_globals.garray[g].status = GAME_SETUP;
642 game_globals.garray[g].status = GAME_EXAMINE;
643 if (board_init(g,&game_globals.garray[g].game_state, category, board)) {
644 pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
645 d_printf( "CHESSD: PROBLEM LOADING BOARD. Examine Aborted.\n");
652 game_globals.garray[g].game_state.gameNum = g;
653 strcpy(game_globals.garray[g].white_name, pp->name);
654 strcpy(game_globals.garray[g].black_name, pp->name);
655 game_globals.garray[g].white_rating = game_globals.garray[g].black_rating = pp->s_stats.rating;
658 if (CheckPFlag(p, PFLAG_OPEN)) /*was open */
659 announce_notavail(p);
662 static int ExamineStored(FILE * fp, int p, char type)
664 struct player *pp = &player_globals.parray[p];
666 char category[100], board[100];
671 decline_withdraw_offers(p, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
672 decline_withdraw_offers(p, -1, PEND_SIMUL,DO_WITHDRAW);
675 gg = &game_globals.garray[g];
678 game_globals.garray[g].FENstartPos[0] = 0; // [HGM] make new shuffle for now
679 if (board_init(g,&gg->game_state, category, board)) {
680 pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
681 d_printf( "CHESSD: PROBLEM LOADING BOARD %s %s. Examine Aborted.\n",
687 gg->status = GAME_EXAMINE;
689 if (type == 'w' || type == 'n') {
690 if (ReadGameAttrs_exam(fp, g) < 0) {
691 pprintf(p, "Either this is an old wild/nonstandard game or the gamefile is corrupt.\n");
696 // [HGM] OK, we retreived the game info, which includes variant name as "category/board"
697 // So now we set up the board again, this time for the proper variant (and proper shuffle)
698 sscanf(gg->variant, "%s/%s", category, board);
699 if(category[0] && !board[0]) strcpy(board, "0");
700 if (board_init(g,&gg->game_state, category, board)) {
701 pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
702 d_printf( "CHESSD: PROBLEM LOADING BOARD %s %s. Examine Aborted.\n",
707 } else if (ReadGameAttrs(fp, g) < 0) {
708 pprintf(p, "Gamefile is corrupt; please notify an admin.\n");
713 gg->totalHalfMoves = gg->numHalfMoves;
714 gg->numHalfMoves = 0;
715 gg->revertHalfMove = 0;
718 gg->game_state.gameNum = g;
720 gg->startTime = tenth_secs();
721 gg->lastMoveTime = gg->startTime;
722 gg->lastDecTime = gg->startTime;
724 pp->side = WHITE; /* oh well... */
727 if (CheckPFlag(p, PFLAG_OPEN)) /* was open */
728 announce_notavail(p);
733 static void ExamineAdjourned(int p, int p1, int p2)
736 char *p1Login, *p2Login;
739 p1Login = player_globals.parray[p1].login;
740 p2Login = player_globals.parray[p2].login;
742 fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p1Login, p1Login, p2Login);
743 if (!fp) fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p2Login, p1Login, p2Login);
744 if (!fp) fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p2Login, p2Login, p1Login);
745 if (!fp) fp = fopen_p("%s/%c/%s-%s", "r", ADJOURNED_DIR, *p1Login, p2Login, p1Login);
747 pprintf(p, "No stored game between \"%s\" and \"%s\".\n",
748 player_globals.parray[p1].name, player_globals.parray[p2].name);
751 /* Assume old wild games are of type blitz - adjudicators should be
753 g = ExamineStored(fp, p,'b');
757 if (game_globals.garray[g].white_name[0] == '\0')
758 strcpy(game_globals.garray[g].white_name, p1Login);
759 if (game_globals.garray[g].black_name[0] == '\0')
760 strcpy(game_globals.garray[g].black_name, p2Login);
764 /* type is now returned because prior to V1.7.1 loading a wild game for
765 examining was impossible since the initial position was not saved.
766 Only types blitz,standard,lightning and untimed may be loaded for
767 examining if the gamefile version is less than 4 */
769 static char *FindHistory(int p, int p1, int game,char* type)
772 static char fileName[MAX_FILENAME_SIZE];
777 sprintf(fileName, "%s/player_data/%c/%s.%s", STATS_DIR,
778 player_globals.parray[p1].login[0], player_globals.parray[p1].login, STATS_GAMES);
779 fpHist = fopen_s(fileName, "r");
780 if (fpHist == NULL) {
781 pprintf(p, "No games in history for %s.\n", player_globals.parray[p1].name);
785 fscanf(fpHist, "%d %*c %*d %*c %*d %*s %s %*d %*d %*d %*d %*s %*s %ld",
786 &index, typestr, &when);
787 } while (!feof(fpHist) && index != game);
790 pprintf(p, "There is no history game %d for %s.\n", game, player_globals.parray[p1].name);
796 if (typestr[0] != 'p')
801 sprintf(fileName, "%s/%ld/%ld", HISTORY_DIR, when % 100, when);
805 /* I want to know how game ended/ECO code */
807 static char *FindHistory2(int p, int p1,int game, char* Eco,char* End)
810 static char fileName[MAX_FILENAME_SIZE];
814 sprintf(fileName, "%s/player_data/%c/%s.%s", STATS_DIR,
815 player_globals.parray[p1].login[0], player_globals.parray[p1].login, STATS_GAMES);
816 fpHist = fopen_s(fileName, "r");
817 if (fpHist == NULL) {
818 pprintf(p, "No games in history for %s.\n", player_globals.parray[p1].name);
822 fscanf(fpHist, "%d %*c %*d %*c %*d %*s %*s %*d %*d %*d %*d %s %s %ld",
823 &index, Eco, End, &when);
824 } while (!feof(fpHist) && index != game);
827 pprintf(p, "There is no history game %d for %s.\n", game, player_globals.parray[p1].name);
833 sprintf(fileName, "%s/%ld/%ld", HISTORY_DIR, when % 100, when);
837 int com_wname(int p, param_list param)
839 struct player *pp = &player_globals.parray[p];
845 !((game_globals.garray[g].status != GAME_EXAMINE) || (game_globals.garray[g].status != GAME_SETUP)))) {
846 pprintf (p, "You are not examining or setting up a game.\n");
850 if (param[0].type == TYPE_NULL)
851 strcpy (game_globals.garray[g].white_name,pp->name);
854 if (strlen (param[0].val.word) > MAX_LOGIN_NAME - 1) {
855 pprintf (p,"The maximum length of a name is %d characters.\n",MAX_LOGIN_NAME - 1);
858 strcpy (game_globals.garray[g].white_name,param[0].val.word);
865 int com_bname(int p, param_list param)
867 struct player *pp = &player_globals.parray[p];
873 !((game_globals.garray[g].status != GAME_EXAMINE) || (game_globals.garray[g].status != GAME_SETUP)))) {
874 pprintf (p, "You are not examining or setting up a game.\n");
878 if (param[0].type == TYPE_NULL)
879 strcpy (game_globals.garray[g].black_name,pp->name);
882 if (strlen (param[0].val.word) > MAX_LOGIN_NAME - 1) {
883 pprintf (p,"The maximum length of a name is %d characters.\n",MAX_LOGIN_NAME - 1);
886 strcpy (game_globals.garray[g].black_name,param[0].val.word);
893 static void ExamineHistory(int p, int p1, int game)
898 fileName = FindHistory(p, p1, game,&type);
900 FILE *fpGame = fopen_p("%s", "r", fileName);
901 if (fpGame == NULL) {
902 pprintf(p, "History game %d not available for %s.\n",
903 game, player_globals.parray[p1].name);
905 ExamineStored(fpGame, p,type);
911 static void ExamineJournal(int p,int p1,char slot)
913 struct player *pp = &player_globals.parray[p];
914 char* name_from = player_globals.parray[p1].login;
918 if (CheckPFlag(p1, PFLAG_JPRIVATE) && (p != p1)
919 && (pp->adminLevel < ADMIN_ADMIN)) {
920 pprintf (p,"Sorry, this journal is private.\n");
924 if ((slot - 'a' + 1) > MAX_JOURNAL &&
925 !check_admin(p1, ADMIN_ADMIN) &&
926 !titled_player(p,player_globals.parray[p1].login)) {
927 pprintf(p,"%s's maximum journal entry is %c\n",
928 player_globals.parray[p1].name,
929 toupper((char)(MAX_JOURNAL + 'A' - 1)));
933 fpGame = fopen_p("%s/%c/%s.%c", "r", JOURNAL_DIR, name_from[0],name_from,slot);
934 if (fpGame == NULL) {
935 pprintf(p, "Journal entry %c is not available for %s.\n", toupper (slot),
936 player_globals.parray[p1].name);
939 asprintf(&fname, "%s/player_data/%c/%s.journal",
940 STATS_DIR, name_from[0],name_from);
941 slot = toupper(slot);
943 if ((type = get_journalgame_type (p,fname,slot)) == '\0') {
944 pprintf(p, "Journal entry %c is not available for %s or is corrupt.\n",
945 slot, player_globals.parray[p1].name);
947 ExamineStored(fpGame, p,type);
955 int com_examine(int p, param_list param)
957 struct player *pp = &player_globals.parray[p];
958 int p1, p2 = p, p1conn, p2conn = 1;
960 char fname[MAX_FILENAME_SIZE];
963 if ((game_globals.garray[pp->game].status == GAME_EXAMINE) ||
964 (game_globals.garray[pp->game].status == GAME_SETUP))
965 pprintf(p, "You are already examining a game.\n");
967 pprintf(p, "You are playing a game.\n");
968 } else if (param[0].type == TYPE_NULL) {
969 ExamineScratch(p, param, 0);
970 } else if (param[0].type != TYPE_NULL) {
971 if ((param[1].type == TYPE_NULL) && (!strcmp(param[0].val.word,"setup"))) {
972 ExamineScratch(p, param, 1);
974 } else if (param[1].type == TYPE_WORD) {
975 sprintf(fname, "%s/%s/%s", BOARD_DIR, param[0].val.word, param[1].val.word);
976 if (file_exists(fname)) {
977 ExamineScratch(p, param, 0);
981 if (!FindPlayer(p, param[0].val.word, &p1, &p1conn))
984 if (param[1].type == TYPE_INT)
985 ExamineHistory(p, p1, param[1].val.integer);
987 if (param[1].type == TYPE_WORD) {
989 /* Lets check the journal */
990 wincstring = param[1].val.word;
991 if ((strlen(wincstring) == 1) && (isalpha(wincstring[0]))) {
992 ExamineJournal(p,p1,wincstring[0]);
997 if (!FindPlayer(p, param[1].val.word, &p2, &p2conn)) {
1004 ExamineAdjourned(p, p1, p2);
1014 int com_stored(int p, param_list param)
1021 char dname[MAX_FILENAME_SIZE];
1023 if (param[0].type == TYPE_WORD) {
1024 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1031 sprintf(dname, "%s/%c", ADJOURNED_DIR, player_globals.parray[p1].login[0]);
1032 dirp = opendir(dname);
1034 pprintf(p, "Player %s has no games stored.\n", player_globals.parray[p1].name);
1039 pprintf(p, "Stored games for %s:\n", player_globals.parray[p1].name);
1040 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
1041 if (file_has_pname(dp->d_name, player_globals.parray[p1].login)) {
1042 pprintf(p, " %s vs. %s\n", file_wplayer(dp->d_name), file_bplayer(dp->d_name));
1048 pprintf (p,"%d stored game%sfound.\n",count,(count == 1 ? " " : "s "));
1054 static void stored_mail_moves(int p, int mail, param_list param)
1056 struct player *pp = &player_globals.parray[p];
1057 int wp, wconnected, bp, bconnected, gotit = 0;
1059 char type; /* dummy */
1060 char* wincstring = NULL;
1061 char* name_from = NULL;
1062 char* fileName = NULL;
1063 char fileName2[MAX_FILENAME_SIZE];
1066 if (param[2].type == TYPE_NULL) {
1067 if (!CheckPFlag(p, PFLAG_REG)) {
1068 pprintf (p,"Unregistered players must specify their e-mail address.\n");
1071 } else if(!safestring(param[2].val.string)) {
1072 pprintf (p,"Bad e-mail address.\n");
1076 if (!FindPlayer(p, param[0].val.word, &wp, &wconnected))
1079 if (param[1].type == TYPE_INT) { /* look for a game from history */
1080 fileName = FindHistory(p, wp, param[1].val.integer,&type);
1081 if (fileName != NULL) {
1082 fpGame = fopen_s(fileName, "r");
1083 if (fpGame == NULL) {
1084 pprintf(p, "History game %d not available for %s.\n", param[1].val.integer, player_globals.parray[wp].name);
1087 if (ReadGameAttrs(fpGame, g) < 0)
1088 pprintf(p, "Gamefile is corrupt; please notify an admin.\n");
1094 } else { /* Let's test for journal */
1095 name_from = param[0].val.word;
1096 wincstring = param[1].val.word;
1097 if ((strlen(wincstring) == 1) && (isalpha(wincstring[0]))) {
1098 if (CheckPFlag(wp, PFLAG_JPRIVATE)
1099 && (pp->adminLevel < ADMIN_ADMIN) && (p != wp)) {
1100 pprintf (p,"Sorry, the journal from which you are trying to fetch is private.\n");
1102 if (((wincstring[0] - 'a' + 1) > MAX_JOURNAL) && (player_globals.parray[wp].adminLevel < ADMIN_ADMIN) && (!titled_player(p,player_globals.parray[wp].login))) {
1103 pprintf (p,"%s's maximum journal entry is %c\n",player_globals.parray[wp].name,toupper((char)(MAX_JOURNAL + 'A' - 1)));
1105 sprintf(fileName2, "%s/%c/%s.%c", JOURNAL_DIR, name_from[0],name_from,wincstring[0]);
1106 fpGame = fopen_s(fileName2, "r");
1107 if (fpGame == NULL) {
1108 pprintf(p, "Journal entry %c is not available for %s.\n", toupper(wincstring[0]),
1109 player_globals.parray[wp].name);
1112 if (ReadGameAttrs(fpGame, g) < 0)
1113 pprintf(p, "Journal entry is corrupt; please notify an admin.\n");
1122 /* look for a stored game between the players */
1124 if (FindPlayer(p, param[1].val.word, &bp, &bconnected)) {
1126 if (game_read(g, wp, bp) >= 0) { /* look for a game white-black, */
1128 } else if (game_read(g, bp, wp) >= 0) { /* or black-white */
1131 pprintf(p, "There is no stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
1139 if (strcasecmp(pp->name, game_globals.garray[g].white_name) && strcasecmp(player_globals.parray[p]
1140 .name, game_globals.garray[g].black_name) && game_globals.garray[g].private && (pp->adminLevel < ADMIN_ADMIN)) {
1141 pprintf(p, "Sorry, that is a private game.\n");
1143 if (mail == 1) { /*Do mailstored */
1145 if (param[1].type == TYPE_INT)
1146 sprintf(subj, "FICS history game: %s %d", player_globals.parray[wp].name, param[1].val.integer);
1148 if ((strlen(wincstring) == 1) && (isalpha(wincstring[0]))) {
1149 sprintf(subj, "FICS journal game %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
1151 sprintf(subj, "FICS adjourned game %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
1153 if (param[2].type == TYPE_NULL ? mail_string_to_user(p, subj,
1154 movesToString(g, CheckPFlag(p, PFLAG_PGN))) :
1155 mail_string_to_address(param[2].val.string, subj,
1156 movesToString(g, CheckPFlag(p, PFLAG_PGN))))
1157 pprintf(p, "Moves NOT mailed, perhaps your address is incorrect.\n");
1159 pprintf(p, "Moves mailed.\n");
1161 pprintf_noformat(p, "%s\n", movesToString(g, 0));
1171 /* Tidied up a bit but still messy */
1173 int com_mailstored(int p, param_list param)
1175 stored_mail_moves(p, 1, param);
1179 int com_smoves(int p, param_list param)
1181 stored_mail_moves(p, 0, param);
1185 int com_sposition(int p, param_list param)
1187 struct player *pp = &player_globals.parray[p];
1188 int wp, wconnected, bp, bconnected, confused = 0;
1191 if (!FindPlayer(p, param[0].val.word, &wp, &wconnected))
1193 if (!FindPlayer(p, param[1].val.word, &bp, &bconnected)) {
1200 if (game_read(g, wp, bp) < 0) { /* if no game white-black, */
1201 if (game_read(g, bp, wp) < 0) { /* look for black-white */
1203 pprintf(p, "There is no stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
1210 wconnected = bconnected;
1215 if ((wp != p) && (bp != p) && (game_globals.garray[g].private) && (pp->adminLevel < ADMIN_ADMIN)) {
1216 pprintf(p, "Sorry, that is a private game.\n");
1218 game_globals.garray[g].white = wp;
1219 game_globals.garray[g].black = bp;
1220 game_globals.garray[g].startTime = tenth_secs();
1221 game_globals.garray[g].lastMoveTime = game_globals.garray[g].startTime;
1222 game_globals.garray[g].lastDecTime = game_globals.garray[g].startTime;
1223 pprintf(p, "Position of stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
1224 send_board_to(g, p);
1235 int com_forward(int p, param_list param)
1237 struct player *pp = &player_globals.parray[p];
1243 if (!((pp->game >=0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE) || (game_globals.garray[pp->game].status == GAME_SETUP)))) {
1244 pprintf(p, "You are not examining any games.\n");
1247 if (game_globals.garray[pp->game].status == GAME_SETUP) {
1248 pprintf (p,"You can't move forward yet, the position is still being set up.\n");
1252 if (!strcmp(game_globals.garray[g].white_name, game_globals.garray[g].black_name)) {
1253 pprintf(p, "You cannot go forward; no moves are stored.\n");
1256 if (param[0].type == TYPE_INT) {
1257 nHalfMoves = param[0].val.integer;
1259 if (game_globals.garray[g].numHalfMoves > game_globals.garray[g].revertHalfMove) {
1260 pprintf(p, "Game %u: No more moves.\n", g);
1263 if (game_globals.garray[g].numHalfMoves < game_globals.garray[g].totalHalfMoves) {
1264 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1265 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1267 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1268 pprintf(p1, "Game %u: %s goes forward %d move%s.\n",
1270 pp->name, nHalfMoves, (nHalfMoves == 1) ? "" : "s");
1274 for (i = 0; i < nHalfMoves; i++) {
1275 if (game_globals.garray[g].numHalfMoves < game_globals.garray[g].totalHalfMoves) {
1276 execute_move(&game_globals.garray[g].game_state, &game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves], 1);
1277 if (game_globals.garray[g].numHalfMoves + 1 > game_globals.garray[g].examMoveListSize) {
1278 game_globals.garray[g].examMoveListSize += 20; /* Allocate 20 moves at a
1280 game_globals.garray[g].examMoveList = (struct move_t *) realloc(game_globals.garray[g].examMoveList, sizeof(struct move_t) * game_globals.garray[g].examMoveListSize);
1282 game_globals.garray[g].examMoveList[game_globals.garray[g].numHalfMoves] = game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves];
1283 game_globals.garray[g].revertHalfMove++;
1284 game_globals.garray[g].numHalfMoves++;
1286 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1287 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1289 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1290 pprintf(p1, "Game %u: End of game.\n", g);
1296 /* roll back time */
1297 if (game_globals.garray[g].game_state.onMove == WHITE) {
1298 game_globals.garray[g].wTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1300 game_globals.garray[g].bTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1303 if (game_globals.garray[g].numHalfMoves == 0)
1304 game_globals.garray[g].timeOfStart = now;
1305 game_globals.garray[g].lastMoveTime = now;
1306 game_globals.garray[g].lastDecTime = now;
1309 if (game_globals.garray[g].revertHalfMove == game_globals.garray[g].totalHalfMoves) {
1310 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1311 if (player_globals.parray[p1].status != PLAYER_PROMPT) continue;
1312 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1313 pprintf(p1, "Game %u: %s %s\n", g, EndString(g,0), EndSym(g));
1321 int com_backward(int p, param_list param)
1323 struct player *pp = &player_globals.parray[p];
1329 if (!((pp->game >=0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE) || (game_globals.garray[pp->game].status == GAME_SETUP)))) {
1330 pprintf(p, "You are not examining any games.\n");
1333 if (game_globals.garray[pp->game].status == GAME_SETUP) {
1334 pprintf (p,"You can't move backward yet, the postion is still being set up.\n");
1339 if (param[0].type == TYPE_INT) {
1340 nHalfMoves = param[0].val.integer;
1342 if (game_globals.garray[g].numHalfMoves != 0) {
1343 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1344 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1346 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1347 pprintf(p1, "Game %u: %s backs up %d move%s.\n",
1349 pp->name, nHalfMoves, (nHalfMoves == 1) ? "" : "s");
1353 for (i = 0; i < nHalfMoves; i++) {
1354 if (backup_move(g, REL_EXAMINE) != MOVE_OK) {
1355 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1356 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1358 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1359 pprintf(p1, "Game %u: Beginning of game.\n", g);
1366 if (game_globals.garray[g].numHalfMoves < game_globals.garray[g].revertHalfMove) {
1367 game_globals.garray[g].revertHalfMove = game_globals.garray[g].numHalfMoves;
1369 /* roll back time */
1370 if (game_globals.garray[g].game_state.onMove == WHITE) {
1371 game_globals.garray[g].wTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1373 game_globals.garray[g].bTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1376 if (game_globals.garray[g].numHalfMoves == 0)
1377 game_globals.garray[g].timeOfStart = now;
1378 game_globals.garray[g].lastMoveTime = now;
1379 game_globals.garray[g].lastDecTime = now;
1384 int com_revert(int p, param_list param)
1386 struct player *pp = &player_globals.parray[p];
1392 if (!((pp->game >=0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE)|| (game_globals.garray[pp->game].status == GAME_SETUP)))) {
1393 pprintf(p, "You are not examining any games.\n");
1396 if (game_globals.garray[pp->game].status == GAME_SETUP) {
1397 pprintf (p,"You can't move revert yet, the position is still being set up.\n");
1401 nHalfMoves = game_globals.garray[g].numHalfMoves - game_globals.garray[g].revertHalfMove;
1402 if (nHalfMoves == 0) {
1403 pprintf(p, "Game %u: Already at mainline.\n", g);
1406 if (nHalfMoves < 0) { /* eek - should NEVER happen! */
1407 d_printf( "OUCH! in com_revert: nHalfMoves < 0\n");
1410 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1411 if (player_globals.parray[p1].status != PLAYER_PROMPT)
1413 if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
1414 pprintf(p1, "Game %u: %s reverts to mainline.\n",
1418 for (i = 0; i < nHalfMoves; i++) {
1419 backup_move(g, REL_EXAMINE);/* should never return error */
1421 /* roll back time */
1422 if (game_globals.garray[g].game_state.onMove == WHITE) {
1423 game_globals.garray[g].wTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1425 game_globals.garray[g].bTime += (game_globals.garray[g].lastDecTime - game_globals.garray[g].lastMoveTime);
1428 if (game_globals.garray[g].numHalfMoves == 0)
1429 game_globals.garray[g].timeOfStart = now;
1430 game_globals.garray[g].lastMoveTime = now;
1431 game_globals.garray[g].lastDecTime = now;
1436 int com_history(int p, param_list param)
1439 char fname[MAX_FILENAME_SIZE];
1441 if (param[0].type == TYPE_WORD) {
1442 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1449 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, player_globals.parray[p1].login[0],
1450 player_globals.parray[p1].login, STATS_GAMES);
1451 pgames(p, p1, fname);
1457 int com_journal(int p, param_list param)
1459 struct player *pp = &player_globals.parray[p];
1461 char fname[MAX_FILENAME_SIZE];
1463 if (param[0].type == TYPE_WORD) {
1464 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1471 if (!CheckPFlag(p1, PFLAG_REG)) {
1472 pprintf (p,"Only registered players may keep a journal.\n");
1477 if (CheckPFlag(p1, PFLAG_JPRIVATE) && (p != p1)
1478 && (pp->adminLevel < ADMIN_ADMIN)) {
1479 pprintf (p,"Sorry, this journal is private.\n");
1484 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, player_globals.parray[p1].login[0],
1485 player_globals.parray[p1].login, STATS_JOURNAL);
1486 pjournal(p, p1, fname);
1492 /* Remove a journal item */
1494 int com_jkill(int p, param_list param)
1496 struct player *pp = &player_globals.parray[p];
1498 char* kill = param[0].val.word;
1499 char fname[MAX_FILENAME_SIZE];
1500 char fname_new[MAX_FILENAME_SIZE];
1503 if (!CheckPFlag(p, PFLAG_REG)) {
1504 pprintf (p,"Only registered players may keep a journal.\n");
1508 if ((strlen(kill) != 1) || (!(isalpha(kill[0])))) {
1509 pprintf (p,"Journal entries are referenced by single letters.\n");
1513 if (((kill[0] - 'a' + 1) > MAX_JOURNAL) && (pp->adminLevel < ADMIN_ADMIN)
1514 && (!titled_player(p,pp->login))) {
1515 pprintf (p,"Your maximum journal entry is %c\n",toupper ((char)(MAX_JOURNAL
1520 sprintf(fname, "%s/player_data/%c/%s.journal",
1521 STATS_DIR, pp->login[0],pp->login);
1522 sprintf (fname_new,"%s.w",fname);
1524 Journal = fopen_s(fname, "r");
1525 if (Journal == NULL) {
1526 pprintf(p, "You don't have a journal.\n");
1530 kill[0] = toupper(kill[0]);
1532 if (removejournalitem(p, kill[0], Journal,fname_new,&empty)) {
1534 rename (fname_new,fname);
1537 sprintf(fname, "%s/%c/%s.%c",
1538 JOURNAL_DIR, pp->login[0],pp->login,tolower(kill[0]));
1540 pprintf (p,"Journal entry %c deleted.\n",kill[0]);
1542 pprintf (p,"You have no journal entry %c.\n",kill[0]);
1549 static void jsave_journalentry(int p,char save_spot,int p1,char from_spot,char* to_file)
1551 struct player *pp = &player_globals.parray[p];
1553 char fname[MAX_FILENAME_SIZE], fname2[MAX_FILENAME_SIZE];
1554 char* name_from = player_globals.parray[p1].login;
1555 char* name_to = pp->login;
1558 sprintf(fname, "%s/%c/%s.%c", JOURNAL_DIR, name_from[0],name_from,from_spot);
1559 Game = fopen_s(fname, "r");
1561 pprintf(p, "Journal entry %c not available for %s.\n", toupper(from_spot), player_globals.parray[p1].name);
1566 sprintf(fname2, "%s/%c/%s.%c", JOURNAL_DIR, name_to[0],name_to,save_spot);
1568 if (file_copy(fname, fname2) != 0) {
1569 pprintf (p,"Copy in jsave_journalentry failed!\n");
1570 pprintf (p,"Please report this to an admin.\n");
1571 d_printf("CHESSD: Copy failed in jsave_journalentry\n");
1575 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, name_from[0],
1576 name_from, STATS_JOURNAL);
1578 j = (struct journal*) malloc (sizeof(struct journal));
1579 if (!journal_get_info(p,tolower(from_spot),j,fname)) {
1584 j->slot = toupper(save_spot);
1585 addjournalitem(p, j, to_file);
1587 pprintf(p,"Journal entry %s %c saved in slot %c in journal.\n",player_globals.parray[p1].name, toupper(from_spot), toupper(save_spot));
1591 static void jsave_history(int p,char save_spot,int p1,int from,char* to_file)
1593 struct player *pp = &player_globals.parray[p];
1596 char jfname[MAX_FILENAME_SIZE];
1597 char* HistoryFname = FindHistory2(p, p1, from, Eco, End);
1598 /* End symbol Mat Res, etc is the only thing we can't find out */
1599 char command[MAX_FILENAME_SIZE*2+3];
1600 char* name_to = pp->login;
1605 if (HistoryFname == NULL) {
1608 Game = fopen_s(HistoryFname, "r");
1610 pprintf(p, "History game %d not available for %s.\n",
1611 from, player_globals.parray[p1].name);
1615 sprintf(jfname, "%s/%c/%s.%c", JOURNAL_DIR, name_to[0],name_to,save_spot);
1616 unlink(jfname); /* necessary if cp is hard aliased to cp -i */
1617 sprintf(command, "cp %s %s",HistoryFname,jfname);
1618 if (file_copy(HistoryFname, jfname) != 0) {
1619 pprintf (p,"Copy in jsave_history failed!\n");
1620 pprintf (p,"Please report this to an admin.\n");
1621 d_printf("CHESSD: Copy failed in jsave_journalentry\n");
1624 g = game_new(); /* Open a dummy game */
1626 if (ReadGameAttrs(Game, g) < 0) {
1627 pprintf (p,"Gamefile is corrupt. Please tell an admin.\n");
1634 j = (struct journal*) malloc (sizeof(struct journal));
1636 if (game_globals.garray[g].private) {
1641 if (game_globals.garray[g].type == TYPE_BLITZ) {
1643 } else if (game_globals.garray[g].type == TYPE_WILD) {
1645 } else if (game_globals.garray[g].type == TYPE_STAND) {
1647 } else if (game_globals.garray[g].type == TYPE_LIGHT) {
1649 } else if (game_globals.garray[g].type == TYPE_BUGHOUSE) {
1652 if (game_globals.garray[g].type == TYPE_NONSTANDARD)
1657 if (game_globals.garray[g].rated) {
1664 j->slot = toupper(save_spot);
1665 strcpy (j->WhiteName, game_globals.garray[g].white_name);
1666 j->WhiteRating = game_globals.garray[g].white_rating;
1667 strcpy (j->BlackName, game_globals.garray[g].black_name);
1668 j->BlackRating = game_globals.garray[g].black_rating;
1669 j->t = game_globals.garray[g].wInitTime;
1670 j->i = game_globals.garray[g].wIncrement;
1671 strcpy (j->eco, Eco);
1672 strcpy (j->ending, End);
1673 strcpy (j->result, EndSym(g));
1675 addjournalitem(p, j, to_file);
1677 pprintf(p,"Game %s %d saved in slot %c in journal.\n",
1678 player_globals.parray[p1].name, from, toupper(save_spot));
1682 int com_jsave(int p, param_list param)
1684 struct player *pp = &player_globals.parray[p];
1686 char* to = param[0].val.word;
1688 char fname[MAX_FILENAME_SIZE];
1690 if (!CheckPFlag(p, PFLAG_REG)) {
1691 pprintf (p,"Only registered players may keep a journal.\n");
1695 if ((strlen(to) != 1) || (!(isalpha(to[0])))) {
1696 pprintf (p,"Journal entries are referenced by single letters.\n");
1700 if (((to[0] - 'a' + 1) > MAX_JOURNAL) && (pp->adminLevel < ADMIN_ADMIN) && (!titled_player(p,pp->login))) {
1701 pprintf (p,"Your maximum journal entry is %c\n",toupper ((char)(MAX_JOURNAL + 'A' - 1)));
1705 if (!FindPlayer(p, param[1].val.word, &p1, &p1conn))
1708 if (param[2].type == TYPE_INT) {
1710 /* grab from a history */
1711 sprintf (fname,"%s/player_data/%c/%s.%s",STATS_DIR,pp->login[0],pp->login, STATS_JOURNAL);
1712 jsave_history(p, to[0], p1, param[2].val.integer,fname);
1716 from = param[2].val.word;
1718 if ((strlen(from) != 1) || (!(isalpha(from[0])))) {
1719 pprintf (p,"Journal entries are referenced by single letters.\n");
1725 if (CheckPFlag(p1, PFLAG_JPRIVATE)
1726 && (pp->adminLevel < ADMIN_ADMIN) && (p != p1)) {
1727 pprintf (p,"Sorry, the journal from which you are trying to fetch is private.\n");
1734 if (((to[0] - 'a' + 1) > MAX_JOURNAL) && (player_globals.parray[p1].adminLevel < ADMIN_ADMIN) && (!titled_player(p,player_globals.parray[p1].login))) {
1735 pprintf (p,"%s's maximum journal entry is %c\n",player_globals.parray[p1].name,toupper((char)(MAX_JOURNAL + 'A' - 1)));
1740 if (( p == p1) && (to[0] == from [0])) {
1741 pprintf (p,"Source and destination entries are the same.\n");
1745 /* grab from a journal */
1747 sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR, pp->login[0],
1748 pp->login, STATS_JOURNAL);
1749 jsave_journalentry(p,to[0],p1, from[0], fname);
1757 int com_refresh(int p, param_list param)
1759 struct player *pp = &player_globals.parray[p];
1762 if (param[0].type == TYPE_NULL) {
1763 if (pp->game >= 0) {
1764 send_board_to(pp->game, p);
1765 } else { /* Do observing in here */
1766 if (pp->num_observe) {
1767 for (g = 0; g < pp->num_observe; g++) {
1768 send_board_to(pp->observe_list[g], p);
1771 pprintf(p, "You are neither playing, observing nor examining a game.\n");
1776 g = GameNumFromParam (p, &p1, ¶m[0]);
1779 if ((g >= game_globals.g_num) || ((game_globals.garray[g].status != GAME_ACTIVE)
1780 && ((game_globals.garray[g].status != GAME_EXAMINE)
1781 || (game_globals.garray[g].status != GAME_SETUP)))) {
1782 pprintf(p, "No such game.\n");
1785 int link = game_globals.garray[g].link;
1787 if ((game_globals.garray[g].private && pp->adminLevel==ADMIN_USER) &&
1788 (game_globals.garray[g].white != p) && (game_globals.garray[g].white != p1)) {
1790 if ((game_globals.garray[link].white != p) && (game_globals.garray[link].black != p)) {
1791 pprintf (p, "Sorry, game %d is a private game.\n", g+1);
1797 if (game_globals.garray[g].private)
1798 pprintf(p, "Refreshing static game %d\n", g+1);
1799 send_board_to(g, p);
1805 int com_prefresh(int p, param_list param)
1807 struct player *pp = &player_globals.parray[p];
1808 int retval, part = pp->partner;
1811 pprintf(p, "You do not have a partner.\n");
1814 retval = pcommand (p, "refresh %s", player_globals.parray[part].name);
1815 if (retval == COM_OK)
1816 return COM_OK_NOPROMPT;