6
|
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 char binary[] = "@(#)robotII";
|
|
20
|
|
21 #include "config.h"
|
|
22
|
|
23 #include <stdio.h>
|
|
24 #include <sys/types.h>
|
|
25 #include <sys/time.h>
|
|
26 #include <sys/stat.h>
|
|
27 #include <sys/file.h>
|
|
28 #ifndef ULTRIX
|
|
29 #include <sys/fcntl.h>
|
|
30 #endif
|
|
31 #include <signal.h>
|
|
32 #include <setjmp.h>
|
|
33 #include <errno.h>
|
|
34 #include "defs.h"
|
|
35 #include "struct.h"
|
|
36 #include "data.h"
|
|
37 #include "shmem.h"
|
|
38
|
|
39 extern void (*r_signal()) ();
|
|
40
|
|
41 void config();
|
|
42
|
|
43 struct itimerval udt;
|
|
44 extern int redrawall; /* maint: missing "extern" 6/22/92 TC */
|
|
45 extern int lastm; /* maint: missing "extern" 6/22/92 TC */
|
|
46
|
|
47 /* This lets you specify which ships a robot is allowed to choose */
|
|
48 int robotships[NUM_TYPES] = {
|
|
49 1, /* SCOUT */
|
|
50 1, /* DESTROYER */
|
|
51 1, /* CRUISER */
|
|
52 1, /* BATTLESHIP */
|
|
53 1, /* ASSAULT */
|
|
54 0, /* STARBASE */
|
|
55 0, /* ATT */
|
|
56 0, /* JUMPSHIP */
|
|
57 1, /* FRIGATE */
|
|
58 0, /* WARBASE */
|
|
59 1, /* LIGHTCRUISER */
|
|
60 0, /* CARRIER */
|
|
61 0, /* UTILITY */
|
|
62 1 /* PATROL */
|
|
63 };
|
|
64
|
|
65 /* lots of neat flags */
|
|
66 int hostile;
|
|
67 int debug;
|
|
68 int level;
|
|
69 int fleet;
|
|
70 int sticky;
|
|
71 int berserk;
|
|
72 int practice;
|
|
73 int nofuel;
|
|
74
|
|
75 int polymorphic; /* match opponent's ship class 8/15/91 TC */
|
|
76 int target; /* Terminator's target 7/27/91 TC */
|
|
77 int phrange; /* phaser range 7/31/91 TC */
|
|
78 int trrange; /* tractor range 8/2/91 TC */
|
|
79
|
|
80 int startplanet = -1; /* CRD feature - MAK, 2-Jun-93 */
|
|
81
|
|
82 /* velocities 8/9/91 TC */
|
|
83
|
|
84 int dogslow; /* dodge speed (hard turn) */
|
|
85 int dogfast; /* dodge speed (soft turn) */
|
|
86 int runslow; /* run speed (flat etemp) */
|
|
87 int runfast; /* run speed (gain etemp) */
|
|
88 int closeslow; /* approach speed (hard turn) */
|
|
89 int closefast; /* approach speed (soft turn) */
|
|
90
|
|
91 char *rnames[6] = {"M5", "Colossus", "Guardian", "HAL", "DreadPirate Bob",
|
|
92 "TERMINATOR"};
|
|
93
|
|
94 #ifdef ROBOTSTATS
|
|
95 void
|
|
96 do_robot_login()
|
|
97 {
|
|
98 int plfd, position, entries, i;
|
|
99 char *path;
|
|
100 struct statentry player;
|
|
101 struct stat buf;
|
|
102
|
|
103 path = build_path(PLAYERFILE);
|
|
104 plfd = open(path, O_RDONLY, 0);
|
|
105 if (plfd < 0)
|
|
106 {
|
|
107 fprintf(stderr, "%s: I cannot open the player file! (errno: %d)\n",
|
|
108 argv0, errno);
|
|
109 me->p_pos = -1;
|
|
110 return;
|
|
111 }
|
|
112 position = 0;
|
|
113 while (read(plfd, (char *) &player, sizeof(struct statentry)) ==
|
|
114 sizeof(struct statentry))
|
|
115 {
|
|
116 if (!strcmp(pseudo, player.name))
|
|
117 {
|
|
118 close(plfd);
|
|
119 me->p_pos = position;
|
|
120 memcpy(&(me->p_stats), &player.stats, sizeof(struct stats));
|
|
121 return;
|
|
122 }
|
|
123 position++;
|
|
124 }
|
|
125 /* Not in there, so create it */
|
|
126 strcpy(player.name, pseudo);
|
|
127 strcpy(player.password, "*"); /* an invalid password to prevent logins */
|
|
128 memset(&player.stats, 0, sizeof(struct stats));
|
|
129 player.stats.st_tticks = 1;
|
|
130 player.stats.st_flags = ST_INITIAL;
|
|
131
|
|
132 plfd = open(path, O_RDWR | O_CREAT, 0644);
|
|
133 if (plfd < 0)
|
|
134 {
|
|
135 fprintf(stderr, "%s: I cannot open the player file! (errno: %d)\n",
|
|
136 argv0, errno);
|
|
137 me->p_pos = -1;
|
|
138 return;
|
|
139 }
|
|
140 else
|
|
141 {
|
|
142 fstat(plfd, &buf);
|
|
143 entries = buf.st_size / sizeof(struct statentry);
|
|
144 lseek(plfd, entries * sizeof(struct statentry), 0);
|
|
145 write(plfd, (char *) &player, sizeof(struct statentry));
|
|
146 close(plfd);
|
|
147 me->p_pos = entries;
|
|
148 memcpy(&(me->p_stats), &player.stats, sizeof(struct stats));
|
|
149 }
|
|
150 }
|
|
151
|
|
152 void
|
|
153 save_robot()
|
|
154 {
|
|
155 int fd;
|
|
156 char *path;
|
|
157
|
|
158 if (me->p_pos < 0)
|
|
159 return;
|
|
160 path = build_path(PLAYERFILE);
|
|
161 fd = open(path, O_WRONLY, 0644);
|
|
162 if (fd >= 0)
|
|
163 {
|
|
164 me->p_stats.st_lastlogin = time(NULL);
|
|
165 lseek(fd, 32 + me->p_pos * sizeof(struct statentry), 0);
|
|
166 write(fd, (char *) &me->p_stats, sizeof(struct stats));
|
|
167 close(fd);
|
|
168 }
|
|
169 }
|
|
170 #endif
|
|
171
|
|
172 int
|
|
173 main(argc, argv)
|
|
174 int argc;
|
|
175 char **argv;
|
|
176 {
|
|
177 register int i;
|
|
178 int rmove();
|
|
179 int team = -1;
|
|
180 int bteam;
|
|
181 int pno;
|
|
182 int class; /* ship class 8/9/91 TC */
|
|
183
|
|
184 argv0 = argv[0];
|
|
185 srand48(time(NULL) + getpid());
|
|
186
|
|
187 openmem(0, 0);
|
|
188
|
|
189 for (;;)
|
|
190 {
|
|
191 class = lrand48() % NUM_TYPES; /* pick a ship type */
|
|
192 if (robotships[class] && shipsallowed[class])
|
|
193 break;
|
|
194 }
|
|
195
|
|
196 target = -1; /* no target 7/27/91 TC */
|
|
197 for (; argc > 1 && argv[1][0] == '-'; argc--, argv++)
|
|
198 {
|
|
199 switch (argv[1][1])
|
|
200 {
|
|
201 case 'S':
|
|
202 startplanet = atoi(&argv[1][2]);
|
|
203 if (startplanet >= configvals->numplanets)
|
|
204 {
|
|
205 printf("startplanet insane: %d\n", startplanet);
|
|
206 startplanet = -1;
|
|
207 }
|
|
208 break;
|
|
209 case 'F':
|
|
210 nofuel++;
|
|
211 break;
|
|
212 case 'P':
|
|
213 polymorphic++;
|
|
214 break;
|
|
215 case 'f':
|
|
216 fleet++;
|
|
217 break;
|
|
218 case 's':
|
|
219 sticky++;
|
|
220 break;
|
|
221 case 'd':
|
|
222 debug++;
|
|
223 break;
|
|
224 case 'h':
|
|
225 hostile++;
|
|
226 break;
|
|
227 case 'p':
|
|
228 practice++;
|
|
229 break;
|
|
230 case 'b':
|
|
231 berserk++;
|
|
232 break;
|
|
233 case 'l':
|
|
234 if (argv[1][2] != '\0')
|
|
235 level = atoi(&argv[1][2]);
|
|
236 else
|
|
237 level = 100;
|
|
238 break;
|
|
239 case 'c': /* ship class */
|
|
240 {
|
|
241 char cstr[NUM_TYPES + 1];
|
|
242
|
|
243 for (class = 0; class <= NUM_TYPES; class++)
|
|
244 {
|
|
245 if (class == NUM_TYPES)
|
|
246 {
|
|
247 cstr[NUM_TYPES] = 0;
|
|
248 fprintf(stderr, "Unknown ship class, must be one of [%s].\n", cstr);
|
|
249 exit(1);
|
|
250 }
|
|
251 if (argv[1][2] == shipvals[class].s_letter)
|
|
252 break;
|
|
253 cstr[class] = shipvals[class].s_letter;
|
|
254 }
|
|
255 }
|
|
256 break;
|
|
257 case 'T': /* team */
|
|
258 switch (argv[1][2])
|
|
259 {
|
|
260 case 'f':
|
|
261 team = 0;
|
|
262 bteam = FED;
|
|
263 break;
|
|
264 case 'r':
|
|
265 team = 1;
|
|
266 bteam = ROM;
|
|
267 break;
|
|
268 case 'k':
|
|
269 team = 2;
|
|
270 bteam = KLI;
|
|
271 break;
|
|
272 case 'o':
|
|
273 team = 3;
|
|
274 bteam = ORI;
|
|
275 break;
|
|
276 case 'n': /* change 5/10/91 TC neutral */
|
|
277 case 'i':
|
|
278 team = 4;
|
|
279 bteam = FED | ROM | KLI | ORI; /* don't like anybody */
|
|
280 break;
|
|
281 case 't':
|
|
282 {
|
|
283 char c;
|
|
284 c = argv[1][3];
|
|
285
|
|
286 team = 5;
|
|
287 bteam = FED | ROM | KLI | ORI; /* don't like anybody */
|
|
288 target = -1;
|
|
289 if (c == '\0')
|
|
290 {
|
|
291 fprintf(stderr, "Must specify target. e.g. -Tt3.\n");
|
|
292 exit(1);
|
|
293 }
|
|
294 if ((c >= '0') && (c <= '9'))
|
|
295 target = c - '0';
|
|
296 else if ((c >= 'a') && (c <= 'v'))
|
|
297 target = c - 'a' + 10;
|
|
298 else
|
|
299 {
|
|
300 fprintf(stderr, "Must specify target. e.g. -Tt3.\n");
|
|
301 exit(1);
|
|
302 }
|
|
303 } /* end case 't' */
|
|
304 break;
|
|
305 default:
|
|
306 fprintf(stderr, "Unknown team type. Usage -Tx where x is [frko]\n");
|
|
307 exit(1);
|
|
308 } /* end switch argv */
|
|
309 break;
|
|
310 default:
|
|
311 fprintf(stderr, "Unknown option '%c' (must be one of: bcdfpsFPT)\n", argv[1][1]);
|
|
312 exit(1);
|
|
313 } /* end switch argv[1][1] */
|
|
314
|
|
315
|
|
316 } /* end for */
|
|
317
|
|
318 if (team < 0 || team >= 6)
|
|
319 { /* change 7/27/91 TC was 4 now 6 */
|
|
320 if (debug)
|
|
321 fprintf(stderr, "Choosing random team.\n");
|
|
322 team = lrand48() % 4;
|
|
323 }
|
|
324
|
|
325 pno = findrslot(); /* Robots are entitled to tester's slots. */
|
|
326 me = &players[pno];
|
|
327 me->p_no = pno;
|
|
328 myship = &me->p_ship;
|
|
329 mystats = &me->p_stats;
|
|
330 lastm = mctl->mc_current;
|
|
331
|
|
332 /*
|
|
333 * At this point we have memory set up. If we aren't a fleet, we don't
|
|
334 * want to replace any other robots on this team, so we'll check the other
|
|
335 * players and get out if there are any on our team.
|
|
336 */
|
|
337
|
|
338 if (practice)
|
|
339 {
|
|
340 strcpy(pseudo, "Hozer");
|
|
341 }
|
|
342 else
|
|
343 {
|
|
344 strcpy(pseudo, rnames[team]);
|
|
345 }
|
|
346 strcpy(login, "Robot");
|
|
347
|
|
348 (void) strncpy(me->p_login, login, sizeof(me->p_login));
|
|
349 me->p_login[sizeof(me->p_login) - 1] = '\0';
|
|
350 (void) strncpy(me->p_monitor, "Nowhere", sizeof(me->p_monitor));
|
|
351 me->p_monitor[sizeof(me->p_monitor) - 1] = '\0';
|
|
352
|
|
353 /* repeat "Nowhere" for completeness 4/13/92 TC */
|
|
354 (void) strncpy(me->p_full_hostname, "Nowhere", sizeof(me->p_full_hostname));
|
|
355 me->p_full_hostname[sizeof(me->p_full_hostname) - 1] = '\0';
|
|
356
|
|
357 if (target >= 0)
|
|
358 { /* hack 7/27/91 TC */
|
|
359 enter(team, target, pno, class, startplanet);
|
|
360 startplanet = -1; /* Termies should forget about startplanet */
|
|
361 }
|
|
362 else
|
|
363 startplanet = enter(team, 0, pno, class, startplanet);
|
|
364
|
|
365 #ifdef ROBOTSTATS
|
|
366 do_robot_login();
|
|
367 #else
|
|
368 me->p_pos = -1; /* So robot stats don't get saved */
|
|
369 #endif
|
|
370
|
|
371 me->p_flags |= PFROBOT; /* Mark as a robot */
|
|
372 if ((berserk) || (team == 4)) /* indeps are hostile */
|
|
373 me->p_hostile = (FED | ROM | KLI | ORI); /* unless they are berserk */
|
|
374 else if (team == 5)
|
|
375 me->p_hostile = 0; /* Termies declare war later */
|
|
376 else if (practice)
|
|
377 me->p_hostile = bteam; /* or practice */
|
|
378 else
|
|
379 me->p_hostile = 0; /* robots are peaceful */
|
|
380
|
|
381 if (practice)
|
|
382 me->p_flags |= PFPRACTR; /* Mark as a practice robot */
|
|
383 r_signal(SIGALRM, rmove);
|
|
384
|
|
385 config();
|
|
386 if (practice)
|
|
387 {
|
|
388 udt.it_interval.tv_sec = 1; /* Robots get to move 1/sec */
|
|
389 udt.it_interval.tv_usec = 000000;
|
|
390 }
|
|
391 else
|
|
392 {
|
|
393 udt.it_interval.tv_sec = 0; /* Robots get to move 2/sec */
|
|
394 udt.it_interval.tv_usec = 500000;
|
|
395 }
|
|
396 udt.it_value.tv_sec = 1;
|
|
397 udt.it_value.tv_usec = 0;
|
|
398 if (setitimer(ITIMER_REAL, &udt, 0) < 0)
|
|
399 {
|
|
400 perror("setitimer");
|
|
401 me->p_status = PFREE; /* Put robot in game */
|
|
402 move_player(me->p_no, -1, -1, 1);
|
|
403 exit(1);
|
|
404 }
|
|
405 /* allows robots to be forked by the daemon -- Evil ultrix bullshit */
|
|
406 #ifndef SVR4
|
|
407 sigsetmask(0);
|
|
408 #endif /* SVR4 */
|
|
409
|
|
410 if (team == 4)
|
|
411 {
|
|
412 int count = 0;
|
|
413 for (i = 0; i < MAXPLAYER; i++)
|
|
414 {
|
|
415 if (players[i].p_status == PALIVE)
|
|
416 count++;
|
|
417 }
|
|
418 if (((count <= 1) && (!fleet)) ||
|
|
419 ((count < 1) && (fleet)))
|
|
420 { /* if one or less players, don't show */
|
|
421 if (debug)
|
|
422 fprintf(stderr, "No one to hoze.\n");
|
|
423 players[pno].p_status = PFREE;
|
|
424 move_player(me->p_no, -1, -1, 1);
|
|
425 exit(1);
|
|
426 }
|
|
427 }
|
|
428 if (!fleet)
|
|
429 {
|
|
430 for (i = 0; i < MAXPLAYER; i++)
|
|
431 {
|
|
432 if ((players[i].p_status == PALIVE) && (players[i].p_team == bteam))
|
|
433 {
|
|
434 if (debug)
|
|
435 fprintf(stderr, "Galaxy already defended\n");
|
|
436 players[pno].p_status = PFREE;
|
|
437 move_player(me->p_no, -1, -1, 1);
|
|
438 exit(1);
|
|
439 }
|
|
440 }
|
|
441 }
|
|
442 me->p_status = PALIVE; /* Put robot in game */
|
|
443 while (1)
|
|
444 {
|
|
445 pause();
|
|
446 }
|
|
447 return 0;
|
|
448 }
|
|
449
|
|
450 int
|
|
451 findrslot()
|
|
452 {
|
|
453 register int i;
|
|
454
|
|
455 #if 0
|
|
456 for (i = 0; i < MAXPLAYER; i++)
|
|
457 #else
|
|
458 for (i = MAXPLAYER - 1; i >= 0; i--)
|
|
459 #endif
|
|
460 {
|
|
461 /* reverse entry..let's be trendy 4/6/92 TC */
|
|
462 if (players[i].p_status == PFREE)
|
|
463 { /* We have a free slot */
|
|
464 players[i].p_status = POUTFIT; /* possible race code */
|
|
465 break;
|
|
466 }
|
|
467 }
|
|
468 if ((i == MAXPLAYER) || (i == -1))
|
|
469 {
|
|
470 if (debug)
|
|
471 {
|
|
472 fprintf(stderr, "No more room in game\n");
|
|
473 }
|
|
474 exit(0);
|
|
475 }
|
|
476 memset(&players[i].p_stats, 0, sizeof(struct stats));
|
|
477 players[i].p_stats.st_tticks = 1;
|
|
478 return (i);
|
|
479 }
|
|
480
|
|
481 void
|
|
482 warning(mess)
|
|
483 char *mess;
|
|
484 {
|
|
485 if (debug)
|
|
486 fprintf(stderr, "warning: %s\n", mess);
|
|
487 }
|
|
488
|
|
489 void
|
|
490 config()
|
|
491 {
|
|
492 /* calc class-specific stuff */
|
|
493
|
|
494 phrange = PHASEDIST * me->p_ship.s_phaser.damage / 100;
|
|
495 trrange = TRACTDIST * me->p_ship.s_tractrng;
|
|
496
|
|
497 switch (myship->s_type)
|
|
498 {
|
|
499 case SCOUT:
|
|
500 dogslow = 5;
|
|
501 dogfast = 7;
|
|
502 runslow = 8;
|
|
503 runfast = 9;
|
|
504 closeslow = 5;
|
|
505 closefast = 7;
|
|
506 break;
|
|
507 case DESTROYER:
|
|
508 dogslow = 4;
|
|
509 dogfast = 6;
|
|
510 runslow = 6;
|
|
511 runfast = 8;
|
|
512 closeslow = 4;
|
|
513 closefast = 6;
|
|
514 break;
|
|
515 case CRUISER:
|
|
516 dogslow = 4;
|
|
517 dogfast = 6;
|
|
518 runslow = 6;
|
|
519 runfast = 7;
|
|
520 closeslow = 4;
|
|
521 closefast = 6;
|
|
522 break;
|
|
523 case BATTLESHIP:
|
|
524 dogslow = 3;
|
|
525 dogfast = 5;
|
|
526 runslow = 5;
|
|
527 runfast = 6;
|
|
528 closeslow = 3;
|
|
529 closefast = 4;
|
|
530 break;
|
|
531 case FRIGATE:
|
|
532 dogslow = 3;
|
|
533 dogfast = 5;
|
|
534 runslow = 5;
|
|
535 runfast = 6;
|
|
536 closeslow = 3;
|
|
537 closefast = 4;
|
|
538 break;
|
|
539 case ASSAULT:
|
|
540 dogslow = 3;
|
|
541 dogfast = 5;
|
|
542 runslow = 6;
|
|
543 runfast = 7;
|
|
544 closeslow = 3;
|
|
545 closefast = 4;
|
|
546 break;
|
|
547 case JUMPSHIP:
|
|
548 dogslow = 2;
|
|
549 dogfast = 3;
|
|
550 runslow = 2;
|
|
551 runfast = 3;
|
|
552 closeslow = 2;
|
|
553 closefast = 3;
|
|
554 break;
|
|
555 case STARBASE:
|
|
556 dogslow = 2;
|
|
557 dogfast = 2;
|
|
558 runslow = 2;
|
|
559 runfast = 2;
|
|
560 closeslow = 2;
|
|
561 closefast = 2;
|
|
562 break;
|
|
563 case WARBASE:
|
|
564 dogslow = 2;
|
|
565 dogfast = 2;
|
|
566 runslow = 2;
|
|
567 runfast = 2;
|
|
568 closeslow = 2;
|
|
569 closefast = 2;
|
|
570 break;
|
|
571 case LIGHTCRUISER:
|
|
572 dogslow = 5;
|
|
573 dogfast = 6;
|
|
574 runslow = 6;
|
|
575 runfast = 7;
|
|
576 closeslow = 5;
|
|
577 closefast = 7;
|
|
578 break;
|
|
579 case CARRIER:
|
|
580 dogslow = 3;
|
|
581 dogfast = 4;
|
|
582 runslow = 5;
|
|
583 runfast = 6;
|
|
584 closeslow = 4;
|
|
585 closefast = 6;
|
|
586 break;
|
|
587 case UTILITY:
|
|
588 dogslow = 3;
|
|
589 dogfast = 4;
|
|
590 runslow = 5;
|
|
591 runfast = 6;
|
|
592 closeslow = 4;
|
|
593 closefast = 5;
|
|
594 break;
|
|
595 case PATROL:
|
|
596 dogslow = 7;
|
|
597 dogfast = 8;
|
|
598 runslow = 9;
|
|
599 runfast = 10;
|
|
600 closeslow = 8;
|
|
601 closefast = 9;
|
|
602 break;
|
|
603 }
|
|
604
|
|
605 if (debug)
|
|
606 printf("My phaser range: %d.\n", phrange);
|
|
607 if (debug)
|
|
608 printf("My tractor range: %d.\n", trrange);
|
|
609
|
|
610 if (!nofuel)
|
|
611 {
|
|
612 myship->s_phaser.cost = 0;
|
|
613 myship->s_torp.cost = 0;
|
|
614 myship->s_cloakcost = 0;
|
|
615 }
|
|
616 if (target >= 0)
|
|
617 { /* 7/27/91 TC */
|
|
618 myship->s_imp.maxspeed = 20;/* was 10, so you can't run */
|
|
619 myship->s_imp.cost = 1;
|
|
620 myship->s_egncoolrate = 100;
|
|
621 }
|
|
622 }
|