void StarSystem::ExecuteUnitAI() { try { Unit *unit = NULL; for (un_iter iter = getUnitList().createIterator(); (unit = *iter); ++iter) { unit->ExecuteAI(); unit->ResetThreatLevel(); } } catch (const boost::python::error_already_set) { if ( PyErr_Occurred() ) { PyErr_Print(); PyErr_Clear(); fflush( stderr ); fflush( stdout ); } throw; } }
void StarSystem::UpdateUnitPhysics( bool firstframe ) { static bool phytoggle = true; static int batchcount = SIM_QUEUE_SIZE-1; double aitime = 0; double phytime = 0; double collidetime = 0; double flattentime = 0; double bolttime = 0; targetpick = 0; aggfire = 0; numprocessed = 0; stats.CheckVitals( this ); if (phytoggle) { for (++batchcount; batchcount > 0; --batchcount) { //BELOW COMMENTS ARE NO LONGER IN SYNCH //NOTE: Randomization is necessary to preserve scattering - otherwise, whenever a //unit goes from low-priority to high-priority and back to low-priority, they //get synchronized and start producing peaks. //NOTE2: But... randomization must come only on priority changes. Otherwise, it may //interfere with subunit scheduling. Luckily, all units that make use of subunit //scheduling also require a constant base priority, since otherwise priority changes //will wreak havoc with subunit interpolation. Luckily again, we only need //randomization on priority changes, so we're fine. try { Unit *unit = NULL; for (un_iter iter = physics_buffer[current_sim_location].createIterator(); (unit = *iter); ++iter) { int priority = UnitUtil::getPhysicsPriority( unit ); //Doing spreading here and only on priority changes, so as to make AI easier int predprior = unit->predicted_priority; //If the priority has really changed (not an initial scattering, because prediction doesn't match) if (priority != predprior) { if (predprior == 0) //Validate snapshot of current interpolated state (this is a reschedule) unit->curr_physical_state = unit->cumulative_transformation; //Save priority value as prediction for next scheduling, but don't overwrite yet. predprior = priority; //Scatter, so as to achieve uniform distribution priority = 1+( ( (unsigned int) vsrandom.genrand_int32() )%priority ); } float backup = SIMULATION_ATOM; theunitcounter = theunitcounter+1; SIMULATION_ATOM *= priority; unit->sim_atom_multiplier = priority; double aa = queryTime(); unit->ExecuteAI(); double bb = queryTime(); unit->ResetThreatLevel(); //FIXME "firstframe"-- assume no more than 2 physics updates per frame. unit->UpdatePhysics( identity_transformation, identity_matrix, Vector( 0, 0, 0 ), priority == 1 ? firstframe : true, &this->gravitationalUnits(), unit ); double cc = queryTime(); aitime += bb-aa; phytime += cc-bb; SIMULATION_ATOM = backup; unit->predicted_priority = predprior; } } catch (const boost::python::error_already_set) { if ( PyErr_Occurred() ) { PyErr_Print(); PyErr_Clear(); fflush( stderr ); fflush( stdout ); } throw; } double c0 = queryTime(); Bolt::UpdatePhysics( this ); double cc = queryTime(); last_collisions.clear(); double fl0 = queryTime(); collidemap[Unit::UNIT_BOLT]->flatten(); if (Unit::NUM_COLLIDE_MAPS > 1) collidemap[Unit::UNIT_ONLY]->flatten( *collidemap[Unit::UNIT_BOLT] ); flattentime = queryTime()-fl0; Unit *unit; for (un_iter iter = physics_buffer[current_sim_location].createIterator(); (unit = *iter);) { int priority = unit->sim_atom_multiplier; float backup = SIMULATION_ATOM; SIMULATION_ATOM *= priority; unsigned int newloc = (current_sim_location+priority)%SIM_QUEUE_SIZE; unit->CollideAll(); SIMULATION_ATOM = backup; if (newloc == current_sim_location) ++iter; else iter.moveBefore( physics_buffer[newloc] ); } double dd = queryTime(); collidetime += dd-cc; bolttime += cc-c0; current_sim_location = (current_sim_location+1)%SIM_QUEUE_SIZE; ++physicsframecounter; totalprocessed += theunitcounter; theunitcounter = 0; } } else { Unit *unit = NULL; for (un_iter iter = getUnitList().createIterator(); (unit = *iter); ++iter) { unit->ExecuteAI(); last_collisions.clear(); unit->UpdatePhysics( identity_transformation, identity_matrix, Vector( 0, 0, 0 ), firstframe, &this->gravitationalUnits(), unit ); unit->CollideAll(); } } }