1    | /*
2    |    ** $Log: ml_list.c,v $
3    |    ** Revision 1.10  2003/07/28 14:23:09  millis
4    |    ** Fix bug 205
5    |    **
6    |    ** Revision 1.9  2003/01/14 13:51:37  millis
7    |    ** Merges from USTV
8    |    **
9    |    ** Revision 1.8  2002/08/27 22:27:54  millis
10   |    ** Updated for automake/autoconf functionality
11   |    **
12   |    ** Revision 1.7  2002/04/18 04:44:32  greg
13   |    ** Added the following commands:
14   |    ** - unstart
15   |    ** - set secret
16   |    ** - set [prflist|prfrand|prfboth]
17   |    **
18   |    ** Fixed Set Absence so that "to" is not case sensitive
19   |    **
20   |    ** Fixed Quiet games so that new players are announced
21   |    ** before the game starts
22   |    **
23   |    ** Fixed ascii_to_ded.c so thatit no longer generates an
24   |    ** error when compiled
25   |    **
26   |    ** Revision 1.6  2001/07/15 09:17:15  greg
27   |    ** added support for game directories in a sub directory
28   |    **
29   |    ** Revision 1.5  2001/05/13 17:18:42  greg
30   |    ** took off ")" at line 224
31   |    **
32   |    ** Revision 1.4  2001/05/12 07:42:55  greg
33   |    ** minor bug fixes proposed by Mario Becroft & Philippe Lalande
34   |    ** to display zero dedications in listing and problems with
35   |    ** user's dedication
36   |    **
37   |    ** Revision 1.3  2001/04/15 21:21:22  miller
38   |    ** Add use of GetMaxCountryStrlen() to space out properly for big country names
39   |    **
40   |    ** Revision 1.2  2000/11/14 14:27:37  miller
41   |    ** Various changes including:
42   |    **  - Adjust display for blind games
43   |    **  - Display Late Count if enabled
44   |    **  - Display to master who is whatching press
45   |    **  - Show new flags
46   |    **  - Different message if game has quota but has XF_MANUALSTART set
47   |    **
48   |    ** Revision 1.1  1998/02/28 17:49:42  david
49   |    ** Initial revision
50   |    **
51   |    ** Revision 1.2  1997/02/16 20:43:18  davidn
52   |    ** Additions to dipent structure and associated code, to allow duplex variants.
53   |    ** Command is "set players n".
54   |    **
55   |    ** Revision 1.1  1996/10/20 12:29:45  rpaar
56   |    ** Morrolan v9.0
57   |    **
58   |  */
59   | 
60   | /*  ml_list.c -- Generate listings of game parameters.
61   |    **
62   |    **  Copyright 1987, Lowe.
63   |    **
64   |    **  Diplomacy is a trademark of the Avalon Hill Game Company, Baltimore,
65   |    **  Maryland, all rights reserved; used with permission.
66   |    **
67   |    **  Redistribution and use in source and binary forms are permitted
68   |    **  provided that it is for non-profit purposes, that this and the 
69   |    **  above notices are preserved and that due credit is given to Mr.
70   |    **  Lowe.
71   |    **
72   |    **  DATE        NAME         REASON
73   |    **  ----------- ------------ -----------------------------------------
74   |    **  ?? ??? 1987 Ken Lowe     He wrote it
75   |    **  30 Dec 1996 David Norman Additions for dipent.no_of_players
76   |    **  18 Nov 1999 Millis Miller Changed display for a non-started, terminated 
77   | 				 game
78   |    **  26 Nov 1999 Millis Miller Added Display if in Shrthand mode
79   |    */
80   | 
81   | #include <string.h>
82   | #include <time.h>
83   | 
84   | #include "config.h"
85   | #include "functions.h"
86   | #include "dip.h"
87   | #include "mail.h"
88   | 
89   | 
90   | /***************************************************************************/
91   | 
92   | void mail_listit(void)
93   | {
94   | 
95   | /*  List out current status of the game  */
96   | 
97   | 	int i, f, n;
98   | 	int ccount;
99   | 	char *s, line[150];
100  | 	long now;
101  | 	FILE *fp;
102  | 	int ok_for_blind = 0;
103  | 
104  | 	/* If it's not blind, ok to show everything */
105  | 	if (!(dipent.flags & F_BLIND)) ok_for_blind = 1;
106  | 
107  | 	time(&now);
108  | 
109  | 	if (dipent.phase[6] == 'X' && dipent.seq[0] == 'x') {
110  | 	       fprintf(rfp, "Game '%s' is already terminated before starting.\n", 
111  | 			dipent.name);
112  | 	}
113  | 	else if (dipent.seq[0] == 'x') {
114  | 
115  | 		n = dipent.no_of_players - (dipent.seq[1] - '0');
116  | 
117  | 		if (!(dipent.flags & F_QUIET)) {
118  | 			fprintf(rfp, "Game '%s' is waiting for %d%s player%s to sign on.\n",
119  | 			dipent.name, n, n == dipent.no_of_players ? "" : " more",
120  | 				n == 1 ? "" : "s");
121  | 		}
122  | 
123  | 	} else if (dipent.phase[6] == 'X') {
124  | 		ok_for_blind = 1; /* Game over, so ok to show all for blind */
125  | 
126  | 		for (i = 0; i < dipent.n; i++) {
127  | 			if (dipent.players[i].power < 0)
128  | 				continue;
129  | 
130  | 			if (dipent.players[i].centers >= dipent.vp) {
131  | 				fprintf(rfp, "Game '%s' completed in %4.4s.\n",
132  | 					dipent.name, &dipent.phase[1]);
133  | 				break;
134  | 			}
135  | 		}
136  | 		if (i == dipent.n) {
137  | 			fprintf(rfp, "Game '%s' was terminated in %s of %4.4s.\n", dipent.name,
138  | 				dipent.phase[1] == 'F' ? "fall" :
139  | 				dipent.phase[1] == 'U' ? "summer" :
140  | 				"spring", &dipent.phase[1]);
141  | 		}
142  | 	} else {
143  | 
144  | 		fprintf(rfp, "Game '%s' order #%s (%s) has a deadline of %s.\n",
145  | 			dipent.name, dipent.seq, dipent.phase, ptime(&dipent.deadline));
146  | 		if (now < dipent.start)
147  | 			fprintf(rfp, "The earliest orders will be processed is %s.\n",
148  | 				ptime(&dipent.start));
149  | 		if (now < dipent.deadline) {
150  | 			for (i = 0; i < dipent.n; i++) {
151  | 				if (dipent.players[i].power < 0)
152  | 					continue;
153  | 
154  | 				if (WAITING(dipent.players[i].status)) {
155  | 					fprintf(rfp, "One or more players have not gotten their orders in.\n");
156  | 					break;
157  | 				}
158  | 			}
159  | 			for (i = 0; i < dipent.n; i++) {
160  | 				if (dipent.players[i].power < 0)
161  | 					continue;
162  | 
163  | 				if ((dipent.players[i].status &
164  | 				     (SF_ABAND | SF_CD | SF_WAIT)) == SF_WAIT) {
165  | 					fprintf(rfp, "One or more players have requested that orders not be ");
166  | 					fprintf(rfp, "processed\nuntil the deadline.\n");
167  | 					break;
168  | 				}
169  | 			}
170  | 		}
171  | 		fprintf(rfp, "Those who haven't gotten their orders in will be %s if ",
172  | 			dipent.flags & F_NONMR ? "abandoned" : "CD");
173  | 		fprintf(rfp, "nothing\nis received by %s.\n", ptime(&dipent.grace));
174  | 	}
175  | 
176  | 	fprintf(rfp, "\nThe parameters for '%s' are as follows:\n", dipent.name);
177  | 	params(rfp);
178  | 
179  | 	sprintf(line, "%s%s/info", GAME_DIR, dipent.name);
180  | 	if ((fp = fopen(line, "r"))) {
181  | 		fputc('\n', rfp);
182  | 		while (fgets(line, sizeof(line), fp))
183  | 			fputs(line, rfp);
184  | 		fclose(fp);
185  | 	}
186  | 	if (dipent.n) {
187  | 		
188  | 		int lates, abandons;
189  | 		fprintf(rfp, "\nThe following players are signed up for game '%s':\n",
190  | 			dipent.name);
191  | 		lates = abandons = 0;
192  | 
193  | 		for (i = 0; i < dipent.n; i++) {
194  | 			if (dipent.players[i].power < 0)
195  | 				continue;
196  | 
197  | 			f = dipent.players[i].status;
198  | 			s = "";
199  | 
200  | 			if (f & (SF_CD | SF_ABAND))
201  | 				abandons++;
202  | 
203  | 			if (now > dipent.deadline && WAITING(f))
204  | 				lates++;
205  | 
206  | 			if (dipent.flags & F_QUIET && (!signedon ||
207  | 						       (player != i && dipent.players[player].power != MASTER))) {
208  | 				if (f & SF_MOVE && ok_for_blind) {
209  | 					s = "move";
210  | 				}
211  | 			} else if (f & SF_CD) {
212  | 				s = "CD";
213  | 			} else if (f & SF_ABAND) {
214  | 				s = "abandon";
215  | 			} else if (f & SF_MOVE && ok_for_blind) {
216  | 				s = "move";
217  | 				if (now > dipent.deadline && WAITING(f)) {
218  | 					s = f & SF_PART ? "part" : "late";
219  | 				}
220  | 			}
221  | 
222  | 			sprintf(line, "   %-*.*s %-7.7s", GetMaxCountryStrlen(), GetMaxCountryStrlen(), powers[dipent.players[i].power], s);
223  | 
224  | /*			fprintf(rfp, "   %-*.*s %-7.7s", GetMaxCountryStrlen(), GetMaxCountryStrlen(), powers[dipent.players[i].power], s);*/
225  | 			if (ok_for_blind && 
226  | 			     (dipent.players[i].units || dipent.players[i].centers)) {
227  | 				ccount = dipent.players[i].centers-dipent.players[i].centres_blockaded;
228  | 				sprintf(line, "%s%2d/%d%s",
229  | 					line,
230  | 					dipent.players[i].units, 
231  | 					ccount,
232  | 					dipent.players[i].centers < 10 ? " " : "");
233  | 
234  | /*
235  |  *				fprintf(rfp, "%2d/%d%s",
236  |  *					dipent.players[i].units, 
237  |  *					ccount,
238  |  *					dipent.players[i].centers < 10 ? " " : "");
239  |  */
240  | 			} else
241  | 				strcat(line, "     ");
242  | /*				fputs("     ", rfp); */
243  | 
244  | 			/* Now display late count if either master or not quiet/late_count */
245  | 		        if ((dipent.xflags & XF_LATECOUNT) ) {	
246  | 				if ((dipent.players[i].power >= 0 && dipent.players[i].power < WILD_PLAYER) &&
247  | 				    ((signedon && (dipent.players[player].power == MASTER || player == i)) || (!(dipent.flags & F_QUIET)))) 
248  | 					sprintf(line, "%s %2d ", line, dipent.players[i].late_count);
249  | /*					fprintf(rfp, " %2d ", dipent.players[i].late_count);  */
250  | 				else
251  | 					strcat(line, "   ");
252  | /*					fprintf(rfp, "   "); */
253  | 			}
254  | 			else
255  | 				strcat(line, "   ");
256  | /*				fprintf(rfp, "   "); */
257  | 			
258  | 			if (signedon && (dipent.players[player].power == MASTER || player == i)) {
259  | 				if (dipent.players[i].status & SF_PRESS)
260  | 					strcat(line, "*");
261  | /*					fprintf(rfp,"*"); */
262  | 				else
263  | 					strcat(line, " ");
264  | /*					fprintf(rfp, " "); */
265  | 			} else {
266  | 				strcat(line, " ");
267  | /*				fprintf(rfp, " "); */
268  | 			}
269  | 
270  | 	
271  | 			if ( (!(dipent.flags & F_GUNBOAT)
272  | 			    && 0 < dipent.players[i].userid
273  | 			    && dipent.players[i].userid <= nded)
274  | /*			    && ded[dipent.players[i].userid].r */
275  | 			    && (0 != strcmp(dipent.players[i].password,GONE_PWD)))
276  | 				sprintf(line, "%s%4d", line, ded[dipent.players[i].userid].r);
277  | /*				fprintf(rfp, "%4d", ded[dipent.players[i].userid].r); */
278  | 			else
279  | 				strcat(line, "    ");
280  | /*				fputs("    ", rfp); */
281  | 
282  | 			if (dipent.flags & F_GUNBOAT
283  | 			    && dipent.players[i].power != MASTER
284  | 			    && (!signedon || dipent.players[player].power != MASTER)
285  | 			    && ((signedon && player != i)
286  | 			|| strcasecmp(raddr, dipent.players[i].address)))
287  | 				sprintf(line, "%s %s\n", line, someone);
288  | /*				fprintf(rfp, " %s\n", someone); */
289  | 			else
290  | 				sprintf(line, "%s %s\n", line, dipent.players[i].address);
291  | /*				fprintf(rfp, " %s\n", dipent.players[i].address); */
292  | 
293  | 			if (!(dipent.x2flags & X2F_SECRET) ||
294  | 			  (dipent.seq[0] != 'x') ||
295  | 			  (signedon && dipent.players[player].power == MASTER) ||
296  | 			  (dipent.players[i].power == MASTER) ||
297  | 			  !(strcasecmp(raddr, dipent.players[i].address)))
298  | 				fprintf(rfp, line);
299  | 
300  | 		}
301  | 
302  | 		if ((dipent.seq[0] == 'x') &&
303  | 		  (dipent.x2flags & X2F_SECRET) &&
304  | 		  !(signedon && dipent.players[player].power == MASTER)) {
305  | 			fprintf(rfp, "\n  Other players kept secret.\n");
306  | 		}
307  | 
308  | 		if (dipent.flags & F_QUIET && (lates || abandons)) {
309  | 			fputs("\n", rfp);
310  | 			if (lates) {
311  | 				if (dipent.x2flags & X2F_SECRET)
312  | 					fprintf(rfp, "One or more powers are late.\n");
313  | 				else
314  | 					fprintf(rfp, "%d power%s late.\n", lates, lates == 1 ? " is" : "s are");
315  | 			}
316  | 			if (abandons) {
317  | 				if (dipent.x2flags & X2F_SECRET)
318  | 					fprintf(rfp, "One or more powers are abandoned.\n");
319  | 				else
320  | 					fprintf(rfp, "%d power%s abandoned.\n", abandons, abandons == 1 ? " is" : "s are");
321  | 			}
322  | 
323  | /*			fputs("\n", rfp); */
324  | 		}
325  | 	}
326  | 
327  | 
328  | 	fputs("\n", rfp);
329  | 
330  | }
331  | 
332  | 
333  | /***************************************************************************/
334  | 
335  | void mail_listbrief(void)
336  | {
337  | 
338  | /*  List out current status of the game briefly */
339  | 
340  | 	int i, n;
341  | 	char *s;
342  | 	static int count = 0;
343  | 
344  | 
345  | 	if (!count++) {
346  | 		fprintf(rfp, "Name      Phase    Variant/Options\n");
347  | 		fprintf(rfp, "-------   ------   ---------------\n");
348  | 	}
349  | 	fprintf(rfp, "%-10.10s%-9.9s", dipent.name, dipent.phase);
350  | 
351  | 	fprintf(rfp, "%c%s",
352  | 	toupper(*variants[dipent.variant]), variants[dipent.variant] + 1);
353  | 
354  | 	if (dipent.flags & F_GUNBOAT)
355  | 		fprintf(rfp, ", Gunboat");
356  | 
357  | 	if (dipent.flags & F_BLIND)
358  | 		fprintf(rfp, ", Blind");
359  | 
360  | 	if (dipent.flags & F_AFRULES)
361  | 		fprintf(rfp, ", A/F");
362  | 
363  |         if (dipent.flags & F_SHORTHAND)
364  | 		fprintf(rfp, ", Shorthand");
365  | 
366  | 	if (dipent.flags & F_WINGS)
367  | 		fprintf(rfp, ", Wings");
368  | 
369  | 	if (!(dipent.flags & F_NONMR))
370  | 		fprintf(rfp, ", NMR");
371  | 
372  | 	if ((i = (int) dipent.movement.next) < 72)
373  | 		fprintf(rfp, ", %d hrs", i);
374  | 
375  | 	if (dipent.access == A_ANY)
376  | 		fprintf(rfp, ", Any-site");
377  | 
378  | 	if (dipent.access == A_SAME)
379  | 		fprintf(rfp, ", Same-site");
380  | 
381  | 	if (dipent.flags & F_MODERATE) {
382  | 		fprintf(rfp, ", Moderated (");
383  | 		for (i = 0; i < dipent.n; i++) {
384  | 			if (dipent.players[i].power == MASTER) {
385  | 				for (n = 0, s = dipent.players[i].address; *s && *s != '@'; s++)
386  | 					fputc(!n++ && islower(*s) ? toupper(*s) : *s, rfp);
387  | 				break;
388  | 			}
389  | 		}
390  | 		fputc(')', rfp);
391  | 	}
392  | /*  Comment this out to not display press in brief listing   *RV*  */
393  | /*    Comment until the next "*RV*" */
394  | 
395  | 	fprintf(rfp, ", Press:");
396  | 
397  | 	if (dipent.flags & F_NOWHITE)
398  | 		fprintf(rfp, "-");
399  | 	else
400  | 		fprintf(rfp, "W");
401  | 
402  | 	if (dipent.flags & F_GREY)
403  | 		fprintf(rfp, "G");
404  | 	else
405  | 		fprintf(rfp, "-");
406  | 
407  | 	if (dipent.flags & F_NOPARTIAL || dipent.flags & F_NOWHITE)
408  | 		fprintf(rfp, "-");
409  | 	else
410  | 		fprintf(rfp, "P");
411  | 
412  | 	if (dipent.flags & F_FAKE)
413  | 		fprintf(rfp, "F");
414  | 	else
415  | 		fprintf(rfp, "-");
416  | 
417  | /*     *RV*             */
418  | 
419  | 	if (dipent.flags & F_NORATE)
420  | 		fprintf(rfp, ", Unrated");
421  | 
422  | /*  Uncomment this for a display of Winning Centres in brief listing */
423  | /*  fprintf(rfp,", Win=%d",dipent.vp); */
424  | 
425  | 	if (dipent.phase[6] == 'X') {
426  | 		for (i = 0; i < dipent.n; i++) {
427  | 			if (dipent.players[i].power < 0)
428  | 				continue;
429  | 
430  | 			if (dipent.players[i].centers >= dipent.vp) {
431  | 				fprintf(rfp, ", Completed");
432  | 				break;
433  | 			}
434  | 		}
435  | 		if (i == dipent.n) {
436  | 			fprintf(rfp, ", Terminated");
437  | 		}
438  | 	}
439  | 	fputs(".\n", rfp);
440  | 
441  | 	if ((n = strlen(dipent.comment))) {
442  | 		if (n < 60)
443  | 			n = 20;
444  | 		else if (n < 69)
445  | 			n = 11;
446  | 		else
447  | 			n = 79 - n;
448  | 		fprintf(rfp, "%*s%s\n", n, "", dipent.comment);
449  | 	}
450  |         
451  | 	if (dipent.phase[6] != 'X' && dipent.seq[0] == 'x') {
452  | 		n = dipent.np - (dipent.seq[1] - '0');
453  | 		if (n == 0) fprintf(rfp, "%21.21sFormed: waiting to be started.\n","");
454  | 		else if (dipent.x2flags & X2F_SECRET) {
455  | 		    fprintf(rfp, "%21.21sForming: more players needed.\n", "" );
456  | 		} else {
457  | 		     fprintf(rfp, "%21.21sForming: %d%s player%s needed.\n", "",
458  | 		        n, n == dipent.np ? "" : " more", n == 1 ? "" : "s");
459  | 		}
460  | 	} else if (dipent.phase[6] != 'X') {
461  | 		n = 0;
462  | 		for (i = 0; i < dipent.n; i++) {
463  | 			if (dipent.players[i].power < 0)
464  | 				continue;
465  | 
466  | 			if ((dipent.players[i].status & (SF_CD | SF_ABAND)
467  | 			     || *dipent.players[i].address == '*') &&
468  | 			    (dipent.players[i].status & SF_MOVE
469  | 			     || dipent.players[i].centers != 0)) {
470  | 
471  | 				if (!n++)
472  | 					fprintf(rfp, "%21.21sOpenings: ", "");
473  | 				else
474  | 					fputs(", ", rfp);
475  | 
476  | 				fprintf(rfp, "%s", powers[dipent.players[i].power]);
477  |                                 if (!(dipent.flags & F_BLIND))
478  |                                     fprintf(rfp, " (%d/%d)",
479  |                                         dipent.players[i].units,
480  |                                         dipent.players[i].centers-dipent.players[i].centres_blockaded);
481  |  			}
482  | 		}
483  | 		if (n)
484  | 			fputs("\n", rfp);
485  | 	}
486  | }
487  | 
488  | 
489  | /***************************************************************************/