I wrote an aimbot for a FPS game.
The basic idea:
Take all the players, and all the buildings.
Filter out those that aren't enemies.
Filter out those that are currently invincible.
Transform that into a list of actual points in worldspace- the hitboxes for players, the AABB centers for buildings. (Not all player models have the same hitbox count.) Unless we are holding a weapon that does splash damage- then go for the feet on players (their origin). And if we hold a projectile weapon, do prediction based on the player's velocity.
Now transform each point into a 2-tuple (position, score), based on some heuristics implemented in another function.
Do a raycast to each point. Filter out those that can't be hit.
Take the point with the highest score, if there is one, and set our viewangles to aim at it. Otherwise leave them alone.
The actual implementation of this looked something like this:
let target = get_players().chain(get_buildings)
.filter(|e| are_enemies(me, e))
.filter(is_vulnerable)
.flat_map(entity_to_scored_aimpoints)
.filter(|(score, point)| trace(me_eyes_predicted, point).fraction > 0.999)
.max_by(|(score, point)| score);
if let Some(target) = target {
aimray = target - me_eyes_predicted;
viewangles = vector_to_angles(aimray);
}
(Note that max_by is just a special case of reduce/fold; in my experience, you rarely want to use reduce directly; there's probably a more ergonomic wrapper. Sometimes you do, though.)
To me, that's pretty readable (stuff specific to the game aside, like the trace.fraction ugliness- fraction is "how far" the trace got before hitting something, 1.0 meaning there's nothing in the way. the comparison is to handle some floating-point inaccuracy there), and handles some really annoying cases properly.