coding-horror/basic-computer-games · error
AI RAN OUT OF OPTIONS!
Error message
AI RAN OUT OF OPTIONS!
What it means
A panic via .expect("AI RAN OUT OF OPTIONS!") on Iterator::choose() over all_positions in ai_turn() of the Bombardment Rust port. choose() returns None only when the slice is empty, so this fires when the AI has no remaining board positions to target. all_positions is meant to track every not-yet-fired cell; reaching an empty vector before the game is won indicates a logic/state bug (the AI firing loop is being entered after the position pool was exhausted).
Source
Thrown at 11_Bombardment/rust/src/main.rs:95
);
} else {
println!(
"YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN MY TRANSISTO&S RECUP%RA*E!\n\n"
);
return false;
}
} else {
println!("HA, HA YOU MISSED. MY TURN NOW\n");
}
true
}
fn ai_turn(all_positions: &mut Vec<u8>, player_positions: &mut Vec<u8>) -> bool {
std::thread::sleep(Duration::from_secs(1));
let ai_missile = *all_positions
.choose(&mut rand::thread_rng())
.expect("AI RAN OUT OF OPTIONS!");
let index = all_positions
.iter()
.position(|p| p == &ai_missile)
.expect("AI CHOOSE AN INVALID POSITION!");
all_positions.remove(index);
if let Some(index) = player_positions.iter().position(|p| p == &ai_missile) {
player_positions.remove(index);
let remaining = player_positions.len();
if remaining > 0 {
println!("I GOT YOU. IT WON'T BE LONG NOW. POST {ai_missile} WAS HIT.");
println!(
"YOU HAVE ONLY {} OUTPOST LEFT.\n",
get_text_from_number(remaining)View on GitHub (pinned to 5301155192)
Solutions
- Guard ai_turn() with `if all_positions.is_empty() { return false; }` before calling choose.
- Verify the main game loop breaks immediately when either side has no positions left.
- Ensure all_positions is sized to the full board and only one entry is removed per AI turn.
Example fix
// before
let ai_missile = *all_positions
.choose(&mut rand::thread_rng())
.expect("AI RAN OUT OF OPTIONS!");
// after
if all_positions.is_empty() {
return false; // no targets left, end game
}
let ai_missile = *all_positions
.choose(&mut rand::thread_rng())
.expect("AI RAN OUT OF OPTIONS!"); Defensive patterns
Strategy: validation
Validate before calling
// Guard ai_turn before calling choose
fn ai_turn(all_positions: &mut Vec<u8>, player_positions: &mut Vec<u8>) -> bool {
if all_positions.is_empty() { return false; }
// ... existing logic Type guard
// Rust: empty check is the idiomatic guard let has_targets = !all_positions.is_empty();
Try / catch
// Replace .expect with a match on Option
let ai_missile = match all_positions.choose(&mut rand::thread_rng()) {
Some(&p) => p,
None => return false, // no targets left; end game
}; Prevention
- Always check is_empty() before choose()/unwrap() on a Vec.
- Ensure the game loop stops as soon as either side has zero positions.
- Remove exactly one position per AI turn and size all_positions to the full board.
When it happens
Trigger: Calling ai_turn() when all_positions is empty (every cell already consumed); a turn-order bug that lets the AI take extra turns; a victory/loss check that fails to stop the loop before the AI runs out of targets.
Common situations: Miscalibrated board size vs number of turns; a draw/stalemate condition not detected; the game loop not breaking after player_positions hits zero, letting ai_turn run again on an empty pool.
Related errors
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/6b2a376c1949b1db.
Report an issue: GitHub.