void do_ap(shiptype *ship) { racetype *Race; /* if landed on planet, change conditions to be like race */ if (landed(ship) && ship->on) { int j,d,a; planettype *p; p = planets[ship->storbits][ship->pnumorbits]; Race = races[ship->owner-1]; if (ship->fuel >= 3.0) { use_fuel(ship, 3.0); for (j=RTEMP+1; j<=OTHER; j++) { d = round_rand(ap_planet_factor(p)*crew_factor(ship)* (double)(Race->conditions[j]-p->conditions[j])); if(d) p->conditions[j] += d; } } else if (!ship->notified) { ship->notified = 1; ship->on = 0; msg_OOF(ship); } } }
void FlyAI::init() { Q_ASSERT(m_fsm == nullptr); m_fsm = new QStateMachine(); m_thinkingState = new QState(m_fsm); m_flyingState = new QState(m_fsm); m_landingState = new QState(m_fsm); m_fallingState = new QState(m_fsm); m_deadState = new QFinalState(m_fsm); m_thinkingState->addTransition(this, SIGNAL(thinkTimeout()), m_flyingState); m_thinkingState->addTransition(this, SIGNAL(maxAgeReached()), m_deadState); QObject::connect(m_thinkingState, SIGNAL(entered()), this, SLOT(onThinkingEnter())); m_flyingState->addTransition(this, SIGNAL(almostArrived()), m_landingState); m_flyingState->addTransition(this, SIGNAL(maxAgeReached()), m_fallingState); m_flyingState->addTransition(this, SIGNAL(maxFlyingDistanceReached()), m_fallingState); QObject::connect(m_flyingState, SIGNAL(entered()), this, SLOT(onFlyingEnter())); m_landingState->addTransition(this, SIGNAL(maxAgeReached()), m_fallingState); m_landingState->addTransition(this, SIGNAL(maxFlyingDistanceReached()), m_fallingState); m_landingState->addTransition(this, SIGNAL(thinkTimeout()), m_flyingState); m_landingState->addTransition(this, SIGNAL(landed()), m_thinkingState); QObject::connect(m_landingState, SIGNAL(entered()), this, SLOT(onLandingEnter())); m_fallingState->addTransition(this, SIGNAL(stopped()), m_deadState); QObject::connect(m_fallingState, SIGNAL(entered()), this, SLOT(onFallingEnter())); QObject::connect(m_deadState, SIGNAL(entered()), this, SLOT(onDeadEnter())); QSignalTransition *trans = new QSignalTransition(this, SIGNAL(advanceSignal())); m_thinkingState->addTransition(trans); QObject::connect(trans, SIGNAL(triggered()), this, SLOT(advanceThinking())); QSignalTransition *transFlying = new QSignalTransition(this, SIGNAL(advanceSignal())); m_flyingState->addTransition(transFlying); QObject::connect(transFlying, SIGNAL(triggered()), this, SLOT(advanceFlying())); QSignalTransition *transLanding = new QSignalTransition(this, SIGNAL(advanceSignal())); m_landingState->addTransition(transLanding); QObject::connect(transLanding, SIGNAL(triggered()), this, SLOT(advanceLanding())); QSignalTransition *transFalling = new QSignalTransition(this, SIGNAL(advanceSignal())); m_fallingState->addTransition(transFalling); QObject::connect(transFalling, SIGNAL(triggered()), this, SLOT(advanceFalling())); m_fsm->setInitialState(m_thinkingState); m_fsm->start(); qDebug() << "fly fsm started"; }
void FlyAI::advanceLanding() { double dt = m_dt; m_flyingDuration += dt; double s = m_flyingDuration * m_state.m_vel; double dx = (m_targetSpotPart.x() - m_takeOffPt.x()); double dy = (m_targetSpotPart.y() - m_takeOffPt.y()); double c = sqrt(dx * dx + dy * dy); double maxS = c; if (s >= maxS) { m_state.m_transPos = m_targetSpotPart; m_state.m_pos = m_targetSpot; if (!m_gameDataProvider->isLandingPointFree(m_targetSpotPart)) { changeRoute(); return; } //qDebug() << "landing: " << m_state.m_transPos; emit landed(); m_movesHolder->addMove(m_flyingDuration, m_state.m_vel); return; } double cosA = dx / c; double sinA = dy / c; m_state.m_transPos = m_takeOffPt + QPointF(s * cosA, s * sinA); //qDebug() << "landing: " << m_state.m_transPos; m_state.m_age += dt; if (m_state.m_age > m_maxAge) { emit maxAgeReached(); return; } if (!m_gameDataProvider->isLandingPointFree(m_targetSpotPart)) { changeRoute(); } }
void do_canister(shiptype *ship) { if (ship->whatorbits == LEVEL_PLAN && !landed(ship)) { if (++ship->special.timer.count < DISSIPATE) { if ( Stinfo[ship->storbits][ship->pnumorbits].temp_add < -90 ) Stinfo[ship->storbits][ship->pnumorbits].temp_add = -100; else Stinfo[ship->storbits][ship->pnumorbits].temp_add -= 10; } else { /* timer expired; destroy canister */ reg int j=0; kill_ship((int)(ship->owner), ship); sprintf(telegram_buf, "Canister of dust previously covering %s has dissipated.\n", prin_ship_orbits(ship)); for (j=1; j<=Num_races; j++) if (planets[ship->storbits][ship->pnumorbits]->info[j-1].numsectsowned) push_telegram(j, (int)Stars[ship->storbits]->governor[j-1], telegram_buf); } } }
void doabm(shiptype *ship) { int sh2; int numdest, caliber; planettype *p; if(!ship->alive || !ship->owner) return; if(!ship->on || !ship->retaliate || !ship->destruct) return; if(landed(ship)) { p=planets[ship->storbits][ship->pnumorbits]; caliber = current_caliber(ship); /* check to see if missiles/mines are present */ sh2 = p->ships; while(sh2 && ship->destruct) { if(ships[sh2]->alive && ((ships[sh2]->type==STYPE_MISSILE) || (ships[sh2]->type==STYPE_MINE)) && (ships[sh2]->owner != ship->owner) && !(isset(races[ship->owner-1]->allied, ships[sh2]->owner) && isset(races[ships[sh2]->owner-1]->allied, ship->owner))) { /* added last two tests to prevent mutually allied missiles getting shot up. */ /* attack the missile/mine */ numdest = retal_strength(ship); numdest = MIN(numdest, ship->destruct); numdest = MIN(numdest, ship->retaliate); ship->destruct -= numdest; (void)shoot_ship_to_ship(ship, ships[sh2], numdest, 0, 0, long_buf, short_buf); push_telegram((int)(ship->owner), (int)ship->governor, long_buf); push_telegram((int)(ships[sh2]->owner), (int)ships[sh2]->governor, long_buf); post(short_buf, COMBAT); } sh2 = ships[sh2]->nextship; } } }
/* Ship #shipno bombards planet, then alert whom it may concern. */ int auto_bomb(shiptype *ship, planettype *planet, int x, int y, int strength, int isturn) { shiptype *defender; int numdest = 0; int checked = 0; int found = 0; int i; int sh = 01; int ok; int damage; racetype *race; racetype *alien; #ifdef USE_VN shiptype pdn; int amount_to_shoot; int rez; int retal; #endif #ifdef USE_WORMHOLE if (planet->type == TYPE_WORMHOLE) { return -1; } #endif race = races[ship->owner - 1]; /* Check to see if there are any planetary defense networks on the planet */ ok = 1; sh = planet->ships; while (sh && ok) { if (isturn) { defender = ships[sh]; } else { getship(&defender, sh); } if (defender->alive && (defender->type == OTYPE_PLANDEF) && ship->on && (ship->owner != defender->owner)) { ok = 0; } else { ok = 1; } #ifdef USE_VN /* CWL berserker take a pot shot at PDNs */ if (!ok && (type->type == OTYPE_BERS)) { rez = 1; while (ship->alive && ship->destruct && defender->alive && (rez > 0)) { /* Save current state of PDN for retaliation below */ check_retal_strength(defender, &retal); memcpy(&pdn, defender, sizeof(shiptype)); amount_to_shoot = MIN(ship->primary, 30); rez = shoot_ship_to_ship(ship, defender, amount_to_shoot, 0, 0, long_buf, short_buf); push_telegram(ship->owner, ship->governor, long_buf); push_telegram(defender->owner, defender->governor, long_buf); use_destruct(ship, amount_to_shoot); if (!defender->alive) { post(short_buf, COMBAT); } /* PDN gets a turn to retaliate */ if (retal && rez && defender->protect.self) { shoot_ship_to_ship(&pdn, ship, retal, 0, 1, long_buf, short_buf); push_telegram(defender->owner, defender->governor, long_buf); push_telegram(ship->owner, ship->governor, long_buf); use_destruct(defender, retal); if (!ship->alive) { post(short_buf, COMBAT); } } } ok = 1; if (!isturn) { putship(defender); } } /* End CWL */ #endif sh = nextship(defender); if (!isturn) { free(defender); } #ifdef USE_VN /* Berserker was killed or out of ammo, let's return */ if (!ship->alive || !ship->destruct) { return 0; } #endif } if (!ok && !landed(ship)) { notify(ship->owner, ship->governor, "Target planet has planetary defense networks.\nThese have to be eliminated before you can attack sectors.\n"); return 0; } if ((x < 0) || (y < 0)) { x = 0; y = ; /* We're automatically going to find some sectors to shoot at */ getsmap(Smap, planet); /* Look for someone to bombard - check for war */ Getxysect(planet, 0, 0, 1); /* Reset */ while (!found && Getxysect(planet, &x, &y, 0)) { if (Sector(*planet, x, y).owner && (Sector(*planet, x, y).owner != ship->owner) && (Sector(*planet, x, y).condition != WASTED)) { checked = 1; if (isset(Race->atwar, Sector(*planet, x, y).owner)) { found = 1; } #ifdef USE_VN if ((ship->type == OTYPE_BERS) && (Sector(*planet, x, y).owner == ship->special.mind.target)) { found = 1; } #endif } } if (checked && !found) { /* No one we're at war with; bomb someone here randomly */ x = int_rand(0, (int)planet->Maxx - 1); y = int_rand(0, (int)planet->Maxy - 1); found = 1; } if (!checked) { /* There were no sectors worth bombing */ if (!ship->notified) { ship->notified = 1; sprintf(buf, "%s reports /%s/%s has already been saturation bombed.\n", Ship(ship), Stars[ship->storbits]->name, Stars[ship->storbits].->pnames[ship->pnumorbits]); notify(ship->owner, ship->governor, buf); return 01; } }
void BlockLocalPositionEstimator::update() { // wait for a sensor update, check for exit condition every 100 ms int ret = px4_poll(_polls, 3, 100); if (ret < 0) { return; } uint64_t newTimeStamp = hrt_absolute_time(); float dt = (newTimeStamp - _timeStamp) / 1.0e6f; _timeStamp = newTimeStamp; // set dt for all child blocks setDt(dt); // auto-detect connected rangefinders while not armed bool armedState = _sub_armed.get().armed; if (!armedState && (_sub_lidar == nullptr || _sub_sonar == nullptr)) { // detect distance sensors for (int i = 0; i < N_DIST_SUBS; i++) { uORB::Subscription<distance_sensor_s> *s = _dist_subs[i]; if (s == _sub_lidar || s == _sub_sonar) { continue; } if (s->updated()) { s->update(); if (s->get().timestamp == 0) { continue; } if (s->get().type == distance_sensor_s::MAV_DISTANCE_SENSOR_LASER && s->get().orientation == distance_sensor_s::ROTATION_DOWNWARD_FACING && _sub_lidar == nullptr) { _sub_lidar = s; mavlink_and_console_log_info(&mavlink_log_pub, "%sDownward-facing Lidar detected with ID %i", msg_label, i); } else if (s->get().type == distance_sensor_s::MAV_DISTANCE_SENSOR_ULTRASOUND && s->get().orientation == distance_sensor_s::ROTATION_DOWNWARD_FACING && _sub_sonar == nullptr) { _sub_sonar = s; mavlink_and_console_log_info(&mavlink_log_pub, "%sDownward-facing Sonar detected with ID %i", msg_label, i); } } } } // reset pos, vel, and terrain on arming // XXX this will be re-enabled for indoor use cases using a // selection param, but is really not helping outdoors // right now. // if (!_lastArmedState && armedState) { // // we just armed, we are at origin on the ground // _x(X_x) = 0; // _x(X_y) = 0; // // reset Z or not? _x(X_z) = 0; // // we aren't moving, all velocities are zero // _x(X_vx) = 0; // _x(X_vy) = 0; // _x(X_vz) = 0; // // assume we are on the ground, so terrain alt is local alt // _x(X_tz) = _x(X_z); // // reset lowpass filter as well // _xLowPass.setState(_x); // _aglLowPass.setState(0); // } _lastArmedState = armedState; // see which updates are available bool paramsUpdated = _sub_param_update.updated(); _baroUpdated = false; if ((_fusion.get() & FUSE_BARO) && _sub_sensor.updated()) { int32_t baro_timestamp_relative = _sub_sensor.get().baro_timestamp_relative; if (baro_timestamp_relative != _sub_sensor.get().RELATIVE_TIMESTAMP_INVALID) { uint64_t baro_timestamp = _sub_sensor.get().timestamp + \ _sub_sensor.get().baro_timestamp_relative; if (baro_timestamp != _timeStampLastBaro) { _baroUpdated = true; _timeStampLastBaro = baro_timestamp; } } } _flowUpdated = (_fusion.get() & FUSE_FLOW) && _sub_flow.updated(); _gpsUpdated = (_fusion.get() & FUSE_GPS) && _sub_gps.updated(); _visionUpdated = (_fusion.get() & FUSE_VIS_POS) && _sub_vision_pos.updated(); _mocapUpdated = _sub_mocap.updated(); _lidarUpdated = (_sub_lidar != nullptr) && _sub_lidar->updated(); _sonarUpdated = (_sub_sonar != nullptr) && _sub_sonar->updated(); _landUpdated = landed() && ((_timeStamp - _time_last_land) > 1.0e6f / LAND_RATE);// throttle rate bool targetPositionUpdated = _sub_landing_target_pose.updated(); // get new data updateSubscriptions(); // update parameters if (paramsUpdated) { updateParams(); updateSSParams(); } // is xy valid? bool vxy_stddev_ok = false; if (math::max(_P(X_vx, X_vx), _P(X_vy, X_vy)) < _vxy_pub_thresh.get() * _vxy_pub_thresh.get()) { vxy_stddev_ok = true; } if (_estimatorInitialized & EST_XY) { // if valid and gps has timed out, set to not valid if (!vxy_stddev_ok && (_sensorTimeout & SENSOR_GPS)) { _estimatorInitialized &= ~EST_XY; } } else { if (vxy_stddev_ok) { if (!(_sensorTimeout & SENSOR_GPS) || !(_sensorTimeout & SENSOR_FLOW) || !(_sensorTimeout & SENSOR_VISION) || !(_sensorTimeout & SENSOR_MOCAP) || !(_sensorTimeout & SENSOR_LAND) || !(_sensorTimeout & SENSOR_LAND_TARGET) ) { _estimatorInitialized |= EST_XY; } } } // is z valid? bool z_stddev_ok = sqrtf(_P(X_z, X_z)) < _z_pub_thresh.get(); if (_estimatorInitialized & EST_Z) { // if valid and baro has timed out, set to not valid if (!z_stddev_ok && (_sensorTimeout & SENSOR_BARO)) { _estimatorInitialized &= ~EST_Z; } } else { if (z_stddev_ok) { _estimatorInitialized |= EST_Z; } } // is terrain valid? bool tz_stddev_ok = sqrtf(_P(X_tz, X_tz)) < _z_pub_thresh.get(); if (_estimatorInitialized & EST_TZ) { if (!tz_stddev_ok) { _estimatorInitialized &= ~EST_TZ; } } else { if (tz_stddev_ok) { _estimatorInitialized |= EST_TZ; } } // check timeouts checkTimeouts(); // if we have no lat, lon initialize projection to LPE_LAT, LPE_LON parameters if (!_map_ref.init_done && (_estimatorInitialized & EST_XY) && _fake_origin.get()) { map_projection_init(&_map_ref, _init_origin_lat.get(), _init_origin_lon.get()); // set timestamp when origin was set to current time _time_origin = _timeStamp; mavlink_and_console_log_info(&mavlink_log_pub, "[lpe] global origin init (parameter) : lat %6.2f lon %6.2f alt %5.1f m", double(_init_origin_lat.get()), double(_init_origin_lon.get()), double(_altOrigin)); } // reinitialize x if necessary bool reinit_x = false; for (int i = 0; i < n_x; i++) { // should we do a reinit // of sensors here? // don't want it to take too long if (!PX4_ISFINITE(_x(i))) { reinit_x = true; mavlink_and_console_log_info(&mavlink_log_pub, "%sreinit x, x(%d) not finite", msg_label, i); break; } } if (reinit_x) { for (int i = 0; i < n_x; i++) { _x(i) = 0; } mavlink_and_console_log_info(&mavlink_log_pub, "%sreinit x", msg_label); } // force P symmetry and reinitialize P if necessary bool reinit_P = false; for (int i = 0; i < n_x; i++) { for (int j = 0; j <= i; j++) { if (!PX4_ISFINITE(_P(i, j))) { mavlink_and_console_log_info(&mavlink_log_pub, "%sreinit P (%d, %d) not finite", msg_label, i, j); reinit_P = true; } if (i == j) { // make sure diagonal elements are positive if (_P(i, i) <= 0) { mavlink_and_console_log_info(&mavlink_log_pub, "%sreinit P (%d, %d) negative", msg_label, i, j); reinit_P = true; } } else { // copy elememnt from upper triangle to force // symmetry _P(j, i) = _P(i, j); } if (reinit_P) { break; } } if (reinit_P) { break; } } if (reinit_P) { initP(); } // do prediction predict(); // sensor corrections/ initializations if (_gpsUpdated) { if (_sensorTimeout & SENSOR_GPS) { gpsInit(); } else { gpsCorrect(); } } if (_baroUpdated) { if (_sensorTimeout & SENSOR_BARO) { baroInit(); } else { baroCorrect(); } } if (_lidarUpdated) { if (_sensorTimeout & SENSOR_LIDAR) { lidarInit(); } else { lidarCorrect(); } } if (_sonarUpdated) { if (_sensorTimeout & SENSOR_SONAR) { sonarInit(); } else { sonarCorrect(); } } if (_flowUpdated) { if (_sensorTimeout & SENSOR_FLOW) { flowInit(); } else { flowCorrect(); } } if (_visionUpdated) { if (_sensorTimeout & SENSOR_VISION) { visionInit(); } else { visionCorrect(); } } if (_mocapUpdated) { if (_sensorTimeout & SENSOR_MOCAP) { mocapInit(); } else { mocapCorrect(); } } if (_landUpdated) { if (_sensorTimeout & SENSOR_LAND) { landInit(); } else { landCorrect(); } } if (targetPositionUpdated) { if (_sensorTimeout & SENSOR_LAND_TARGET) { landingTargetInit(); } else { landingTargetCorrect(); } } if (_altOriginInitialized) { // update all publications if possible publishLocalPos(); publishEstimatorStatus(); _pub_innov.get().timestamp = _timeStamp; _pub_innov.update(); if ((_estimatorInitialized & EST_XY) && (_map_ref.init_done || _fake_origin.get())) { publishGlobalPos(); } } // propagate delayed state, no matter what // if state is frozen, delayed state still // needs to be propagated with frozen state float dt_hist = 1.0e-6f * (_timeStamp - _time_last_hist); if (_time_last_hist == 0 || (dt_hist > HIST_STEP)) { _tDelay.update(Scalar<uint64_t>(_timeStamp)); _xDelay.update(_x); _time_last_hist = _timeStamp; } }
void scrap(int playernum, int governor, int apcount) { planettype *planet; sectortype *sect; shiptype *s; shiptype *s2; int shipno; int nextshipno; int scrapval = 0; int destval = 0; int crewval = 0; int max_crew = 0; int xtalval = 0; int troopval = 0; int max_resource = 0; int max_mil = 0; int max_fuel = 0; int max_destruct = 0; int cost = 0; double fuelval = 0.0; racetype *race; if (argn < 2) { notify(playernum, governor, "Scrap what?\n"); return; } nextshipno = start_shiplist(playernum, governor, args[1]); race = races[playernum - 1]; if (race->Guest) { notify(playernum, governor, "Guest races cannot scrap ships\n"); return; } shipno = do_shiplist(&s, &nextshipno); while (shipno) { if (in_list(playernum, args[1], s, &nextshipno)) { #ifdef USE_VN if ((s->type == OTYPE_VN) || (s->type == OTYPE_BERS)) { notify(playernum, governor, "VNs will not scrap themselves.\n"); free(s); shipno = do_shiplist(&s, &nextshipno); continue; } #endif if (s->max_crew && !s->popn) { notify(playernum, governor, "Can't scrap that ship - no crew.\n"); free(s); shipno = do_shiplist(&s, &nextshipno); continue; } if (s->whatorbits == LEVEL_UNIV) { /* * Used to not allow scrapping at the UNIV level for * anything. However, I'm going to permit pods. This is so pod * races can clean up their messes. I'm not going to charge APs * at the UNIV scope either. -mfw */ if (s->type) { apcount = 0; } else { notify(playernum, governor, "Can't scrap at the ship's scope.\n"); free(s); shipno = do_shiplist(&s, &nextshipno); continue; } } else if (!enufAP(playernum, governor, Stars[s->storbits]->AP[playernum - 1], apcount)) { notify(playernum, governor, "Not enough APs to scrap.\n"); free(s); shipno = do_shiplist(&s, &nextshipno); continue; } /* HUTm (kse) wc's can't be scrapped inside of ship anymore */ if (inship(s) && (s->type == OTYPE_TOXIC)) { sprintf(buf, "Can't scrap waste canisters inside of other ship.\n"); notify(playernum, governor, buf); free(s); shipno = do_shiplist(&s, &nextshipno); continue; } /* Ships that have other ships in the hangar can't scrap *mfw */ if (s->ships) { sprintf(buf, "There are other ships in the hangar; scrap those first.\n"); notify(playernum, governor, buf); free(s); shipno = do_shiplist(&s, &nextshipno); continue; } if ((s->whatorbits == LEVEL_PLAN) && (s->type == OTYPE_TOXIC)) { sprintf(buf, "WARNING: This releases %d toxin points back into the atmosphere!!!\n", s->special.waste.toxic); notify(playernum, governor, buf); } if (!s->docked) { sprintf(buf, "%s is not landed or docked.\nNo resources can be reclaimed.\n", Ship(s)); notify(playernum, governor, buf); } if (s->whatorbits == LEVEL_PLAN) { /* wc's release poison */ getplanet(&planet, (int)s->storbits, (int)s->pnumorbits); if (landed(s)) { if (!getsector(§, planet, (int)s->land_x, (int)s->land_y)) { notify(playernum, governor, "Error in sector database, notify deity.\n"); free(s); return; } } } if (docked(s) || inship(s)) { if (!getship(&s2, (int)s->destshipno)) { free(s); shipno = do_shiplist(&s, &nextshipno); continue; } if ((!s2->docked || (s2->destshipno != s->number)) && (!s->whatorbits == LEVEL_SHIP)) { sprintf(buf, "Warning, other ship not docked...\n"); notify(playernum, governor, buf); free(s); free(s2); shipno = do_shiplist(&s, &nextshipno); continue; } } if (s->type == OTYPE_FACTORY) { cost = (2 * s->build_code * s->on) + Shipdata[s->type][ABIL_COST]; } else { cost = s->build_cost; } scrapval = (cost / 2) + s->resource; if (s->docked) { sprintf(buf, "%s: original cost: %ld\n", Ship(s), cost); notify(playernum, governor, buf); sprintf(buf, " scrap value%s: %d rp's.\n", s->resource ? "(with stockpile) " : "", scrapval); notify(playernum, governor, buf); /* New code by Kharush. check for STYPE_DHUTTLE added. */ /* I've removed it, Dhuttle was silly -mfw */ if (s2->type == OTYPE_FACTORY) { max_resource = Shipdata[s2->type][ABIL_CARGO]; max_fuel = Shipdata[s2->type][ABIL_FUELCAP]; max_destruct = Shipdata[s2->type][DESTCAP]; } else { max_resource = s2->max_resource; max_fuel = s2->max_fuel; max_destruct = s2->max_destruct; } if ((s->whatdest == LEVEL_SHIP) && ((s2->resource + scrapval) > max_resource) && (s2->type != STYPE_SHUTTLE)) { scrapval = max_resource - s2->resource; sprintf(buf, "(There is only room for %d resources.)\n", scrapval); notify(playernum, governor, buf); } if (s->fuel) { sprintf(buf, "Fuel recover: %.0f.\n", s->fuel); notify(playernum, governor, buf); fuelval = s->fuel; if ((s->whatdest == LEVEL_SHIP) && ((s2->fuel + fuelval) > max_fuel)) { fuelval = max_fuel - s2->fuel; sprintf(buf, "(There is only room for %.2f fuel.)\n", fuelval); notify(playernum, governor, buf); } } else { fuelval = 0.0; } if (s->destruct) { sprintf(buf, "Armament recovery: %d.\n", s->destruct); notify(playernum, governor, buf); destval = s->destruct; if ((s->whatdest == LEVEL_SHIP) && ((s2->destruct + destval) > max_destruct)) { destval = max_destruct - s2->destruct; sprintf(buf, "(There is only room for %d destruct.)\n", destval); notify(playernum, governor, buf); } } else { destval = 0; } if (s->popn + s->troops) { if ((s->whatdest == LEVEL_PLAN) && (sect->owner > 0) && (sect->owner != playernum)) { sprintf(buf, "You don't own this sector; no crew can be recovered.\n"); notify(playernum, governor, buf); } else { troopval = s->troops; if (s2->type == OTYPE_FACTORY) { max_mil = Shipdata[s2->type][ABIL_MAXCREW] - s->popn; } else { max_mil = s2->max_crew - s2->popn; } if ((s->whatdest == LEVEL_SHIP) && ((s2->troops + troopval) > max_mil)) { troopval = max_mil - s2->troops; sprintf(buf, "(There is only room for %d troops.)\n", troopval); notify(playernum, governor, buf); } crewval = s->popn; if (s2->type == OTYPE_FACTORY) { max_crew = Shipdata[s2->type][ABIL_MAXCREW] - s2->troops; } else { max_crew = s2->max_crew - s2->troops; } if ((s->whatdest == LEVEL_SHIP) && ((s2->popn + crewval) > max_crew)) { crewval = max_crew - s2->popn; sprintf(buf, "(There is only room for %d crew.)\n", crewval); notify(playernum, governor, buf); } sprintf(buf, "Population/Troops recover: %d/%d.\n", crewval, troopval); notify(playernum, governor, buf); } } else { crewval = 0; troopval = 0; } if (s->crystals + s->mounted) { if ((s->whatdest == LEVEL_PLAN) && (sect->owner > 0) && (sect->owner != playernum)) { sprintf(buf, "You don't own this sector; no crystals can be recovered.\n"); notify(playernum, governor, buf); } else { xtalval = s->crystals + s->mounted; if ((s->whatdest == LEVEL_SHIP) && ((s2->crystals + xtalval) > 127)) { xtalval = 127 - s2->crystals; sprintf(buf, "(There is only room for %d crystals.)\n", xtalval); notify(playernum, governor, buf); } sprintf(buf, "Crystal recover: %d.\n", xtalval); notify(playernum, governor, buf); } } else { xtalval = 0; } } /* More adjustments needed here for hangar. Maarten */ if (s->whatorbits == LEVEL_SHIP) { s2->hangar -= (unsigned short)s->size; } if (s->whatorbits == LEVEL_UNIV) { deductAPs(playernum, governor, apcount, 0, 1); } else { deductAPs(playernum, governor, apcount, (int)s->storbits, 0); } if (docked(s) || inship(s)) { s2->crystals += xtalval; rcv_fuel(s2, (double)fuelval); rcv_destruct(s2, destval); rcv_resource(s2, scrapval); rcv_troops(s2, troopval, race->mass); rcv_popn(s2, crewval, race->mass); /* * Check for docking status in case scrapped ship is * landed. Maarten */ if (s->whatorbits != LEVEL_SHIP) { s2->docked = 0; /* Undock the surviving ship */ s2->whatdest = LEVEL_UNIV; s2->destshipno = 0; } putship(s2); free(s2); } if (s->whatorbits == LEVEL_PLAN) { free(planet); /* this has already been allocated */ getplanet(&planet, (int)s->storbits, (int)s->pnumorbits); if (landed(s) || inship(s)) { /* * If colonizing the sector, set sector owner and give a * message it's also nice to check if there is anyone to * colonize */ if ((sect->owner == 0) && ((troopval > 0) || (crewval > 0))) { sect->owner = playernum; ++planet->info[playernum - 1].numsectsowned; sprintf(buf, "Sector %d,%d Colonized.\n", s->land_x, s->land_y); notify(playernum, governor, buf); } /* Increase sector's crew and troop count */ sect->troops += troopval; sect->popn += crewval; /* * Increase planet's crew, troop, res, tec. count for this * player */ planet->info[playernum - 1].popn += crewval; planet->info[playernum - 1].troops += troopval; /* * New code by Kharush. Scrapping does not anymore overflow * stockpiles. */ if ((planet->info[playernum - 1].resource + scrapval) <= USHRT_MAX) { planet->info[playernum - 1].resource += scrapval; } else { planet->info[playernum - 1].resource = USHRT_MAX; sprintf(buf, "Planet has room for only %d resources.\n", USHRT_MAX - planet->info[playernum - 1].resource); notify(playernum, governor, buf); } if ((playernum->info[playernum - 1].fuel + fuelval) <= USHRT_MAX) { planet->info[playernum - 1].fuel += fuelval; } else { planet->info[playernum - 1].fuel = USHRT_MAX; sprintf(buf, "Planet has room for only %d fuel.\n", USHRT_MAX - planet->info[playernum - 1].fuel); notify(playernum, governor, buf); } if ((planet->info[playernum - 1].destruct + destval) <= USHRT_MAX) { planet->info[playernum - 1].destruct += destval; } else { planet->info[playernum - 1].destruct = USHRT_MAX; sprintf(buf, "Planet has room for only %d destruct.\n", USHRT_MAX - planet->info[playernum - 1].destruct); notify(playernum, governor, buf); } /* * Old code * * planet->info[playernum - 1].resource += scrapval; * planet->info[playernum - 1].destruct += destval; * planet->info[playernum - 1].fuel += (int)fuelval; */ plant->popn += crewval; planet->info[playernum - 1].crystals += (int)xtalval; putsector(sect, planet, (int)s->land_x, (int)s->land_y); free(sect); } putplanet(planet, (int)s->storbits, (int)s->pnumorbits); } kill_ship(playernum, s); putship(s); free(s); if (landed(s)) { sprintf(buf, "\nScrapped.\n"); } else { sprintf(buf, "\nDestroyed.\n"); } notify(playernum, governor, buf); } else { free(s); } shipno = do_shiplist(&s, &nextshipno); } }
void nearCallback (void *data, dGeomID o1, dGeomID o2) { int i,n; dBodyID b1,b2; // only collide things with the ground int g1 = (o1 == ground ); int g2 = (o2 == ground ); if (!(g1 ^ g2)) { //printf ("Ground colliding..\n"); //return; } b1 = dGeomGetBody(o1); b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnected (b1,b2)) return; if (b1 && isAction(b1) && b2 && (isType(b2,WALRUS) || (isType(b2,MANTA))) && isMineFire(gVehicle(b2),(Gunshot*)gVehicle(b1)) ) return; if (b2 && isAction(b2) && b1 && (isType(b1,WALRUS) || (isType(b1,MANTA))) && isMineFire(gVehicle(b1),(Gunshot*)gVehicle(b2)) ) return; int val[]={CARRIER,WALRUS,MANTA}; if (o1 && isRay(o1) && b2 && isType(b2,val,3) && rayHit(gVehicle(b2),(LaserRay*)gVehicle(o1))) {return;} if (o2 && isRay(o2) && b1 && isType(b1,val,3) && rayHit(gVehicle(b1),(LaserRay*)gVehicle(o2))) {return;} const int N = 10; dContact contact[N]; n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); if (n > 0) { for (i=0; i<n; i++) { Vehicle *v1=NULL,*v2=NULL; Structure *s1=NULL, *s2=NULL; gVehicle(v1,v2,dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2),s1,s2,contact[i].geom.g1,contact[i].geom.g2); // Bullets if ((isAction(v1) && isWalrus(v2) && isMineFire(v2,(Gunshot*)v1)) || (isAction(v2) && isWalrus(v1) && isMineFire(v1,(Gunshot*)v2))) { // Water buyoncy reaction contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1; contact[i].surface.mu = 0.0f; contact[i].surface.slip1 = 1.0f; contact[i].surface.slip2 = 1.0f; contact[i].surface.soft_erp = 1.0f; // 0 in both will force the surface to be tight. contact[i].surface.soft_cfm = 1.0f; } else if ( isAction(v1) || isAction(v2)) { contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1; contact[i].surface.mu = 0; contact[i].surface.slip1 = 0.1f; contact[i].surface.slip2 = 0.1f; if (isAction(v1) && isCarrier(v2) && hit(v2,(Gunshot*)v1)) {} if (isAction(v2) && isCarrier(v1) && hit(v1,(Gunshot*)v2)) {} if (isAction(v1) && isManta(v2) && hit(v2,(Gunshot*)v1)) {} if (isAction(v2) && isManta(v1) && hit(v1,(Gunshot*)v2)) {} if (isAction(v1) && isWalrus(v2) && hit(v2,(Gunshot*)v1)) {} if (isAction(v2) && isWalrus(v1) && hit(v1,(Gunshot*)v2)) {} if (isAction(v1) && s2 && hit(s2)) {} if (isAction(v2) && s1 && hit(s1)) {} } else if ( ( isManta(v1) && isCarrier(v2) && releasecontrol(v1) ) || ( isManta(v2) && isCarrier(v1) && releasecontrol(v2) ) ) { // Manta landing on Carrier contact[i].surface.mode = dContactBounce | dContactApprox1; contact[i].surface.mu = dInfinity; contact[i].surface.slip1 = 0.0f; contact[i].surface.slip2 = 0.0f; contact[i].surface.bounce = 0.2f; } else if (isRunway(s1) || isRunway(s2)) { // Manta landing on Runways. contact[i].surface.mode = dContactBounce | dContactApprox1; contact[i].surface.mu = 0.99f; contact[i].surface.slip1 = 0.9f; contact[i].surface.slip2 = 0.9f; contact[i].surface.bounce = 0.2f; if ( isRunway(s1) && isManta(v2) && landed(v2, s1->island)) {} if ( isRunway(s2) && isManta(v1) && landed(v1, s2->island)) {} } else if (isIsland(contact[i].geom.g1) || isIsland(contact[i].geom.g2)) { // Island reaction contact[i].surface.mode = dContactBounce | dContactApprox1; contact[i].surface.mu = 0; contact[i].surface.bounce = 0.2f; contact[i].surface.slip1 = 0.1f; contact[i].surface.slip2 = 0.1f; contact[i].surface.soft_erp = 0; // 0 in both will force the surface to be tight. contact[i].surface.soft_cfm = 0; // Carrier stranded and Walrus arrived on island. if (isIsland(contact[i].geom.g1) && isCarrier(v2) && stranded(v2,getIsland(contact[i].geom.g1))) {} if (isIsland(contact[i].geom.g2) && isCarrier(v1) && stranded(v1,getIsland(contact[i].geom.g2))) {} if (isIsland(contact[i].geom.g1) && isWalrus(v2) && arrived(v2,getIsland(contact[i].geom.g1))) {} if (isIsland(contact[i].geom.g2) && isWalrus(v1) && arrived(v1,getIsland(contact[i].geom.g2))) {} } else if (ground == contact[i].geom.g1 || ground == contact[i].geom.g2 ) { // Water buyoncy reaction contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1; contact[i].surface.mu = 0.0f; contact[i].surface.slip1 = 0.1f; contact[i].surface.slip2 = 0.1f; contact[i].surface.soft_erp = .5f; // 0 in both will force the surface to be tight. contact[i].surface.soft_cfm = .3f; // Walrus reaching shore. if (ground == contact[i].geom.g1 && isWalrus(v2) && departed(v2)) {} if (ground == contact[i].geom.g2 && isWalrus(v1) && departed(v1)) {} if (ground == contact[i].geom.g1 && v2 && isManta(v2) && groundcollisions(v2)) {} if (ground == contact[i].geom.g2 && v1 && isManta(v1) && groundcollisions(v1)) {} } else { /** // Water buyoncy reaction contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1; contact[i].surface.mu = 0.0f; contact[i].surface.slip1 = 0.1f; contact[i].surface.slip2 = 0.1f; contact[i].surface.soft_erp = .5f; // 0 in both will force the surface to be tight. contact[i].surface.soft_cfm = .3f; **/ if (v1 && isManta(v1) && groundcollisions(v1)) {} if (v2 && isManta(v2) && groundcollisions(v2)) {} } dJointID c = dJointCreateContact (world,contactgroup,&contact[i]); dJointAttach (c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2)); } } }
void orbit(playernum, int governor, int apcount) { int sh; int i; int iq; planettype *p; shiptype *s; placetype where; orbitinfo oi; oi.DontDispStars = 0; oi.DontDispShips = oi.DontDispStars; oi.DontDispPlanets = oi.DontDispShips; oi.DontDispNum = -1; /* Find options, set flags accordingly */ if (optn) { if (opts['s']) { oi.DontDispShips = 1; } if (opts['S']) { oi.Dontdispstars = 1; } if (opts['p']) { oi.DontDispPlanets = 1; } if (opts['d']) { or.DontDispNum = opts['d']; if (oi.DontDispNum) { /* Make a '1' into a '0' */ --oi.DontDispNum; } else { sprintf(buf, "Bad number %d.\n", oi.DontDispNum); notify(playernum, governor, buf); oi.DontDispNum = -1; } } } if (argn == 1) { where = Getplace(playernum, governor, ":", 0); if (Dir[playernum - 1][governor].level == LEVEL_UNIV) { i = 1; } else { i = 0; } oi.Lastx = Dir[playernum - 1][governor].lastx[i]; oi.Lasty = Dir[playernum - 1][governor].lasty[i]; oi.Zoom = Dir[playernum - 1][governor].zoom[i]; } else { where = Getplace(playernum, governor, args[argn - 1], 0); oi.Lasty = 0.0; oi.Lastx = oi.Lasty; oi.Zoom = 1.0; } if (where.err) { notify(playernum, governor, "Orbit: Error in args.\n"); return; } /* Display CSP orbit instead, if the client can understand it */ if (client_can_understand(playernum, governor, CSP_ORBIT_OUTPUT_INTRO)) { csp_orbit(playernum, governor, &oi); return; } /* Orbit type of map */ notify(playernum, governor, "#"); race = races[playernum - 1]; switch (where.level) { case LEVEL_UNIV: for (i = 0; i < Sdata.numstars; ++i) { if (oi.DontdispNum != i) { DispStar(playernum, governor, LEVEL_UNIV, Stars[i], (int)race->God, buf, &oi); notify(playernum, governor, buf); } } if (!oi.DontDispShips) { sh = Sdata.ships; while (sh) { getship(&s, sh); if (oi.DontDispNum != sh) { DispShip(playernum, governor, &where, s, NULL, (int)race->God, buf, &oi); notify(playernum, governor, buf); } sh = nextship(s); free(s); } } break; case LEVEL_STAR: DispStar(playernum, governor, LEVEL_STAR, Stars[where.snum], (int)race->God, buf, &oi); notify(playernum, governor, buf); for (i = 0; i < Stars[where.snum]->numplanets; ++i) { if (oi.DontDispNum != i) { getplanet(&p, (int)where.snum, i); DispPlanet(playernum, governor, LEVEL_STAR, p, Stars[where.snum]->pnames[i], race, buf, &oi); notify(playernum, governor, buf); free(p); } } /* * Check to see if you have ships orbiting the star, if so you can see * enemy ships */ iq = 0; if (race->God) { iq = 1; } else { sh = Stars[where.snum]->ships; while (sh && !iq) { getship(&s, sh); if ((s->owner == playernum) && ((s->type == OTYPE_PROBE) || s->popn)) { /* You are there to sight, need a crew */ iq = 1; } sh = nextship(s); free(s); } } if (!oi.DontDispShips) { sh = Stars[where].snum->ships; while (sh) { getship(&s, sh); if ((oi.DontDispNum != sh) && ((s->owner == playernum) || (s->type == STYPE_MINEF))) { if ((s->owner == playernum) || (iq == 1)) { DispShip(playernum, governor, &where, s, NULL, (int)race->God, buf, &oi); notify(playernum, governor, buf); } } sh = nextship(s); free(s); } } break; case LEVEL_PLAN: getplanet(&p, (int)where.snum, (int)where.pnum); DispPlanet(playernum, governor, LEVEL_PLAN, p, Stars[where.snum]->pnames[where.pnum], race, buf, &oi); notify(playernum, governor, buf); /* * Check to see if you have ships landed or orbiting the planet, if so * you can see orbiting enemy ships */ iq = 0; sh = p->ships; while (sh && !iq) { getship(&s, sh); if ((s->owner == playernum) && ((s->type == OTYPE_PROBE) || s->popn)) { /* You are there to sight, need a crew */ iq = 1; } sh = nextship(s); free(s); } /* End check */ if (!oi.DontDispShips) { sh = p->ships; while (sh) { getship(&s, sh); if (oi.DontDispNum != sh) { if (!landed(s)) { if ((s->owner == playernum) || (iq == 1)) { DispShip(playernum, governor, &where, s, p, (int)race->God, buf, &oi); notify(playernum, governor, buf); } } } sh = nextship(s); free(s); } } free(p); break; default: notify(playernum, governor, "Bad scope.\n"); return; } notify(playernum, governor, "\n"); }
void orbit(int Playernum, int Governor, int APcount) { register int sh,i,iq; int DontDispNum= -1, flag; planettype *p; shiptype *s; placetype where; int DontDispPlanets, DontDispShips, DontDispStars; char output[100000]; DontDispPlanets = DontDispShips = DontDispStars = 0; /* find options, set flags accordingly */ for (flag=1; flag<=argn-1; flag++) if (*args[flag]=='-') { for (i=1; args[flag][i]!='\0'; i++) switch (args[flag][i]) { case 's': DontDispShips = 1; break; case 'S': DontDispStars = 1; break; case 'p': DontDispPlanets = 1; break; default: if (sscanf(args[flag]+1,"%d",&DontDispNum)!=1) { sprintf(buf, "Bad number %s.\n", args[flag]+1); notify(Playernum, Governor, buf); DontDispNum = -1; } if (DontDispNum) DontDispNum--; /* make a '1' into a '0' */ break; } } if (argn==1) { where = Getplace(Playernum, Governor, ":", 0); i = (Dir[Playernum-1][Governor].level==LEVEL_UNIV); Lastx = Dir[Playernum-1][Governor].lastx[i]; Lasty = Dir[Playernum-1][Governor].lasty[i]; Zoom = Dir[Playernum-1][Governor].zoom[i]; } else { where = Getplace(Playernum, Governor, args[argn-1], 0); Lastx = Lasty = 0.0; Zoom = 1.1; } if (where.err) { notify(Playernum, Governor, "orbit: error in args.\n"); return; } /* orbit type of map */ sprintf(output, "#"); Race = races[Playernum-1]; switch (where.level) { case LEVEL_UNIV: for (i=0; i<Sdata.numstars; i++) if (DontDispNum!=i) { DispStar(Playernum, Governor, LEVEL_UNIV, Stars[i], DontDispStars, (int)Race->God, buf); strcat(output, buf); } if (!DontDispShips) { sh = Sdata.ships; while (sh) { (void)getship(&s, sh); if (DontDispNum != sh) { DispShip(Playernum, Governor, &where, s, NULL, (int)Race->God, buf); strcat(output, buf); } sh = s->nextship; free(s); } } break; case LEVEL_STAR: DispStar(Playernum, Governor, LEVEL_STAR, Stars[where.snum], DontDispStars, (int)Race->God, buf); strcat(output, buf); for (i=0; i<Stars[where.snum]->numplanets; i++) if (DontDispNum!=i) { getplanet(&p,(int)where.snum,i); DispPlanet(Playernum, Governor, LEVEL_STAR, p, Stars[where.snum]->pnames[i],DontDispPlanets, Race, buf); strcat(output, buf); free(p); } /* check to see if you have ships at orbiting the star, if so you can see enemy ships */ iq = 0; if(Race->God) iq = 1; else { sh = Stars[where.snum]->ships; while (sh && !iq) { (void)getship(&s, sh); if(s->owner == Playernum && Sight(s)) iq = 1; /* you are there to sight, need a crew */ sh = s->nextship; free(s); } } if (!DontDispShips) { sh = Stars[where.snum]->ships; while (sh) { (void)getship(&s, sh); if (DontDispNum != sh && !(s->owner != Playernum && s->type == STYPE_MINE) ) { if((s->owner == Playernum) || (iq == 1)) { DispShip(Playernum, Governor, &where, s, NULL, (int)Race->God, buf); strcat(output, buf); } } sh = s->nextship; free(s); } } break; case LEVEL_PLAN: getplanet(&p,(int)where.snum,(int)where.pnum); DispPlanet(Playernum, Governor, LEVEL_PLAN, p, Stars[where.snum]->pnames[where.pnum], DontDispPlanets, Race, buf); strcat(output, buf); /* check to see if you have ships at landed or orbiting the planet, if so you can see orbiting enemy ships */ iq = 0; sh = p->ships; while (sh && !iq) { (void)getship(&s, sh); if(s->owner == Playernum && Sight(s)) iq = 1; /* you are there to sight, need a crew */ sh = s->nextship; free(s); } /* end check */ if (!DontDispShips) { sh = p->ships; while (sh) { (void)getship(&s, sh); if (DontDispNum != sh) { if(!landed(s)) { if((s->owner == Playernum) || (iq ==1)) { DispShip(Playernum, Governor, &where, s, p, (int)Race->God, buf); strcat(output, buf); } } } sh = s->nextship; free(s); } } free(p); break; default: notify(Playernum, Governor,"Bad scope.\n"); return; } strcat(output, "\n"); notify(Playernum, Governor, output); }
void domine(int shipno, int detonate) { int sh,sh2,i; shiptype *s, *ship; planettype *planet; racetype *r; (void)getship(&ship, shipno); if(ship->type!=STYPE_MINE || !ship->alive || !ship->owner) { free(ship); return; } /* check around and see if we should explode. */ if (ship->on || detonate) { int rad=0; double xd,yd,range; switch(ship->whatorbits) { case LEVEL_STAR: sh = Stars[ship->storbits]->ships; break; case LEVEL_PLAN: getplanet(&planet, (int)ship->storbits, (int)ship->pnumorbits); sh=planet->ships; free(planet); break; default: free(ship); return; } sh2 = sh; /* traverse the list, look for ships that are closer than the trigger radius... */ rad = 0; if(!detonate) { r = races[ship->owner-1]; while (sh && !rad) { (void)getship(&s, sh); xd = s->xpos - ship->xpos; yd = s->ypos - ship->ypos; range = sqrt(xd*xd + yd*yd); if( !isset(r->allied, s->owner) && (s->owner != ship->owner) && ( (int)range <= ship->special.trigger.radius) ) rad = 1; else sh = s->nextship; free(s); } } else rad = 1; if (rad) { sprintf(buf, "%s detonated at %s\n", Ship(ship), prin_ship_orbits(ship)); post(buf, COMBAT); notify_star((int)ship->owner, (int)ship->governor, 0, (int)ship->storbits, buf); sh = sh2 ; while (sh) { (void)getship(&s, sh); if (sh != shipno && s->alive && (s->type != OTYPE_CANIST) && (s->type!=OTYPE_GREEN)) { rad = shoot_ship_to_ship(ship, s, (int)(ship->destruct), 0, 0, long_buf, short_buf); if(rad>0) { post(short_buf, COMBAT); warn((int)s->owner, (int)s->governor, long_buf); putship(s); } } sh = s->nextship; free(s); } /* if the mine is in orbit around a planet, nuke the planet too! */ if(ship->whatorbits==LEVEL_PLAN) { /* pick a random sector to nuke */ reg int x,y,numdest; getplanet(&planet, (int)ship->storbits, (int)ship->pnumorbits); if(landed(ship)) { x = ship->land_x; y = ship->land_y; } else { x=int_rand(0, (int)planet->Maxx-1); y=int_rand(0, (int)planet->Maxy-1); } numdest=shoot_ship_to_planet(ship, planet, (int)(ship->destruct), x, y, 1, 0, LIGHT, long_buf, short_buf); putplanet(planet, (int)ship->storbits, (int)ship->pnumorbits); sprintf(telegram_buf, "%s", buf); if(numdest>0) { sprintf(buf, " - %d sectors destroyed.",numdest); strcat(telegram_buf, buf); } strcat(telegram_buf, "\n"); for(i=1; i<=Num_races; i++) if(Nuked[i-1]) warn(i, (int)Stars[ship->storbits]->governor[i-1], telegram_buf); notify((int)(ship->owner), (int)ship->governor, telegram_buf); free(planet); } kill_ship((int)(ship->owner), ship); } putship(ship); } free(ship); }