comparison src/robotII.c @ 6:8c6d5731234d

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:04 +0000
parents
children
comparison
equal deleted inserted replaced
5:054275999194 6:8c6d5731234d
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 }