static void spathi_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; EVALUATE_DESC *lpEvalDesc; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 24) { COUNT travel_facing, direction_facing; SIZE delta_x, delta_y; travel_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity) + HALF_CIRCLE) ); delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); if (NORMALIZE_FACING (direction_facing - (StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)) + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE) && (lpEvalDesc->which_turn <= 8 || NORMALIZE_FACING (direction_facing + ANGLE_TO_FACING (HALF_CIRCLE) - ANGLE_TO_FACING (GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity )) + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE)) && (!(StarShipPtr->cur_status_flags & (SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL)) || NORMALIZE_FACING (direction_facing - travel_facing + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE))) StarShipPtr->ship_input_state |= SPECIAL; } }
static void doggy_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->special_counter; if (ElementPtr->thrust_wait > 0) /* could be non-zero after a collision */ --ElementPtr->thrust_wait; else { COUNT facing, orig_facing; SIZE delta_facing; facing = orig_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) )); if ((delta_facing = TrackShip (ElementPtr, &facing)) < 0) facing = NORMALIZE_FACING (TFB_Random ()); else { ELEMENT *ShipPtr; LockElement (ElementPtr->hTarget, &ShipPtr); facing = NORMALIZE_FACING (ANGLE_TO_FACING ( ARCTAN (ShipPtr->current.location.x - ElementPtr->current.location.x, ShipPtr->current.location.y - ElementPtr->current.location.y) )); delta_facing = NORMALIZE_FACING (facing - GetFrameIndex (ShipPtr->current.image.frame)); UnlockElement (ElementPtr->hTarget); if (delta_facing > ANGLE_TO_FACING (HALF_CIRCLE - OCTANT) && delta_facing < ANGLE_TO_FACING (HALF_CIRCLE + OCTANT)) { if (delta_facing >= ANGLE_TO_FACING (HALF_CIRCLE)) facing -= ANGLE_TO_FACING (QUADRANT); else facing += ANGLE_TO_FACING (QUADRANT); } facing = NORMALIZE_FACING (facing); } if (facing != orig_facing) SetVelocityVector (&ElementPtr->velocity, DOGGY_SPEED, facing); } }
static void bubble_preprocess (ELEMENT *ElementPtr) { BYTE thrust_wait, turn_wait; thrust_wait = HINIBBLE (ElementPtr->turn_wait); turn_wait = LONIBBLE (ElementPtr->turn_wait); if (thrust_wait > 0) --thrust_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; thrust_wait = (BYTE)((COUNT)TFB_Random () & 3); } if (turn_wait > 0) --turn_wait; else { COUNT facing; SIZE delta_facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity))); if ((delta_facing = TrackShip (ElementPtr, &facing)) == -1) facing = (COUNT)TFB_Random (); else if (delta_facing <= ANGLE_TO_FACING (HALF_CIRCLE)) facing += (COUNT)TFB_Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); else facing -= (COUNT)TFB_Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); #define TRACK_WAIT 2 turn_wait = TRACK_WAIT; } ElementPtr->turn_wait = MAKE_BYTE (turn_wait, thrust_wait); }
static void flak_preprocess (ELEMENT *ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { SIZE angle, delta_speed; angle = GetVelocityTravelAngle (&ElementPtr->velocity); delta_speed = WORLD_TO_VELOCITY (MISSILE_DECELERATION); DeltaVelocityComponents (&ElementPtr->velocity, (SIZE)COSINE (angle, -delta_speed), (SIZE)SINE (angle, -delta_speed)); ElementPtr->turn_wait = MISSILE_DECEL_WAIT; ElementPtr->state_flags |= CHANGING; } }
static void blaster_preprocess (ELEMENT *ElementPtr) { BYTE wait; switch (ElementPtr->mass_points) { case BLASTER_DAMAGE * 1: if (GetFrameIndex (ElementPtr->current.image.frame) < 8) { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; } break; case BLASTER_DAMAGE * 3: if (GetFrameIndex (ElementPtr->current.image.frame) < 19) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 16); ElementPtr->state_flags |= CHANGING; break; } if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else if ((wait = HINIBBLE (ElementPtr->turn_wait))) { COUNT facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity))); if (TrackShip (ElementPtr, &facing) > 0) SetVelocityVector (&ElementPtr->velocity, BLASTER_SPEED, facing); ElementPtr->turn_wait = MAKE_BYTE (wait, wait); } }
static void thraddash_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; EVALUATE_DESC *lpEvalDesc; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { #define STATIONARY_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (4)) SIZE dx, dy; GetCurrentVelocityComponents ( &lpEvalDesc->ObjectPtr->velocity, &dx, &dy ); if (lpEvalDesc->which_turn > 8 || (long)dx * dx + (long)dy * dy <= (long)STATIONARY_SPEED * STATIONARY_SPEED) lpEvalDesc->MoveState = PURSUE; else lpEvalDesc->MoveState = ENTICE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE) { if ((StarShipPtr->ship_input_state & THRUST) || (ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) || NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle ( &ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->velocity ) + HALF_CIRCLE + OCTANT) - StarShipPtr->ShipFacing) > ANGLE_TO_FACING (QUADRANT)) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->ObjectPtr) { if (lpEvalDesc->MoveState == PURSUE) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST + SPECIAL_ENERGY_COST && ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT)) && (!(StarShipPtr->cur_status_flags & SPECIAL) || !(StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)))) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->MoveState == ENTICE) { COUNT direction_angle; SIZE delta_x, delta_y; delta_x = lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; direction_angle = ARCTAN (delta_x, delta_y); if ((lpEvalDesc->which_turn > 24 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) || (lpEvalDesc->which_turn <= 16 && NORMALIZE_ANGLE (direction_angle - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + QUADRANT) <= HALF_CIRCLE && (lpEvalDesc->which_turn < 12 || NORMALIZE_ANGLE (direction_angle - (GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity ) + HALF_CIRCLE) + (OCTANT + 2)) <= ((OCTANT + 2) << 1)))) StarShipPtr->ship_input_state |= SPECIAL; } } if ((StarShipPtr->ship_input_state & SPECIAL) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST) StarShipPtr->ship_input_state &= ~THRUST; } }
static void mmrnmhrm_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { BOOLEAN CanTransform; EVALUATE_DESC *lpEvalDesc; STARSHIP *StarShipPtr; STARSHIP *EnemyStarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); CanTransform = (BOOLEAN)(StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->ship_info.energy_level >= StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); StarShipPtr->ship_input_state &= ~SPECIAL; if (CanTransform && lpEvalDesc->ObjectPtr && !(StarShipPtr->ship_input_state & WEAPON)) { SIZE delta_x, delta_y; COUNT travel_angle, direction_angle; GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, &delta_x, &delta_y); if (delta_x == 0 && delta_y == 0) direction_angle = travel_angle = 0; else { delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_angle = ARCTAN (-delta_x, -delta_y); travel_angle = GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity ); } if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { if (lpEvalDesc->which_turn > 8) { if (MANEUVERABILITY (&EnemyStarShipPtr->RaceDescPtr->cyborg_control) <= SLOW_SHIP || NORMALIZE_ANGLE ( direction_angle - travel_angle + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } } else { SIZE ship_delta_x, ship_delta_y; GetCurrentVelocityComponents (&ShipPtr->velocity, &ship_delta_x, &ship_delta_y); delta_x -= ship_delta_x; delta_y -= ship_delta_y; travel_angle = ARCTAN (delta_x, delta_y); if (lpEvalDesc->which_turn < 16) { if (lpEvalDesc->which_turn <= 8 || NORMALIZE_ANGLE ( direction_angle - travel_angle + OCTANT ) <= QUADRANT) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->which_turn > 32 && NORMALIZE_ANGLE ( direction_angle - travel_angle + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } } if (ShipPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { if (!(StarShipPtr->ship_input_state & SPECIAL) && lpEvalDesc->ObjectPtr) StarShipPtr->ship_input_state |= WEAPON; else StarShipPtr->ship_input_state &= ~WEAPON; } }
static COUNT initialize_flak (ELEMENT *ShipPtr, HELEMENT MissileArray[]) { COUNT i; STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.pixoffs = SPATHI_FORWARD_OFFSET; MissileBlock.speed = (MISSILE_SPEED << RESOLUTION_FACTOR); MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = flak_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; for(i = 0; i < 3; ++i) { if (i == 0) { MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; } else if (i == 1) { MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 12); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 12); } else if (i == 2) { MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -12); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -12); } if ((MissileArray[i] = initialize_missile (&MissileBlock))) { SIZE dx, dy, angle, speed; ELEMENT *MissilePtr; LockElement (MissileArray[i], &MissilePtr); if (i > 0) { angle = GetVelocityTravelAngle (&MissilePtr->velocity); GetCurrentVelocityComponents(&MissilePtr->velocity, &dx, &dy); speed = square_root (dx*dx + dy*dy); if (i == 1) angle += 1; else if (i == 2) angle -= 1; SetVelocityComponents(&MissilePtr->velocity, COSINE(angle, speed), SINE(angle, speed)); } GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); // Add the Eluder's velocity to its projectiles. DeltaVelocityComponents (&MissilePtr->velocity, dx, dy); MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); MissilePtr->turn_wait = 1; UnlockElement (MissileArray[i]); } } return (3); }
void AbandonShip (ELEMENT *ShipPtr, ELEMENT *TargetPtr, COUNT crew_loss) { SIZE dx, dy; COUNT direction; RECT r; STARSHIP *StarShipPtr; HELEMENT hCrew; INTERSECT_CONTROL ShipIntersect; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) return; ShipIntersect = ShipPtr->IntersectControl; GetFrameRect (ShipIntersect.IntersectStamp.frame, &r); if ((direction = GetVelocityTravelAngle ( &ShipPtr->velocity)) == FULL_CIRCLE) dx = dy = 0; else { #define MORE_THAN_ENOUGH 100 direction += HALF_CIRCLE; dx = COSINE (direction, MORE_THAN_ENOUGH); dy = SINE (direction, MORE_THAN_ENOUGH); } while (crew_loss-- && (hCrew = AllocElement ())) { #define CREW_LIFE 300 ELEMENT *CrewPtr; DeltaCrew (ShipPtr, -1); PutElement (hCrew); LockElement (hCrew, &CrewPtr); CrewPtr->playerNr = NEUTRAL_PLAYER_NUM; CrewPtr->hit_points = 1; CrewPtr->state_flags = APPEARING | FINITE_LIFE | CREW_OBJECT; CrewPtr->life_span = CREW_LIFE; SetPrimType (&DisplayArray[CrewPtr->PrimIndex], POINT_PRIM); SetPrimColor (&DisplayArray[CrewPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); CrewPtr->current.image.frame = DecFrameIndex (stars_in_space); CrewPtr->current.image.farray = &stars_in_space; CrewPtr->preprocess_func = crew_preprocess; CrewPtr->collision_func = crew_collision; SetElementStarShip (CrewPtr, StarShipPtr); GetElementStarShip (TargetPtr, &StarShipPtr); CrewPtr->hTarget = StarShipPtr->hShip; { SIZE w, h; INTERSECT_CONTROL CrewIntersect; ShipIntersect.IntersectStamp.origin = ShipPtr->IntersectControl.EndPoint; w = (SIZE)((COUNT)TFB_Random () % r.extent.width); h = (SIZE)((COUNT)TFB_Random () % r.extent.height); CrewIntersect.EndPoint = ShipIntersect.EndPoint; CrewIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); if (dx == 0 && dy == 0) { CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); CrewIntersect.IntersectStamp.origin = TargetPtr->IntersectControl.EndPoint; } else { if (dx == 0) CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); else if (dx > 0) CrewIntersect.EndPoint.x += w; else CrewIntersect.EndPoint.x -= w; if (dy == 0) CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); else if (dy > 0)