1    | /*
2    |  * $Log: ml_short.c,v $
3    |  * Revision 1.2  2002/04/06 15:03:58  miller
4    |  * Added space after "province" and allow "prov" abbreviation
5    |  *
6    |  * Revision 1.1  2000/11/14 14:27:37  miller
7    |  * Initial revision
8    |  *
9    |  * Revision 1.1  1998/02/28 17:49:42  david
10   |  * Initial revision
11   |  *
12   |  * Revision 1.3  1997/03/16 06:53:13  rpaar
13   |  *
14   |  * Revision 1.2  1996/11/05 23:11:36  rpaar
15   |  * USIT changes to fix minor bugs
16   |  */
17   | 
18   | /*  ml_short. -- process incoming shorthand mail
19   |  *  Copyright 1987, Lowe.
20   |  *
21   |  *  Diplomacy is a trademark of the Avalon Hill Game Company, Baltimore,
22   |  *  Maryland, all rights reserved; used with permission.
23   |  *
24   |  *  Redistribution and use in source and binary forms are permitted
25   |  *  provided that it is for non-profit purposes, that this and the 
26   |  *  above notices are preserved and that due credit is given to Mr.
27   |  *  Lowe.
28   |  */
29   | 
30   | #include <stdio.h>
31   | #include <stdlib.h>
32   | #include <string.h>
33   | #include <time.h>
34   | 
35   | #include "dip.h"
36   | #include "mail.h"
37   | #include "functions.h"
38   | #include "conf.h"
39   | #include "porder.h"
40   | 
41   | #define SH_PROPOSE 	1
42   | #define SH_ACCEPT 	2
43   | #define SH_REJECT 	3
44   | #define SH_INFORM 	4
45   | #define SH_DRAW 	5
46   | #define SH_PEACE 	6
47   | #define SH_ALLY 	7
48   | #define SH_TARGET 	8
49   | #define SH_DMZ		9
50   | #define SH_NOT		10
51   | #define SH_PROVINCE     11
52   | #define SH_ORDER        15
53   | 
54   | /* And these do not appear in 'searchable' list */
55   | #define SH_BLANK	12
56   | #define SH_PHASE	13
57   | #define SH_POWER	14
58   | #define SH_PROV_LIST	16
59   | #define SH_ERROR	17
60   | #define SH_NOPOWERS     18
61   | #define SH_NOPROV	19
62   | #define SH_SEPARATOR	20
63   | #define SH_MASTER	21 
64   | #define SH_OBSERVER	22
65   | 
66   | static char *sh_prelim[] =
67   | {"", 
68   |  "proposes","propose",
69   |  "accepts", "accept",
70   |  "rejects", "reject",
71   |  "informs", "inform",
72   |  "draw", 
73   |   "peace", 
74   |   "alliance","ally", 
75   |  "targets","target", 
76   |   "dmz", 
77   |  "not", "!", 
78   |  "provinces","province", "prov",
79   |  "orders", "order",
80   |   ","
81   |   };
82   | static int sh_pvalue[] =
83   | {0, 
84   |  SH_PROPOSE, SH_PROPOSE,
85   |  SH_ACCEPT, SH_ACCEPT,
86   |  SH_REJECT, SH_REJECT,
87   |  SH_INFORM, SH_INFORM,
88   |  SH_DRAW, 
89   |  SH_PEACE,
90   |  SH_ALLY, SH_ALLY,
91   |  SH_TARGET, SH_TARGET,
92   |  SH_DMZ, 
93   |  SH_NOT, SH_NOT,
94   |  SH_PROVINCE, SH_PROVINCE, SH_PROVINCE,
95   |  SH_ORDER, SH_ORDER,
96   |  SH_SEPARATOR
97   | };
98   | 
99   | 
100  | #define NO_POWERS 0
101  | #define CANBE_POWERS 1
102  | #define MUSTBE_POWERS 2
103  | #define NO_PROVINCE 0
104  | #define CANBE_PROVINCE 0
105  | #define MUSTBE_PROVINCE 2
106  | 
107  | int ProcessShSegment(char **s, char *rrret_text, int power_list, int prov_list);
108  | /*
109  |  * This function shoud be replaced by the phase function in phase.c
110  |  */
111  | 
112  | int CheckShSegmentPhase(char *s, char *rret_text) 
113  | {
114  | 	char poss_phase[7];
115  | 	rret_text[0] = '\0';
116  | 	strncpy(poss_phase, s, 6);
117  | 	poss_phase[6] = '\0';
118  | 	if (!isalnum(*s)) {
119  | 		while (!isalnum(*s) && *s != '\0' ) s++; /* Skip spaces */
120  |         }	
121  | 	if (GetOneWord(poss_phase) == 0 ) return SH_BLANK;
122  | 
123  | 	if (strlen(s) < 6 ) return SH_ERROR;
124  | 	/* Only accept annnl */
125  | 	switch (toupper(s[0]))
126  | 	{
127  | 		case 'F':
128  | 		case 'S':
129  | 			rret_text[0]=toupper(s[0]);
130  | 			break;
131  | 		default:
132  | 			return SH_ERROR;
133  | 	}
134  | 
135  | 	if (!isdigit(s[1]) || !isdigit(s[2]) || !isdigit(s[3]) || !isdigit(s[4]) )
136  | 	{
137  | 		return SH_ERROR;
138  | 	}
139  | 	rret_text[1] = s[1];
140  | 	rret_text[2] = s[2];
141  | 	rret_text[3] = s[3];
142  | 	rret_text[4] = s[4];
143  | 	switch (toupper(s[5]))
144  | 	{
145  | 		case 'M':
146  | 		case 'R':
147  | 			rret_text[5] = toupper(s[5]);
148  | 			break;
149  | 		case 'B':
150  | 			/* Check if fall, as only fall has a build phase */
151  | 			if (rret_text[0] == 'F' ) {
152  | 			     rret_text[5] = toupper(s[5]);
153  |                              break;
154  | 			}
155  | 			/* Intentional fall-through */
156  | 
157  | 		default:
158  | 			rret_text[5] = '\0';
159  | 			return SH_ERROR;
160  | 	}
161  | 
162  | 	rret_text[6] = '\0';  /* Null-terminate it */
163  | 
164  | 	return SH_PHASE;
165  | }
166  | 
167  | #define NOIFS 0
168  | 
169  | int mail_shorthand(char *text)
170  | {
171  | 	char sh_line[1024];
172  | 	int ret;
173  | 	int last_ret = SH_BLANK;
174  | 	char ret_text[1024];
175  | 	int com_type = 0; /* =1 for propose, accept, reject */
176  | 	int com_class = 0; /* =1 for draw, peace, DMZ, prov, order */
177  |         int com_dmz = 0;  /* Number of times DMZ encountered */
178  | 	int com_not = 0; /* Number of times NOT encountered */
179  | 	int prov_list = 0;
180  | 	int first_entry = 0;
181  | 	char *text1;
182  |         char phase_text[7];
183  |         char phase_type;
184  | 
185  | 	phase_text[0]='\0';
186  | 	text1 = text;
187  | 	
188  | 	sh_line[0] = '\0';
189  | 	ret_text[0] = '\0';
190  | 	/* firstly, strip away leading blanks */
191  | 	despace(text);
192  | 	if (*text1 == '\0') {
193  | 		/* blank line, ignore */
194  | 		*text = '\0';
195  | 		return 0;
196  | 	}
197  | 	if (!dipent.pr_valid) {
198  | 		/* pr[] must be filled to run this code */
199  | 		po_init();
200  | 		gamein();
201  | 		dipent.pr_valid++;
202  | 	}
203  | 
204  | 	while (!com_type) {
205  | 		ret = ProcessShSegment(&text1, ret_text, CANBE_POWERS, NO_PROVINCE);
206  | 		switch (ret)
207  | 		{
208  | 			case SH_INFORM:
209  | 			case SH_POWER:
210  | 			{
211  | 				strcat(sh_line, ret_text);
212  | 				break;
213  | 			}
214  | 			case SH_PROPOSE:
215  | 			case SH_ACCEPT:
216  | 			case SH_REJECT:
217  | 			{
218  | 			        if (last_ret == SH_INFORM) {
219  | 				    strcat(sh_line, "\nError: Inform must be followed by a powerlist.");
220  | 				    strcpy(text,sh_line);
221  |                                     strcat(text,"\n");
222  | 				    return 1;	
223  | 				}
224  | 				strcat(sh_line,ret_text);
225  | 				com_type++;
226  | 				break;
227  | 			}
228  | 			case SH_BLANK:
229  | 			{
230  | 				if (first_entry == 0) {
231  | 				    /* blank line, return and ignore */
232  | 				    *text = 0;
233  | 				    return 0;
234  | 				}
235  | 				strcat(sh_line, "\nError: Line ended before finding Propose/Accept/Reject.");
236  | 				strcpy(text,sh_line);
237  | 				strcat(text,"\n");
238  | 				return 1;
239  | 				break;
240  | 			}
241  | 			case SH_MASTER:
242  | 			{
243  | 				strcat(sh_line, "\nError: Master is not a valid power in shorthand power list.");
244  |                                 strcpy(text,sh_line);
245  |                                 strcat(text,"\n");
246  |                                 return 1;
247  | 			}
248  | 			default:
249  | 				strcat(sh_line,"\nError: Expected Propose/Accept/Reject not ");
250  | 				strcat(sh_line, ret_text);
251  | 				strcat(sh_line,".\n");
252  | 				strcpy(text,sh_line);
253  | 				strcat(text,"\n");
254  | 				return 1;	/* Error return */
255  | 		}
256  | 		first_entry++;
257  | 		last_ret = ret;
258  | 
259  | 	};
260  | 
261  | 	/* OK, now look for a power/power list */
262  | 	ret = ProcessShSegment(&text1,ret_text, MUSTBE_POWERS, NO_PROVINCE);
263  | 	switch (ret)
264  | 	{
265  | 		case SH_POWER:
266  | 		{
267  | 			strcat(sh_line, ret_text);
268  | 			break;
269  | 		}
270  | 		case SH_BLANK:
271  | 		{
272  | 			strcat(sh_line, "\nError: Line ended before finding a power.");
273  | 			strcpy(text,sh_line);
274  | 			strcat(text,"\n");
275  | 			return 1;
276  | 			break;
277  | 		}
278  | 		case SH_MASTER:
279  | 		{
280  | 			strcat(sh_line, "\nError: Master is not a valid power in powerlist.");
281  |                         strcpy(text,sh_line);
282  |                         strcat(text,"\n");
283  |                         return 1;
284  | 	        }
285  | 		case SH_OBSERVER:
286  | 		{
287  | 			strcat(sh_line, "\nError: Observer is not allowed here as a power.");
288  |                         strcpy(text,sh_line);
289  |                         strcat(text,"\n");
290  |                         return 1;
291  | 		}
292  | 
293  | 		default:
294  | 			strcat(sh_line,"\nError: Expected Power not ");
295  |                         strcat(sh_line, ret_text);
296  |                         strcat(sh_line,".\n");
297  |                         strcpy(text,sh_line);
298  | 			strcat(text,"\n");
299  | 			return 1;       /* Error return */
300  | 	}
301  | 	/* Right, now see which command class it is */
302  |         while (!com_class) {
303  |                 ret = ProcessShSegment(&text1, ret_text, NO_POWERS, CANBE_PROVINCE);
304  |                 switch (ret)
305  |                 {
306  |                         case SH_DRAW:
307  |                         case SH_PEACE:
308  | 			{
309  | 				/* These commands end here */
310  | 				strcat(sh_line, ret_text);
311  | 				if (CheckShSegmentPhase(text1, phase_text) == SH_PHASE ) {
312  |                                         text1 += 6; /* Skip the found phase */
313  |                                         phase_type = phase_text[5];
314  | 					strcat(sh_line," ");
315  |                                         strcat(sh_line, phase_text);
316  |                                         strcat(sh_line," ");
317  |                                 }
318  | 				strcpy(text,sh_line);
319  | 				strcat(text,"\n");
320  | 				return 0;
321  | 			}
322  | 			case SH_ALLY:
323  | 				strcat(sh_line, ret_text);
324  | 				if (CheckShSegmentPhase(text1, phase_text) == SH_PHASE ) {
325  |                                         text1 += 6; /* Skip the found phase */
326  |                                         phase_type = phase_text[5];
327  |                                         strcat(sh_line, phase_text);
328  |                                         strcat(sh_line," ");
329  |                                 }
330  | 				ret = ProcessShSegment(&text1, ret_text, NO_POWERS, NO_PROVINCE);
331  |                 		switch (ret)
332  | 				{
333  | 					case SH_BLANK:
334  | 						strcpy(text,sh_line);
335  | 						strcat(text,"\n");
336  | 						return 0;
337  | 						break;
338  | 
339  | 					case SH_TARGET:
340  | 						strcat(sh_line, ret_text);
341  |                                 		ret = ProcessShSegment(&text1, ret_text, MUSTBE_POWERS, NO_PROVINCE);
342  | 						switch (ret)
343  |                                 		{
344  | 							case SH_POWER:
345  | 								strcat(sh_line, ret_text);
346  | 								strcpy(text,sh_line);
347  | 								strcat(text,"\n");
348  | 								return 0;
349  | 								break;
350  | 							case SH_BLANK:
351  | 								strcat(sh_line,"\nError: Expected powerlist.");
352  | 								strcpy(text,sh_line);
353  | 								strcat(text,"\n");
354  | 								return 1;
355  | 								break;
356  |                 					case SH_MASTER:
357  |                 					{
358  |                         					strcat(sh_line, "\nError: Master is not a valid power in powerlist.");
359  |                         					strcpy(text,sh_line);
360  |                         					strcat(text,"\n");
361  |                         					return 1;
362  |                 					}
363  |                 					case SH_OBSERVER:
364  |                 					{
365  |                         					strcat(sh_line, "\nError: Observer is not allowed here as a power.");
366  |                         					strcpy(text,sh_line);
367  |                         					strcat(text,"\n");
368  |                         					return 1;
369  |                 					}
370  | 							default:
371  | 								strcat(sh_line,"\nError: Expected powerlist not ");
372  | 								strcat(sh_line,ret_text);
373  | 								strcat(sh_line, ret_text);
374  | 								strcpy(text,sh_line);
375  | 								strcat(text,"\n");
376  | 								return 1;
377  | 						}
378  | 					default:
379  | 					{
380  | 						strcat(sh_line,"\nError: Not expected ");
381  |                                                                 strcat(sh_line,ret_text);
382  |                                                                 strcat(sh_line, ret_text);
383  |                                                                 strcpy(text,sh_line);
384  | 								strcat(text,"\n");
385  | 								return 1;
386  | 					}
387  | 				}
388  | 				break; /* out of courtesy */
389  | 			case SH_DMZ:
390  | 			{
391  | 				/* Duplicate instances of DMZ are treated as an error */
392  | 				if (com_dmz != 0) {
393  | 					strcpy(sh_line,"\n:Error - Duplicate DMZ specified.");
394  | 					strcpy(text,sh_line);
395  | 					strcat(text,"\n");
396  | 					return 1;
397  | 				}
398  | 				/* else */
399  | 				com_class++;
400  | 				com_dmz++;
401  | 				prov_list++;
402  | 				strcat(sh_line, ret_text);
403  | 				if (CheckShSegmentPhase(text1, phase_text) == SH_PHASE ) {
404  |                                         text1 += 6; /* Skip the found phase */
405  |                                         phase_type = phase_text[5];
406  |                                         strcat(sh_line, phase_text);
407  |                                         strcat(sh_line," ");
408  |                                 }
409  | 				break;
410  | 
411  | 			}
412  | 			case SH_ORDER:
413  | 			{
414  | 				strcat(sh_line,ret_text);
415  |         			/* See if there is a phase first, to know how to parse the order */
416  |             			if (CheckShSegmentPhase(text1, phase_text) == SH_PHASE ) {
417  |                 			text1 += 6; /* Skip the found phase */
418  | 			                phase_type = phase_text[5];
419  | 					strcat(sh_line, phase_text);
420  | 					strcat(sh_line," ");
421  | 			        } else {
422  | 			                phase_type = dipent.phase[5]; /* Use current phase */
423  | 					phase_text[0]='\0';
424  | 			        }
425  | 			        switch (phase_type) {
426  | 			                case 'B':
427  | 			                        if (build_syntaxcheck(text1,NOIFS, &sh_line[strlen(sh_line)]) == 0) {
428  | 			                        } else {
429  |                                                   strcpy(ret_text, "Invalid order:");
430  |                                                   strcat(ret_text,text1);
431  |                                                   strcat(sh_line,ret_text);
432  |                                                 strcpy(text,sh_line);
433  |                                                 strcat(text,"\n");
434  |                                                 return 1;
435  | 
436  |                                                 }
437  | 
438  | 			                        break;
439  | 			                case 'R':
440  |        			                 if (retreat_syntaxcheck(text1,NOIFS, &sh_line[strlen(sh_line)]) == 0)  {
441  | 						} else {
442  |                                                   strcpy(ret_text, "Invalid order:");
443  |                                                   strcat(ret_text,text1);
444  |                                                   strcat(sh_line,ret_text);
445  |                                                 strcpy(text,sh_line);
446  |                                                 strcat(text,"\n");
447  |                                                 return 1;
448  | 
449  |                                                 }
450  | 
451  | 			                        break;
452  | 			
453  |        			         	case 'M':
454  | 			                        if (move_syntaxcheck(text1,NOIFS, &sh_line[strlen(sh_line)]) == 0) {
455  | 			                        } else {
456  | 						  strcpy(ret_text, "Invalid order:");
457  | 						  strcat(ret_text,text1);
458  | 						  strcat(sh_line,ret_text);
459  |                                                 strcpy(text,sh_line);
460  |                                                 strcat(text,"\n");
461  |                                                 return 1;
462  | 
463  | 						}
464  | 					
465  | 						break;
466  | 					default:
467  | 						strcat(sh_line,
468  | 						       "\nError: bad phase type\n"); 
469  |                                                 strcat(sh_line,ret_text);
470  |                                                 strcpy(text,sh_line);
471  |                                                 strcat(text,"\n");
472  |                                                 return 1;
473  | 			        }
474  | 				/* It was decoded as an order so leave! */
475  | 				strcpy(text,sh_line);
476  | 				strcat(text,"\n");
477  | 				return 0;
478  | 			}
479  | 	
480  | 			case SH_PROVINCE:
481  | 			{
482  | 				com_class++;
483  |                                 com_dmz++;
484  |                                 prov_list++;
485  |                                 strcat(sh_line, ret_text);
486  | 				if (CheckShSegmentPhase(text1, phase_text) == SH_PHASE ) {
487  |                                         text1 += 6; /* Skip the found phase */
488  |                                         phase_type = phase_text[5];
489  |                                         strcat(sh_line, phase_text);
490  |                                         strcat(sh_line," ");
491  |                                 }
492  |                                 break;
493  | 			}
494  | 			case SH_NOT:
495  | 			{
496  |                                /* Duplicate instances of NOT are treated as an error */
497  |                                 if (com_not != 0) {
498  |                                         strcpy(sh_line,"\n:Error - Duplicate NOT specified.");
499  |                                         strcpy(text,sh_line);
500  | 					strcat(text,"\n");
501  | 					return 1;
502  |                                 }
503  |                                 /* else */
504  |                                 com_not++;
505  |                                 strcat(sh_line, ret_text);
506  |                                 break;
507  | 			}
508  | 			case SH_BLANK:
509  | 			{
510  | 				strcat(sh_line, "\n:Error - Command class expected.");
511  | 				strcpy(text,sh_line);
512  | 				strcat(text,"\n");
513  | 				return 1;
514  | 			}
515  | 			default:
516  | 				strcat(sh_line,"\nError: Expected command not ");
517  |                         	strcat(sh_line, ret_text);
518  |                         	strcat(sh_line,".");
519  |                         	strcpy(text,sh_line);
520  | 				strcat(text,"\n");
521  | 				return 1;       /* Error return */
522  | 		}
523  | 	};
524  | 	/* OK, at this point, we're expecting a list of provinces only */
525  |        
526  |        while (prov_list != 0 && prov_list < 4) {
527  | 	   ret = ProcessShSegment(&text1, ret_text, NO_POWERS, MUSTBE_PROVINCE);
528  | 	   switch (ret)
529  |            {
530  | 		case SH_PROV_LIST:
531  | 		{
532  | 			if (prov_list != 1) strcat(sh_line, ",");
533  | 			strcat(sh_line, ret_text);
534  | 			prov_list++;
535  | 			if (prov_list >= 4) { 
536  | 				/* Got the maximum number of provinces */
537  | 				strcpy(text,sh_line);
538  | 				strcat(text,"\n");
539  | 				return 0;
540  | 			}
541  | 			break;
542  | 		}
543  | 		case SH_BLANK:
544  | 		{
545  | 			prov_list = 0;
546  | 			strcpy(text,sh_line);
547  | 			strcat(text,"\n");
548  | 			return 0; /* That's the end! */
549  | 		}
550  | 		case SH_SEPARATOR:
551  | 		{
552  | 			break;  /* ignore separators */
553  | 		}
554  | 		default:
555  | 			prov_list = 0;
556  | 			strcat(sh_line,"\nError: Expected province not ");
557  |                                 strcat(sh_line, ret_text);
558  |                                 strcat(sh_line,".");
559  |                                 strcpy(text,sh_line);
560  | 				strcat(text,"\n");
561  | 				return 1;       /* Error return */
562  | 	     }
563  | 	};
564  | 	
565  | 	/* Should never get here! */
566  | 	strcpy(text,"**Unhandled shorthand line!**\n");
567  | 	return 1;
568  | }
569  | /* Prossess Shorthand single word 
570  |  * Parameters are:
571  |  * s : input text, from which first word is taken
572  |  * rrret_text: returned string
573  |  * power_list: set to 0 if a power is not possible in this context
574  |  * prov_list: set to 0 if a province is not possible in this context
575  |  * orderable: set to 0 if an order is not possible in this context
576  |  */
577  | 
578  | int ProcessShSegment(char **s, char *rrret_text, int power_list, int prov_list)
579  | {	
580  | 	static char power_text[100];
581  | 	static char in_text[150];
582  | 	char *t = power_text;
583  | 	char part_list[MAX_POWERS+1];
584  | 	int count;
585  | 	
586  | 	int p1,c1;  /* dummies for get_prov only */
587  | 
588  | 	int i;
589  |         int sh_error = 0;
590  | 	*rrret_text='\0'; /* Initialise output text */
591  | 
592  | 
593  | 	/* OK, first lets extract first word from 's' as it could be a power */
594  | 	strcpy(power_text, *s);
595  | 	if (GetOneWord(power_text) == 0) return SH_BLANK; /* nothing there! */
596  | 	strcpy(in_text, *s); /* Remember text! */
597  | 
598  |        if (power_list != NO_POWERS) {
599  |         /* OK, it could be a power, let's check! */
600  |             if (parse_powers(&t, part_list, dipent.np, &count,0) == 0 ) {
601  | 	    	    /*list_powers(rrret_text, power_text); */
602  | 		    i = 0;
603  | 		    while (power_text[i]!= 0) {
604  | 			power_text[i] = toupper(power_text[i]);
605  | 			i++;
606  | 		    }
607  | 		    strcpy(rrret_text, power_text); 
608  | 		    strcat(rrret_text," ");
609  | 	            while ( isspace(**s)== 0 && **s != '\0') (*s)++; /* skip until spaces start */		
610  | 		    while ( isspace(**s)!= 0 && **s != '\0') (*s)++; /* skip until spaces end */
611  | 		    /* The power 'M' is not allowed */
612  | 		    if (strchr(power_text, (int) 'M' ) != NULL ) return SH_MASTER;
613  | 		    /* The power 'O' is not allowed in the last powerlist */
614  | 		    if (strchr(power_text, (int) 'O') != NULL && power_list == MUSTBE_POWERS) return SH_OBSERVER;		    
615  | 		    return SH_POWER;
616  | 	    }
617  | 	    if (power_list == MUSTBE_POWERS) return SH_NOPOWERS; 
618  | 	}
619  | 	
620  |         if (prov_list != NO_PROVINCE) {
621  |         /* OK, it could also be a province, let's check */
622  | 		t = get_prov(*s, &p1, &c1);
623  | 		if (p1 != 0) /* indicates a province found */ {
624  | 			*s = t; /* resume AFTER match position */
625  | 			strcpy(rrret_text," ");
626  | 			strcat(rrret_text, pr[p1].name);
627  | 			return SH_PROV_LIST;
628  | 		}
629  | 		if (power_list == MUSTBE_PROVINCE) return SH_NOPROV;
630  |         }
631  | 	*s = lookfor(*s, sh_prelim, nentry(sh_prelim), &i);
632  | 
633  | 	sh_error = sh_pvalue[i];
634  | 	
635  | 	switch (sh_pvalue[i]) {
636  | 	
637  | 		case SH_PROPOSE:
638  | 			strcpy(rrret_text,"proposes ");
639  | 			break;
640  | 
641  | 		case SH_ACCEPT:
642  | 			strcpy(rrret_text,"accepts ");
643  | 			break;
644  | 
645  | 		case SH_REJECT:
646  | 			strcpy(rrret_text,"rejects ");
647  | 			break;
648  | 
649  | 		case SH_INFORM:
650  | 			strcpy(rrret_text,"informs ");
651  | 			break;
652  | 
653  | 		case SH_DRAW:
654  | 			strcpy(rrret_text,"draw");
655  | 			break;
656  | 
657  | 		case SH_PEACE:
658  | 			strcpy(rrret_text,"peace");
659  | 			break;
660  | 
661  | 		case SH_ALLY:
662  | 			strcpy(rrret_text,"alliance ");
663  | 			break;
664  | 
665  | 		case SH_TARGET:
666  | 			strcpy(rrret_text,"target ");
667  | 			break;
668  | 
669  | 		case SH_DMZ:
670  | 			strcpy(rrret_text, "DMZ ");
671  | 			break;
672  | 
673  | 		case SH_NOT:
674  | 			strcpy(rrret_text, "NOT ");
675  | 			break;
676  | 
677  | 		case SH_PROVINCE:
678  | 			strcpy(rrret_text, "province ");
679  | 			break;
680  | 
681  | 		case SH_SEPARATOR:
682  | 			strcpy(rrret_text,", ");
683  | 			break;
684  | 		case SH_ORDER:
685  | 			strcpy(rrret_text,"order ");
686  | 			break;
687  | 
688  | 		default:
689  | 			GetOneWord(in_text);
690  | 			sprintf(rrret_text,"'%s'", in_text);
691  | 			sh_error = SH_ERROR;
692  | 	}
693  | 
694  | 	return sh_error;
695  | }
696  |