2
|
1 /*--------------------------------------------------------------------------
|
|
2 NETREK II -- Paradise
|
|
3
|
|
4 Permission to use, copy, modify, and distribute this software and its
|
|
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
|
|
6 purpose and without fee is hereby granted, provided that this copyright
|
|
7 notice appear in all copies. No representations are made about the
|
|
8 suitability of this software for any purpose. This software is provided
|
|
9 "as is" without express or implied warranty.
|
|
10
|
|
11 Xtrek Copyright 1986 Chris Guthrie
|
|
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
|
|
13 Scott Silvey
|
|
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
|
|
15 Kurt Olsen
|
|
16 Brandon Gillespie
|
|
17 --------------------------------------------------------------------------*/
|
|
18
|
|
19 #include "config.h"
|
|
20 #include <stdio.h>
|
|
21 #include <sys/types.h>
|
|
22 #include <sys/stat.h>
|
|
23 #include "defs.h"
|
|
24 #include "data.h"
|
|
25 #include "struct.h"
|
|
26 #include "shmem.h"
|
|
27
|
|
28 #ifdef CLUECHECK1
|
|
29
|
|
30 /* ----------------- ROBS CLUECHECK -------------------- */
|
|
31
|
|
32 static char clueword[40];
|
|
33
|
|
34 void
|
|
35 set_clue_word(word)
|
|
36 char *word;
|
|
37 {
|
|
38 strncpy(clueword, word, sizeof(clueword));
|
|
39 clueword[sizeof(clueword) - 1] = 0;
|
|
40 }
|
|
41
|
|
42 #ifdef MOTD_SUPPORT
|
|
43 static char *motdstring = 0;
|
|
44 static int motdlen = 0;
|
|
45
|
|
46 void free_motdstruct();
|
|
47 #endif
|
|
48
|
|
49 /* read the MOTD into core so we can parse it later */
|
|
50 void
|
|
51 init_motdbuf(fname)
|
|
52 char *fname;
|
|
53 {
|
|
54 #ifdef MOTD_SUPPORT
|
|
55 struct stat stats;
|
|
56 FILE *fp;
|
|
57
|
|
58 if (motdstring != 0)
|
|
59 {
|
|
60 free_motdstruct();
|
|
61 free(motdstring);
|
|
62 motdstring = 0;
|
|
63 motdlen = 0;
|
|
64 }
|
|
65
|
|
66 if (!configvals->cluecheck ||
|
|
67 configvals->cluecheck != CC_MOTD)
|
|
68 return; /* don't waste the memory if we're not clue
|
|
69 * checking from the MOTD */
|
|
70
|
|
71 if (0 > stat(fname, &stats))
|
|
72 {
|
|
73 perror("statting file");
|
|
74 return;
|
|
75 }
|
|
76
|
|
77 motdlen = stats.st_size;
|
|
78
|
|
79 motdstring = (char *) malloc(motdlen + 1);
|
|
80 fp = fopen(fname, "r");
|
|
81 if (0 == fp)
|
|
82 {
|
|
83 perror("opening file");
|
|
84 exit(1);
|
|
85 }
|
|
86 fread(motdstring, motdlen, 1, fp);
|
|
87 #endif
|
|
88 }
|
|
89
|
|
90 static int page;
|
|
91 static int isfirst;
|
|
92
|
|
93 #ifdef MOTD_SUPPORT
|
|
94
|
|
95 static int line, wordn;
|
|
96
|
|
97 /* structures for the internal representation of the MOTD */
|
|
98 #define LINESPERPAGE 38
|
|
99
|
|
100 struct word
|
|
101 {
|
|
102 char *s;
|
|
103 };
|
|
104
|
|
105 struct line
|
|
106 {
|
|
107 struct word *words;
|
|
108 int nwords;
|
|
109 };
|
|
110
|
|
111 struct page
|
|
112 {
|
|
113 struct line lines[LINESPERPAGE];
|
|
114 int nlines;
|
|
115 struct page *next;
|
|
116 };
|
|
117
|
|
118 struct page *motdhead = 0;
|
|
119
|
|
120
|
|
121
|
|
122 #define MAXATTEMPTS 10
|
|
123 void
|
|
124 find_suitable_motd_word()
|
|
125 {
|
|
126 int attempts;
|
|
127 int pagecount;
|
|
128 int i;
|
|
129 struct page *currp;
|
|
130
|
|
131
|
|
132 for (pagecount = 0, currp = motdhead;
|
|
133 currp;
|
|
134 pagecount++, currp = currp->next)
|
|
135 ;
|
|
136
|
|
137 if (pagecount > 10)
|
|
138 pagecount = 10;
|
|
139
|
|
140 for (attempts = 0; pagecount > 1 && attempts < MAXATTEMPTS; attempts++)
|
|
141 {
|
|
142 /* the first page is excluded. Everybody sees that */
|
|
143 page = 1 + lrand48() % (pagecount - 1);
|
|
144
|
|
145 for (i = 0, currp = motdhead; i < page; i++, currp = currp->next)
|
|
146 ;
|
|
147 if (currp->nlines < 1)
|
|
148 continue;
|
|
149 if (lrand48() & 1)
|
|
150 {
|
|
151 /* get first word */
|
|
152 isfirst = 1;
|
|
153 for (line = 0; line < currp->nlines; line++)
|
|
154 if (currp->lines[line].nwords > 0)
|
|
155 break;
|
|
156 if (line >= currp->nlines)
|
|
157 continue;
|
|
158 wordn = 0;
|
|
159 }
|
|
160 else
|
|
161 {
|
|
162 /* get last word */
|
|
163 isfirst = 0;
|
|
164 for (line = currp->nlines - 1; line >= 0; line--)
|
|
165 if (currp->lines[line].nwords > 0)
|
|
166 break;
|
|
167 if (line < 0)
|
|
168 continue;
|
|
169 wordn = currp->lines[line].nwords - 1;
|
|
170 }
|
|
171 set_clue_word(currp->lines[line].words[wordn].s);
|
|
172 /*
|
|
173 * printf("%s word on page %d (line %d word %d) is %s\n",
|
|
174 * isfirst?"first":"last", page+1, line+1, wordn+1, clueword);
|
|
175 */
|
|
176 return;
|
|
177 }
|
|
178 page = -1;
|
|
179 }
|
|
180
|
|
181 #if 0
|
|
182 /* for the day when we have line numbers in the MOTD. */
|
|
183 void
|
|
184 find_suitable_word2()
|
|
185 {
|
|
186 int attempts;
|
|
187 int pagecount;
|
|
188 int i;
|
|
189 struct page *currp;
|
|
190
|
|
191
|
|
192 for (pagecount = 0, currp = motdhead; currp; pagecount++, currp = currp->next)
|
|
193 ;
|
|
194
|
|
195 for (attempts = 0; attempts < 10; attempts++)
|
|
196 {
|
|
197 page = lrand48() % pagecount;
|
|
198 for (i = 0, currp = motdhead; i < page; i++, currp = currp->next)
|
|
199 ;
|
|
200 if (currp->nlines < 1)
|
|
201 continue;
|
|
202 line = lrand48() % currp->nlines;
|
|
203 if (currp->lines[line].nwords < 1)
|
|
204 continue;
|
|
205 wordn = lrand48() % currp->lines[line].nwords;
|
|
206 set_clue_word(currp->lines[line].words[wordn].s);
|
|
207 printf("word on page %d line %d word %d is %s\n",
|
|
208 page + 1, line + 1, wordn + 1, clueword);
|
|
209 return;
|
|
210 }
|
|
211 clueword[0] = 0;
|
|
212 }
|
|
213 #endif
|
|
214
|
|
215 #if 0
|
|
216 /* useful for debugging the MOTD parsing routine */
|
|
217 void
|
|
218 printout_motd()
|
|
219 {
|
|
220 struct page *currp;
|
|
221 int i, j;
|
|
222 for (currp = motdhead; currp; currp = currp->next)
|
|
223 {
|
|
224 for (i = 0; i < currp->nlines; i++)
|
|
225 {
|
|
226 for (j = 0; j < currp->lines[i].nwords; j++)
|
|
227 {
|
|
228 printf("%s ", currp->lines[i].words[j].s);
|
|
229 }
|
|
230 printf("\n");
|
|
231 }
|
|
232 printf("\014");
|
|
233 }
|
|
234 }
|
|
235 #endif
|
|
236
|
|
237
|
|
238 void
|
|
239 parse_motd()
|
|
240 {
|
|
241 struct page **currp;
|
|
242 int idx;
|
|
243
|
|
244 if (motdhead)
|
|
245 return;
|
|
246
|
|
247 currp = &motdhead;
|
|
248
|
|
249 idx = 0;
|
|
250 while (idx < motdlen)
|
|
251 {
|
|
252 int validword;
|
|
253 char *wordbegin;
|
|
254
|
|
255 validword = 1;
|
|
256
|
|
257 /* skip whitespace */
|
|
258 while (!isalpha(motdstring[idx]) && motdstring[idx] != '\n' && idx < motdlen)
|
|
259 idx++;
|
|
260 if (idx >= motdlen)
|
|
261 break;
|
|
262
|
|
263 if (0 == *currp)
|
|
264 {
|
|
265 *currp = malloc(sizeof(**currp));
|
|
266 (*currp)->nlines = 1;
|
|
267 (*currp)->lines[0].nwords = 0;
|
|
268 (*currp)->next = 0;
|
|
269 }
|
|
270
|
|
271 if (motdstring[idx] == '\n')
|
|
272 {
|
|
273 idx++;
|
|
274 if (0 == strncmp(&motdstring[idx], "\t@@@", 4))
|
|
275 break;
|
|
276 else if (0 == strncmp(&motdstring[idx], "\t@@b", 4))
|
|
277 {
|
|
278 if (*currp)
|
|
279 currp = &(*currp)->next;
|
|
280 idx += 4;
|
|
281 }
|
|
282 else
|
|
283 {
|
|
284 struct line *currl = &(*currp)->lines[(*currp)->nlines - 1];
|
|
285 currl->words = realloc(currl->words, sizeof(*currl->words) * currl->nwords);
|
|
286 if ((*currp)->nlines >= LINESPERPAGE)
|
|
287 currp = &(*currp)->next;
|
|
288 else
|
|
289 {
|
|
290 (*currp)->lines[(*currp)->nlines].nwords = 0;
|
|
291 (*currp)->nlines++;
|
|
292 }
|
|
293 }
|
|
294 continue;
|
|
295 }
|
|
296 wordbegin = &motdstring[idx];
|
|
297 while (isalpha(motdstring[idx]) && idx < motdlen)
|
|
298 {
|
|
299 #if 0
|
|
300 if (!isalpha(motdstring[idx]))
|
|
301 validword = 0;
|
|
302 #endif
|
|
303 idx++;
|
|
304 }
|
|
305
|
|
306 if (0 && !validword)
|
|
307 continue;
|
|
308
|
|
309 {
|
|
310 struct line *currl = &(*currp)->lines[(*currp)->nlines - 1];
|
|
311 int len;
|
|
312
|
|
313 if (currl->nwords == 0)
|
|
314 {
|
|
315 int size = 40;
|
|
316 int j;
|
|
317 currl->words = malloc(sizeof(struct word) * size);
|
|
318 for (j = 0; j < size; j++)
|
|
319 {
|
|
320 currl->words[j].s = 0;
|
|
321 }
|
|
322 }
|
|
323 len = (&motdstring[idx]) - wordbegin;
|
|
324 currl->words[currl->nwords].s = malloc(len + 1);
|
|
325 strncpy(currl->words[currl->nwords].s, wordbegin, len);
|
|
326 currl->words[currl->nwords].s[len] = 0;
|
|
327 currl->nwords++;
|
|
328 }
|
|
329 }
|
|
330 }
|
|
331 #endif
|
|
332
|
|
333 /**********************************************************************/
|
|
334
|
|
335 char **phrases = 0;
|
|
336 int num_phrases = 0;
|
|
337
|
|
338 void
|
|
339 parse_clue_phrases()
|
|
340 {
|
|
341 char *s;
|
|
342 int size;
|
|
343
|
|
344 if (phrases)
|
|
345 return;
|
|
346
|
|
347 phrases = (char **) malloc(sizeof(*phrases) * (size = 20));
|
|
348
|
|
349 for (s = cluephrase_storage; *s; s += strlen(s) + 1)
|
|
350 {
|
|
351 phrases[num_phrases] = s;
|
|
352 num_phrases++;
|
|
353 if (num_phrases >= size)
|
|
354 phrases = (char **) realloc(phrases, sizeof(*phrases) * (size *= 2));
|
|
355 }
|
|
356
|
|
357 phrases = (char **) realloc(phrases, sizeof(*phrases) * num_phrases);
|
|
358 }
|
|
359
|
|
360 /**********************************************************************/
|
|
361
|
|
362
|
|
363 #define BERATE(msg) pmessage( (msg), me->p_no, MINDIV, " CC")
|
|
364
|
|
365 /* print the message that tells the person how to respond to the clue check */
|
|
366 void
|
|
367 remind_cluecheck()
|
|
368 {
|
|
369 char buf[120];
|
|
370 BERATE("This is a clue check! You must send yourself the message");
|
|
371 BERATE(" cluecheck [phrase]");
|
|
372 if (page >= 0)
|
|
373 {
|
|
374 sprintf(buf, "where [phrase] is the %s word on page %d of the MOTD.",
|
|
375 isfirst ? "first" : "last", page + 1);
|
|
376 }
|
|
377 else
|
|
378 {
|
|
379 /* man, the MOTD had no good words */
|
|
380 sprintf(buf, "where [phrase] is %s", clueword);
|
|
381 }
|
|
382 BERATE(buf);
|
|
383 if (me->p_cluecountdown > 60)
|
|
384 sprintf(buf, "If you don't answer within %g minutes, you will be kicked out of", me->p_cluecountdown / (60.0 * 10));
|
|
385 else
|
|
386 sprintf(buf, "If you don't answer within %d seconds, you will be kicked out of", me->p_cluecountdown / 10);
|
|
387 BERATE(buf);
|
|
388 BERATE("the game and publicly humiliated.");
|
|
389 #if 0
|
|
390 BERATE("If you are a complete newbie, then");
|
|
391 BERATE("you probably don't even realize that you can read the MOTD while");
|
|
392 BERATE("playing (shift-M).");
|
|
393 #endif
|
|
394 }
|
|
395
|
|
396 /*
|
|
397 * if other methods of getting clue words fail, then we've always got this
|
|
398 * list of words
|
|
399 */
|
|
400 static char *fallback_cluewords[] = {
|
|
401
|
|
402 /* terms: */
|
|
403 "bomb", "ogg", "scum", "stoneage", "scout", "taxi", "base",
|
|
404 "buttorp", "flee", "planet", "star", "warp", "impulse", "hive",
|
|
405 "repair", "shipyard", "fuel", "arable", "metal", "dilithium",
|
|
406 "standard", "thin", "tainted", "toxic", "phaser", "torp", "photon",
|
|
407 "plasma", "missile", "fighter", "tractor", "pressor",
|
|
408
|
|
409 /* what quarks are made of: */
|
|
410 "satan", "beer", "jesus", "sex", "cthulhu",
|
|
411
|
|
412 /* two food groups: */
|
|
413 /* "grilledcheesesandwich", annoyed too many people */ "ketchup", "caffeine",
|
|
414
|
|
415 /* the men: */
|
|
416 /* "a fungusamongus", people have difficulty with this one */
|
|
417 "Bubbles", "Hammor", "Key", "Kaos", "Lynx",
|
|
418 "Thought", "Brazilian", "Ogre",
|
|
419
|
|
420 /* the big five: */
|
|
421 "Paradise", "Arctica", "Aedile", "Eden", "Minuet",
|
|
422
|
|
423 /* what you are: */
|
|
424 "twink"
|
|
425 };
|
|
426
|
|
427 #define NUM_CLUEWORDS ( sizeof(fallback_cluewords) \
|
|
428 / sizeof(*fallback_cluewords))
|
|
429
|
|
430 /*
|
|
431 * Once in a great while (hour?) the server demands a clue check from the
|
|
432 * player. This makes sure you are paying attention.
|
|
433 */
|
|
434 void
|
|
435 demand_clue()
|
|
436 {
|
|
437 clueword[0] = 0;
|
|
438 page = -1;
|
|
439 switch (configvals->cluesource)
|
|
440 {
|
|
441 case CC_MOTD:
|
|
442 #ifdef MOTD_SUPPORT
|
|
443 parse_motd();
|
|
444
|
|
445 find_suitable_motd_word();
|
|
446 #endif
|
|
447 break;
|
|
448 case CC_PHRASE_LIST_FILE:
|
|
449 parse_clue_phrases();
|
|
450
|
|
451 if (num_phrases)
|
|
452 {
|
|
453 set_clue_word(phrases[lrand48() % num_phrases]);
|
|
454 }
|
|
455 break; /* uh, NYI */
|
|
456 case CC_COMPILED_IN_PHRASE_LIST:
|
|
457 break; /* that's actually the fallback case below: */
|
|
458 }
|
|
459 if (*clueword == 0) /* didn't find one! */
|
|
460 set_clue_word(fallback_cluewords[lrand48() % NUM_CLUEWORDS]);
|
|
461
|
|
462 me->p_cluecountdown = configvals->cluetime * TICKSPERSEC;
|
|
463
|
|
464 remind_cluecheck();
|
|
465 }
|
|
466
|
|
467 /* every tick, check the person's clue status */
|
|
468 void
|
|
469 countdown_clue()
|
|
470 {
|
|
471 if (me->p_status == POUTFIT || me->p_status == PTQUEUE)
|
|
472 return;
|
|
473 if (me->p_cluedelay > 0)
|
|
474 {
|
|
475 me->p_cluedelay--;
|
|
476 if (me->p_cluedelay < 1
|
|
477 && (me->p_stats.st_cluesuccess < 25
|
|
478 || lrand48() % 20 < 1))
|
|
479 {
|
|
480 /* uhoh, time for another cluecheck */
|
|
481 demand_clue();
|
|
482 }
|
|
483 }
|
|
484 else if (me->p_cluecountdown > 0)
|
|
485 {
|
|
486 char buf[120];
|
|
487
|
|
488 /* under the gun here */
|
|
489 me->p_cluecountdown--;
|
|
490 if (me->p_cluecountdown > 0)
|
|
491 return;
|
|
492
|
|
493 /* uhoh, we have a twink */
|
|
494
|
|
495 me->p_status = PEXPLODE;
|
|
496 me->p_explode = 10;
|
|
497 me->p_whydead = KQUIT;
|
|
498
|
|
499 sprintf(buf, "%s (%s) was blasted out of existence due to terminal",
|
|
500 me->p_name, twoletters(me));
|
|
501 pmessage(buf, -1, MALL, MSERVA);
|
|
502 pmessage("stupidity (failure to read messages).", -1, MALL, MSERVA);
|
|
503 pmessage("Let this be a lesson to the rest of you twinks!", -1, MALL, MSERVA);
|
|
504 }
|
|
505 else
|
|
506 {
|
|
507 me->p_cluedelay = 40;
|
|
508 }
|
|
509 }
|
|
510
|
|
511 /* the person sent themselves the message "cluecheck..." */
|
|
512 int
|
|
513 accept_cluecheck(word)
|
|
514 char *word;
|
|
515 {
|
|
516 int i;
|
|
517 char buf[120];
|
|
518
|
|
519 if (me->p_cluedelay > 0)
|
|
520 {
|
|
521 sprintf(buf, "Don't worry %s. You aren't under a clue check yet.",
|
|
522 me->p_name);
|
|
523 BERATE(buf);
|
|
524 }
|
|
525 else if (*word)
|
|
526 {
|
|
527 for (i = 0; word[i] && clueword[i]; i++)
|
|
528 {
|
|
529 if (tolower(word[i]) != tolower(clueword[i]))
|
|
530 break;
|
|
531 }
|
|
532
|
|
533 if (word[i] || clueword[i])
|
|
534 {
|
|
535 sprintf(buf, "Nice try, %s. Guess again. It's not %s.",
|
|
536 me->p_name, word);
|
|
537 BERATE(buf);
|
|
538 BERATE("Send yourself the message `cluecheck' if you need another hint.");
|
|
539 }
|
|
540 else
|
|
541 {
|
|
542 sprintf(buf, "Good show, %s. I won't bother you again for a while.",
|
|
543 me->p_name);
|
|
544 BERATE(buf);
|
|
545 me->p_cluedelay = (configvals->cluedelay / 2) +
|
|
546 lrand48() % (configvals->cluedelay / 2);
|
|
547 me->p_cluedelay *= TICKSPERSEC;
|
|
548
|
|
549 me->p_stats.st_cluesuccess++;
|
|
550 }
|
|
551 }
|
|
552 else
|
|
553 {
|
|
554 remind_cluecheck();
|
|
555 }
|
|
556 return 1;
|
|
557 }
|
|
558
|
|
559 /**********************************************************************/
|
|
560
|
|
561 #ifdef MOTD_SUPPORT
|
|
562 void
|
|
563 free_word(wd)
|
|
564 struct word *wd;
|
|
565 {
|
|
566 free(wd->s);
|
|
567 }
|
|
568
|
|
569 void
|
|
570 free_line(ln)
|
|
571 struct line *ln;
|
|
572 {
|
|
573 int i;
|
|
574 for (i = 0; i < ln->nwords; i++)
|
|
575 free_word(&ln->words[i]);
|
|
576 free(ln->words);
|
|
577 }
|
|
578
|
|
579 void
|
|
580 free_page(pg)
|
|
581 struct page *pg;
|
|
582 {
|
|
583 int i;
|
|
584 for (i = 0; i < LINESPERPAGE; i++)
|
|
585 {
|
|
586 free_line(&pg->lines[i]);
|
|
587 }
|
|
588 }
|
|
589
|
|
590 void
|
|
591 free_motdstruct()
|
|
592 {
|
|
593 struct page *temp;
|
|
594 while (motdhead)
|
|
595 {
|
|
596 temp = motdhead;
|
|
597 motdhead = temp->next;
|
|
598
|
|
599 free_page(temp);
|
|
600 free(temp);
|
|
601 }
|
|
602 }
|
|
603 #endif
|
|
604
|
|
605 #endif /* CLUECHECK1 */
|
|
606
|
|
607 #ifdef CLUECHECK2
|
|
608
|
|
609 /* ---------[ CLUECHECK2 -> Brandons hacked version of CLUECHECK1 ]--------- */
|
|
610
|
|
611 /*
|
|
612 * // I munged this (sorry Rob). Using me->p_cluecountdown: // if it is
|
|
613 * 0 you have not been checked yet // if it is 1 your time is up. //
|
|
614 * if it is -1 you should not be checked. // if it is anything greater
|
|
615 * than one you are under the timer
|
|
616 */
|
|
617
|
|
618 /* -------------------------[ Globals (eep) ]------------------------- */
|
|
619
|
|
620 #define TellLINE { pmessage("", me->p_no, MINDIV, "***! Cluecheck !**! Cluecheck !**! Cluecheck !**! Cluecheck !**! Cluecheck !***"); }
|
|
621
|
|
622 #define NUM_CLUEWORDS (sizeof(fallback_cluewords) / \
|
|
623 sizeof(*fallback_cluewords))
|
|
624 #define CLUE_GETOUTOFIT 7
|
|
625
|
|
626 char **phrases = 0;
|
|
627 int num_phrases = 0;
|
|
628 static char clueword[40];
|
|
629
|
|
630 /*
|
|
631 * // if other methods of getting clue words fail, then we've always got //
|
|
632 * this list of words
|
|
633 */
|
|
634
|
|
635 static char *fallback_cluewords[] = {
|
|
636 /* make it simple, if they want more they can make a .cluecheck file */
|
|
637 "bomb", "ogg", "scum", "stoneage", "scout", "taxi", "base",
|
|
638 "buttorp", "flee", "planet", "star", "warp", "impulse", "hive",
|
|
639 "repair", "shipyard", "fuel", "arable", "metal", "dilithium",
|
|
640 "standard", "thin", "tainted", "toxic", "phaser", "torp", "photon",
|
|
641 "plasma", "missile", "fighter", "tractor", "pressor",
|
|
642 };
|
|
643
|
|
644 /* -------------------------[ Functions ]------------------------- */
|
|
645
|
|
646 void
|
|
647 set_clue_word(char *word)
|
|
648 {
|
|
649 strncpy(clueword, word, sizeof(clueword));
|
|
650 clueword[sizeof(clueword) - 1] = 0;
|
|
651 }
|
|
652
|
|
653 void
|
|
654 parse_clue_phrases()
|
|
655 {
|
|
656 char *s;
|
|
657 int size;
|
|
658
|
|
659 if (phrases)
|
|
660 return;
|
|
661
|
|
662 phrases = (char **) malloc(sizeof(*phrases) * (size = 20));
|
|
663
|
|
664 for (s = cluephrase_storage; *s; s += strlen(s) + 1)
|
|
665 {
|
|
666 phrases[num_phrases] = s;
|
|
667 num_phrases++;
|
|
668 if (num_phrases >= size)
|
|
669 phrases = (char **) realloc(phrases, sizeof(*phrases) * (size *= 2));
|
|
670 }
|
|
671
|
|
672 phrases = (char **) realloc(phrases, sizeof(*phrases) * num_phrases);
|
|
673 }
|
|
674
|
|
675 /*
|
|
676 * // print the message that tells the person how to respond to the clue
|
|
677 * check
|
|
678 */
|
|
679 void
|
|
680 remind_cluecheck()
|
|
681 {
|
|
682 char buf[120];
|
|
683
|
|
684 pmessage("", me->p_no, MINDIV, "*******************************************************************************");
|
|
685 TellLINE;
|
|
686 sprintf(buf, " Send yourself: \"cluecheck %s\"", clueword);
|
|
687 pmessage(buf, me->p_no, MINDIV, "");
|
|
688
|
|
689 if (me->p_cluecountdown > (60 * TICKSPERSEC))
|
|
690 {
|
|
691 sprintf(buf,
|
|
692 " Answer within %.2g minutes or be ejected from the game.",
|
|
693 (me->p_cluecountdown / (60.0 * TICKSPERSEC)));
|
|
694 pmessage(buf, me->p_no, MINDIV, "");
|
|
695 }
|
|
696 else
|
|
697 {
|
|
698 sprintf(buf,
|
|
699 "** ANSWER ** within %d seconds or be ejected from the game.",
|
|
700 (me->p_cluecountdown / 10));
|
|
701 pmessage(buf, me->p_no, MINDIV, "");
|
|
702 }
|
|
703 pmessage("", me->p_no, MINDIV, "*******************************************************************************");
|
|
704
|
|
705 }
|
|
706
|
|
707 /* called the first time */
|
|
708 void
|
|
709 demand_clue()
|
|
710 {
|
|
711 char buf[255];
|
|
712 char syou[32];
|
|
713 clueword[0] = 0;
|
|
714
|
|
715 sprintf(syou, "%s->YOU", SERVNAME);
|
|
716 /* higher than rank CLUE_GETOUTOFIT get ... out of it */
|
|
717 if (me->p_stats.st_rank > CLUE_GETOUTOFIT /* if my rank is high enough */
|
|
718 || me->p_stats.st_royal == GODLIKE + 1 /* or I'm Q */ )
|
|
719 {
|
|
720 TellLINE;
|
|
721 pmessage("Due to your ranking status, I will let you off the hook.",
|
|
722 me->p_no, MINDIV, syou);
|
|
723 me->p_cluecountdown = -1;
|
|
724 return;
|
|
725 }
|
|
726 else if (me->p_stats.st_cluesuccess > configvals->cluecheck)
|
|
727 {
|
|
728 TellLINE;
|
|
729 sprintf(buf, "You have passed the cluecheck the required %d times.",
|
|
730 configvals->cluecheck);
|
|
731 pmessage(buf, me->p_no, MINDIV, syou);
|
|
732 me->p_cluecountdown = -1;
|
|
733 return;
|
|
734 }
|
|
735
|
|
736 parse_clue_phrases();
|
|
737
|
|
738 if (num_phrases)
|
|
739 set_clue_word(phrases[lrand48() % num_phrases]);
|
|
740 if (*clueword == 0) /* didn't find one! */
|
|
741 set_clue_word(fallback_cluewords[lrand48() % NUM_CLUEWORDS]);
|
|
742 me->p_cluecountdown = configvals->cluetime * TICKSPERSEC;
|
|
743
|
|
744 remind_cluecheck();
|
|
745 }
|
|
746
|
|
747
|
|
748 /* every tick, check the person's clue status */
|
|
749 void
|
|
750 countdown_clue()
|
|
751 {
|
|
752 if (me->p_cluecountdown != -1)
|
|
753 {
|
|
754 if (me->p_status == POUTFIT
|
|
755 || me->p_status == PTQUEUE
|
|
756 || me->p_status == POBSERVE)
|
|
757 return;
|
|
758
|
|
759 /* let bases off the hook */
|
|
760 if (me->p_ship.s_type == 5 || me->p_ship.s_type == 9)
|
|
761 return;
|
|
762
|
|
763 if (me->p_cluedelay > 0)
|
|
764 {
|
|
765 me->p_cluedelay--;
|
|
766 return;
|
|
767 }
|
|
768
|
|
769 /* is it greater than one? */
|
|
770 if (me->p_cluecountdown > 0)
|
|
771 {
|
|
772 char buf[255];
|
|
773
|
|
774 /* under the gun here */
|
|
775 me->p_cluecountdown--;
|
|
776
|
|
777 if (me->p_cluecountdown == 150 * TICKSPERSEC
|
|
778 || me->p_cluecountdown == 60 * TICKSPERSEC
|
|
779 || me->p_cluecountdown == 10 * TICKSPERSEC)
|
|
780 {
|
|
781 remind_cluecheck();
|
|
782 return;
|
|
783 }
|
|
784
|
|
785 /* is it still greater than 1? */
|
|
786 else if (me->p_cluecountdown > 0)
|
|
787 return;
|
|
788
|
|
789 /* uhoh, we have a twink */
|
|
790 me->p_status = PEXPLODE;
|
|
791 me->p_explode = 10;
|
|
792 me->p_whydead = KQUIT;
|
|
793 me->p_cluecountdown = -1;
|
|
794
|
|
795 sprintf(buf, "%s (%s) was ejected for failing a cluecheck.",
|
|
796 me->p_name, twoletters(me));
|
|
797 pmessage(buf, SERVNAME, MALL, " ** CLUECHECK **");
|
|
798
|
|
799 #ifdef MAIL_CLUELETTER
|
|
800 sprintf(buf, "%s %s %s", build_path(MAILCLUECHECK),
|
|
801 me->p_login, me->p_full_hostname);
|
|
802 system(buf);
|
|
803 #endif
|
|
804 }
|
|
805 else
|
|
806 {
|
|
807 /*
|
|
808 * they aren't -1, they are greater than 1, so they havn't been checked
|
|
809 * yet
|
|
810 */
|
|
811 demand_clue();
|
|
812 }
|
|
813 }
|
|
814 }
|
|
815
|
|
816
|
|
817 /*
|
|
818 * // the person sent themselves the message "cluecheck..." // called in
|
|
819 * controls (message.c)
|
|
820 */
|
|
821 int
|
|
822 accept_cluecheck(char *word)
|
|
823 {
|
|
824 int i;
|
|
825 char buf[120];
|
|
826 char syou[32];
|
|
827
|
|
828 sprintf(syou, "%s->YOU", SERVNAME);
|
|
829 if (me->p_cluecountdown == -1 || !me->p_cluecountdown)
|
|
830 {
|
|
831 pmessage("You are not under a cluecheck.",
|
|
832 me->p_no, MINDIV, syou);
|
|
833 return;
|
|
834 }
|
|
835 else if (*word)
|
|
836 {
|
|
837 for (i = 0; word[i] && clueword[i]; i++)
|
|
838 {
|
|
839 if (tolower(word[i]) != tolower(clueword[i]))
|
|
840 break;
|
|
841 }
|
|
842
|
|
843 if (word[i] || clueword[i])
|
|
844 {
|
|
845 sprintf(buf, "Nice try, guess again. It is not \"%s\".", word);
|
|
846 pmessage(buf, me->p_no, MINDIV, syou);
|
|
847 pmessage(
|
|
848 "Send the message \"cluecheck\" to yourself for another hint.",
|
|
849 me->p_no, MINDIV, syou);
|
|
850 }
|
|
851 else
|
|
852 {
|
|
853 sprintf(buf,
|
|
854 "Good show %s. I won't bother you again for a while.",
|
|
855 me->p_name);
|
|
856 pmessage(buf, me->p_no, MINDIV, syou);
|
|
857 me->p_stats.st_cluesuccess++;
|
|
858 me->p_cluecountdown = -1;
|
|
859 }
|
|
860 }
|
|
861 else
|
|
862 {
|
|
863 remind_cluecheck();
|
|
864 }
|
|
865 sprintf(buf, "You have passed the cluecheck %d times.",
|
|
866 me->p_stats.st_cluesuccess);
|
|
867 pmessage(buf, me->p_no, MINDIV, syou);
|
|
868 return 1;
|
|
869 }
|
|
870
|
|
871 #endif /* CLUECHECK2 */
|