void check_active_enemies() { static int timer; if(_state.total_enemies == 0){ if(_state.player_type == PT_OGGER || _state.player_type == PT_DOGFIGHTER){ timer ++; if(timer == 100){ mfprintf(stderr, "nobody to fight\n"); exitRobot(0); } } if(_state.timer_delay_ms < 10.0){ mprintf("No enemies: setting 1 update per second\n"); sendUpdatePacket(999999); _state.timer_delay_ms = 10.0; } } else { timer = 0; if(_state.timer_delay_ms > updates){ _state.timer_delay_ms = updates; mprintf("Enemies: setting %d updates per second\n", (int)(1000000./(updates * 100000.))); sendUpdatePacket((int)(updates * 100000.)); } } }
void cleanup(void) { register struct player *j; register int i; /* Free the held slots - MK 9-20-92 */ for (i=12, j = &players[i]; i < MAXPLAYER - TESTERS; i++, j++) { if ( j->p_status==POUTFIT && j->p_team==NOBODY){ j->p_status = PFREE; } } if (!practice) { memcpy(planets, oldplanets, sizeof(struct planet) * MAXPLANETS); for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) { if ((j->p_status != PALIVE) || (j == me)) continue; getship(&(j->p_ship), j->p_ship.s_type); } } status->gameup &= ~GU_DOG; exitRobot(); }
void death() { char buf[80]; int ghost = 0; #ifdef nodef /* Reset the signal */ signal(SIGALRM, SIG_IGN); udt.it_interval.tv_sec = 0; udt.it_interval.tv_usec = 0; udt.it_value.tv_sec = 0; udt.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &udt, 0); signal(SIGALRM, SIG_DFL); #endif switch (me->p_whydead) { case KQUIT: mprintf("You have self-destructed.\n"); break; case KTORP: mprintf("You were killed by a photon torpedo from %s (%c%c).\n", players[me->p_whodead].p_name, teamlet[players[me->p_whodead].p_team], shipnos[me->p_whodead]); break; case KPLASMA: mprintf("You were killed by a plasma torpedo from %s (%c%c)\n", players[me->p_whodead].p_name, teamlet[players[me->p_whodead].p_team], shipnos[me->p_whodead]); break; case KPHASER: mprintf("You were killed by a phaser shot from %s (%c%c)\n", players[me->p_whodead].p_name, teamlet[players[me->p_whodead].p_team], shipnos[me->p_whodead]); break; case KPLANET: mprintf("You were killed by planetary fire from %s (%c)\n", planets[me->p_whodead].pl_name, teamlet[planets[me->p_whodead].pl_owner]); break; case KSHIP: mprintf("You were killed by an exploding ship formerly owned by %s (%c%c)\n", players[me->p_whodead].p_name, teamlet[players[me->p_whodead].p_team], shipnos[me->p_whodead]); break; case KDAEMON: mprintf("You were killed by a dying daemon.\n"); break; case KWINNER: mprintf("Galaxy has been conquered by %s (%c%c) %s\n", players[me->p_whodead].p_name, teamlet[players[me->p_whodead].p_team], shipnos[players[me->p_whodead].p_no], teamstring[players[me->p_whodead].p_team]); break; case KGHOST: mprintf("You were killed by a confused daemon.\n"); ghost++; break; case KGENOCIDE: mprintf("Your team was genocided by %s (%c%c) %s.\n", players[me->p_whodead].p_name, teamlet[players[me->p_whodead].p_team], shipnos[me->p_whodead], teamstring[players[me->p_whodead].p_team]); break; case KPROVIDENCE: mprintf("You were removed from existence by divine mercy.\n"); break; default: mprintf("You were killed by something unknown to this game?\n"); break; } /* warning(buf, 1); */ /* First we check for promotions: */ if (promoted) { mprintf("Congratulations! You have been promoted to %s\n", ranks[mystats->st_rank].name); promoted=0; } if(ghost && (_state.player_type == PT_OGGER || _state.player_type == PT_DOGFIGHTER)) exitRobot(0); longjmp(env, 0); }
void rmove() { register struct player *j; register int i; register int burst; register int numHits, tDir; int avDir; extern struct Enemy *get_nearest(); struct Enemy *enemy_buf; struct player *enemy = NULL; static int roboclock = 0; static int avoid[2] = { -32, 32 }; int no_cloak; char towhom[MSG_LEN]; int timer; static int lastTorpped = 0; /* when we last fired a torp 4/13/92 TC */ roboclock++; /* keep ghostbuster away */ me->p_ghostbuster = 0; /* Check that I'm alive */ if (me->p_status == PEXPLODE) { if (debug) ERROR(1,("Robot: Augh! exploding.\n")); return; } else if (me->p_status == PDEAD) { if (me->p_ntorp > 0) return; if (debug) ERROR(1,("Robot: done exploding and torps are gone.\n")); exitRobot(); return; } timer=0; for (i = 0, j = &players[i]; i < (MAXPLAYER - TESTERS); i++, j++) { if ((j->p_status != PFREE) && !(j->p_flags & PFROBOT)) timer=1; } if (!timer && !sticky) { exitRobot(); return; } /* if I'm a Terminator, quit if he quits, and quit if he dies and */ /* I'm not "sticky" (-s) */ if (target >= 0) { if (players[target].p_status == PFREE) { /* he went away */ me->p_status = PEXPLODE; return; } if ((!sticky) && (players[target].p_status != PALIVE)) { /* he died */ me->p_status = PEXPLODE; return; } } /* If it's been BOREDOM_TIME updates since we fired a torp, become hostile to all races, if we aren't already, and if we're not a practice robot (intended for guardian bots). 4/13/92 TC */ if ((roboclock - lastTorpped > BOREDOM_TIME) && (!practice) && (!hostile) && (me->p_team != 0 && !quiet)) { messAll(me->p_no,roboname,"I'm bored."); hostile++; declare_war(ALLTEAM, 0); } /* Our first priority is to phaser plasma torps in nearby vicinity... */ /* If we fire, we aren't allowed to cloak... */ no_cloak = phaser_plasmas(); /* Find an enemy */ enemy_buf = get_nearest(); if ((enemy_buf != NULL) && (enemy_buf != NOENEMY)) { /* Someone to kill */ enemy = &players[enemy_buf->e_info]; if (((random() % messfuse) == 0) && (hypot((double) me->p_x-enemy->p_x, (double) me->p_y-enemy->p_y) < 20000.0)) { /* change 5/10/21 TC ...neut robots don't message */ messfuse = MESSFUSEVAL; if (me->p_team != 0 && !quiet) { sprintf(towhom, " %s->%s", players[me->p_no].p_mapchars, players[enemy->p_no].p_mapchars); pmessage2(enemy->p_no, MINDIV, towhom, me->p_no, "%s", robo_message(enemy)); } else if (target >= 0 && !quiet) { messAll(me->p_no,roboname,"%s",termie_message(enemy)); } } else if (--messfuse == 0) messfuse = 1; timer = 0; /* if (debug) ERROR(1,( "%d) noticed %d\n", me->p_no, enemy_buf->e_info));*/ } else if (enemy_buf == NOENEMY) { /* no more players. wait 1 minute. */ if (do_repair()) { return; } go_home(0); /* if (debug) ERROR(1,( "%d) No players in game.\n", me->p_no));*/ return; } else if (enemy_buf == 0) { /* no one hostile */ /* if (debug) ERROR(1,( "%d) No hostile players in game.\n", me->p_no));*/ if (do_repair()) { return; } go_home(0); timer = 0; return; } /* Note a bug in this algorithm: ** Once someone dies, he is forgotten. This makes robots particularly easy ** to kill on a suicide run, where you aim to where you think he will turn ** as you die. Once dead, the robot will ignore you and all of your ** active torpedoes! **/ /* Algorithm: ** We have an enemy. ** First priority: shoot at target in range. ** Second: Dodge torps and plasma torps. ** Third: Get away if we are damaged. ** Fourth: repair. ** Fifth: attack. */ /* ** If we are a practice robot, we will do all but the second. One ** will be modified to shoot poorly and not use phasers. **/ /* Fire weapons!!! */ /* ** get_nearest() has already determined if torpedoes and phasers ** will hit. It has also determined the courses which torps and ** phasers should be fired. If so we will go ahead and shoot here. ** We will lose repair and cloaking for the rest of this interrupt. ** if we fire here. */ if (practice) { no_cloak = 1; if (enemy_buf->e_flags & E_TSHOT) { /* if (debug) ERROR(1,( "%d) firing torps\n", me->p_no));*/ for (burst = 0; (burst < 3) && (me->p_ntorp < MAXTORP); burst++) { ntorp(enemy_buf->e_tcourse, TWOBBLE | TOWNERSAFE | TDETTEAMSAFE | TPRACTICE); } } } else { if (enemy_buf->e_flags & E_TSHOT) { /* if (debug) ERROR(1,( "%d) firing torps\n", me->p_no));*/ for (burst = 0; (burst < 2) && (me->p_ntorp < MAXTORP); burst++) { repair_off(); if (! cloaker) cloak_off(); ntorp(enemy_buf->e_tcourse, TWOBBLE | TOWNERSAFE | TDETTEAMSAFE); no_cloak++; lastTorpped = roboclock; /* record time of firing 4/13/92 TC */ } } if (enemy_buf->e_flags & E_PSHOT) { /* if (debug) ERROR(1,( "%d) phaser firing\n", me->p_no));*/ no_cloak++; repair_off(); if (! cloaker) cloak_off(); phaser(enemy_buf->e_course); } } /* auto pressor 7/27/91 TC */ /* tractor/pressor rewritten on 5/1/92... glitches galore :-| TC */ /* whoa, too close for comfort, or he's tractoring me, or headed in for me, or I'm hurt */ /* a little tuning -- 0.8 on phrange and +/- 90 degrees in for pressor */ /* pressor_player(-1); this didn't do anything before, so we'll let the pressors disengage by themselves 5/1/92 TC */ if (enemy_buf->e_flags & E_TRACT) { /* if pressorable */ if (((enemy_buf->e_dist < 0.8 * enemy_buf->e_phrange) && (angdist(enemy_buf->e_edir, enemy_buf->e_course) > 64)) || (isTractoringMe(enemy_buf)) || (me->p_damage > 0)) { if (!(enemy->p_flags & PFCLOAK)) { if (debug) ERROR(1,( "%d) pressoring %d\n", me->p_no, enemy_buf->e_info)); pressor_player(enemy->p_no); no_cloak++; repair_off(); if (!cloaker) cloak_off(); } } } /* auto tractor 7/31/91 TC */ /* tractor if not pressoring and... */ /* tractor if: in range, not too close, and not headed +/- 90 degrees */ /* of me, and I'm not hurt */ if ((!(me->p_flags & PFPRESS)) && (enemy_buf->e_flags & E_TRACT) && (angdist(enemy_buf->e_edir, enemy_buf->e_course) < 64) && (enemy_buf->e_dist > 0.7 * enemy_buf->e_phrange)) { if (!(me->p_flags & PFTRACT)) { if (debug) ERROR(1,( "%d) tractoring %d\n", me->p_no, enemy_buf->e_info)); tractor_player(enemy->p_no); no_cloak++; } } else tractor_player(-1); /* otherwise don't tractor */ /* Avoid torps */ /* ** This section of code allows robots to avoid torps. ** Within a specific range they will check to see if ** any of the 'closest' enemies torps will hit them. ** If so, they will evade for four updates. ** Evading is all they will do for this round, other than shooting. */ if (!practice) { if ((enemy->p_ntorp < 5)) { if ((enemy_buf->e_dist < 15000) || (avoidTime > 0)) { numHits = projectDamage(enemy->p_no, &avDir); if (debug) { ERROR(1,( "%d hits expected from %d from dir = %d\n", numHits, enemy->p_no, avDir)); } if (numHits == 0) { if (--avoidTime > 0) { /* we may still be avoiding */ if (angdist(me->p_desdir, me->p_dir) > 64) me->p_desspeed = dogslow; else me->p_desspeed = dogfast; return; } } else { /* * Actually avoid Torps */ avoidTime = AVOID_TIME; tDir = avDir - me->p_dir; /* put into 0->255 range */ tDir = NORMALIZE(tDir); if (debug) ERROR(1,( "mydir = %d avDir = %d tDir = %d q = %d\n", me->p_dir, avDir, tDir, tDir / 64)); switch (tDir / 64) { case 0: case 1: set_course(NORMALIZE(avDir + 64)); break; case 2: case 3: set_course(NORMALIZE(avDir - 64)); break; } if (!no_cloak) cloak_on(); if (angdist(me->p_desdir, me->p_dir) > 64) me->p_desspeed = dogslow; else me->p_desspeed = dogfast; shield_up(); detothers(); /* hmm */ if (debug) ERROR(1,( "evading to dir = %d\n", me->p_desdir)); return; } } } /* ** Trying another scheme. ** Robot will keep track of the number of torps a player has ** launched. If they are greater than say four, the robot will ** veer off immediately. Seems more humanlike to me. */ else if (enemy_buf->e_dist < 15000) { if (--avoidTime > 0) { /* we may still be avoiding */ if (angdist(me->p_desdir, me->p_dir) > 64) me->p_desspeed = dogslow; else me->p_desspeed = dogfast; return; } if (random() % 2) { me->p_desdir = NORMALIZE(enemy_buf->e_course - 64); avoidTime = AVOID_TIME; } else { me->p_desdir = NORMALIZE(enemy_buf->e_course + 64); avoidTime = AVOID_TIME; } if (angdist(me->p_desdir, me->p_dir) > 64) me->p_desspeed = dogslow; else me->p_desspeed = dogfast; shield_up(); return; } } /* Run away */ /* ** The robot has taken damage. He will now attempt to run away from ** the closest player. This obviously won't do him any good if there ** is another player in the direction he wants to go. ** Note that the robot will not run away if he dodged torps, above. ** The robot will lower his shields in hopes of repairing some damage. */ #define STARTDELTA 5000 /* ships appear +/- delta of home planet */ if (me->p_damage > 0 && enemy_buf->e_dist < 13000) { if (me->p_etemp > 900) /* 90% of 1000 */ me->p_desspeed = runslow; else me->p_desspeed = runfast; if (!no_cloak) cloak_on(); repair_off(); shield_down(); set_course(enemy_buf->e_course - 128); if (debug) ERROR(1,( "%d(%d)(%d/%d) running from %c%d %16s damage (%d/%d) dist %d\n", me->p_no, (int) me->p_kills, me->p_damage, me->p_shield, teamlet[enemy->p_team], enemy->p_no, enemy->p_login, enemy->p_damage, enemy->p_shield, enemy_buf->e_dist)); return; } /* Repair if necessary (we are safe) */ /* ** The robot is safely away from players. It can now repair in peace. ** It will try to do so now. */ if (do_repair()) { return; } /* Attack. */ /* ** The robot has nothing to do. It will check and see if the nearest ** enemy fits any of its criterion for attack. If it does, the robot ** will speed in and deliver a punishing blow. (Well, maybe) */ if ((enemy_buf->e_flags & E_INTRUDER) || (enemy_buf->e_dist < 15000) || (hostile)) { if ((!no_cloak) && (enemy_buf->e_dist < 10000)) cloak_on(); shield_up(); /* if (debug) ERROR(1,( "%d(%d)(%d/%d) attacking %c%d %16s damage (%d/%d) dist %d\n", me->p_no, (int) me->p_kills, me->p_damage, me->p_shield, teamlet[enemy->p_team], enemy->p_no, enemy->p_login, enemy->p_damage, enemy->p_shield, enemy_buf->e_dist));*/ if (enemy_buf->e_dist < 15000) { set_course(enemy_buf->e_course + avoid[(roboclock / AVOID_CLICKS) % SIZEOF(avoid)]); if (angdist(me->p_desdir, me->p_dir) > 64) set_speed(closeslow); else set_speed(closefast); } else { me->p_desdir = enemy_buf->e_course; if (angdist(me->p_desdir, me->p_dir) > 64) set_speed(closeslow); if (target >= 0) /* 7/27/91 TC */ set_speed(12); else if (me->p_etemp > 900) /* 90% of 1000 */ set_speed(runslow); else set_speed(runfast); } } else { go_home(enemy_buf); } }
intrupt() { static long lastread; static int prevread; int cr_time; /* handle torp firing */ do_torps(); _tcheck = 0; keep_reading: ; #ifdef ATM if (readFromServer(pollmode)) { /* should be 0 */ #else if (readFromServer()) { #endif cr_time = mtime(0); _cycletime = cr_time - prevread; _serverdelay = ((double)_cycletime/100.); _udnonsync++; /* can't be less than 100 ms */ if(_serverdelay < 1.) _serverdelay = 1.; if (DEBUG & DEBUG_SERVER) { printf("cycletime = %dms\n", _cycletime); printf("wait for input = %dms\n", cr_time - _waiting_for_input); } prevread = cr_time; if(_state.borg_detect) borg_detect(); } else { /* * We haven't heard from server for 3 secs... Strategy: send a * useless packet to "ping" server. */ /* If server is dead, just give up */ if (isServerDead()) exitRobot(0); if(!pollmode){ int now = time(NULL)-3; mprintf("sending wakeup packet at %s", ctime(&now)); sendWarReq(me->p_hostile); } } if (me->p_status == POUTFIT) { death(); } if(me->p_status != PALIVE) goto keep_reading; } /* borg detect */ borg_detect() { register Player *p; register struct player *j; int last_speedc, last_dirc; register i; for(i=0, p=_state.players; i < MAXPLAYER; i++,p++){ if(!p->p || (p->p->p_status != PALIVE) || p->invisible) continue; j = p->p; /* check for simultaneous torp & phaser but in different directions. -- Very common borg maneuver */ if(_udnonsync - p->tfire_t < 2){ if(p->tfire_t == p->pfire_t){ if(p->tfire_dir > -1){ if(angdist(p->tfire_dir, p->pfire_dir) > 2){ /* printf("%s BORG %d\n", j->p_mapchars, angdist(p->tfire_dir, p->pfire_dir)); printf("current p: %d\n", p->bp1); */ p->bp1 ++; } } } } /* check for recent change in direction far away from current torp or phaser fire */ if(j->p_speed > 1){ if(_udnonsync - p->tfire_t < 2){ if(_udnonsync - p->turn_t < 2){ if(angdist(j->p_dir, p->tfire_t) > 64){ /* printf("%s tfire BORG %d\n", j->p_mapchars, angdist(j->p_dir, p->tfire_t)); */ p->bp2 ++; } } } if(_udnonsync - p->pfire_t < 2){ if(_udnonsync - p->turn_t < 2){ if(angdist(j->p_dir, p->pfire_t) > 64){ /* printf("%s pfire BORG %d\n", j->p_mapchars, angdist(j->p_dir, p->pfire_t)); */ p->bp3 ++; } } } } if(p->bdc < 1.0) p->borg_probability = 0.0; else p->borg_probability = (double)(p->bp1 * 10 + p->bp2 + p->bp3)/ (double)p->bdc; } } /* maybe later */ #ifdef nodef if(_udcounter - p->tfire_t < 3){ last_speedc = p->tfire_t - p->speed_t; /* fired, then observed speed change within 5 cycles */ if(last_speedc < 5 && p->tfire_dir > -1){ /* player direction and torp fire direction greater than 64 */ if(angdist(j->p_dir, p->tfire_dir) > 64){ mprintf("speed detect\n"); p->borg_probability ++; } } last_dirc = p->tfire_t - p->turn_t; /* fired, then observed direction change within 5 cycles */ if(last_dirc < 5 && p->tfire_dir > -1){ /* player direction and torp fire direction greater than 64 */ if(angdist(j->p_dir, p->tfire_dir) > 64){ mprintf("direction detect\n"); p->borg_probability ++; } } }