int phaser_plasmas() { struct torp *t; int myphrange; myphrange = phrange; /*PHASEDIST * me->p_ship.s_phaserdamage / 100;*/ for (t=firstPlasma; t<=lastPlasma; t++) { if (t->t_status != TMOVE) continue; if (t->t_owner == me->p_no) continue; if (!(t->t_war & me->p_team) && !(me->p_war & t->t_team)) continue; if (abs(t->t_x - me->p_x) > myphrange) continue; if (abs(t->t_y - me->p_y) > myphrange) continue; if (myphrange < hypot((float) t->t_x - me->p_x, (float) t->t_y - me->p_y)) continue; repair_off(); if (! cloaker) cloak_off(); phaser(getcourse(t->t_x, t->t_y)); return 1; break; } return 0; }
inline float delayline::get_phaser(float smps, float lfo, int tap_, int stg) { float delta = lfo; if (delta > 1.0f) delta = 1.0f; if (delta < 0.0f) delta = 0.0f; tap = tap_; pstruct[tap].gain[0] = (1.0f - delta) / (1.0f + delta); pstruct[tap].stages = stg; return (phaser(smps)); };
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); } }