fix(kampf): geglueckte Flucht bricht die Initiativreihenfolge ab

Die Reihenfolge steht vor dem Zug fest, Flucht leert `enemies` aber
mitten darin — danach zeigten die Indizes ins Leere und ein Gegner, der
nach dem Helden drankam, stuerzte das Spiel ab.

Zwei Zusagen aus Ticket 14, jede fuer sich richtig, nie zusammen geprueft:
alle Kampftests loesten die Flucht am Ende der Reihenfolge aus.
This commit is contained in:
2026-08-12 20:39:54 +02:00
parent 3a6af6affb
commit 7963df5236
3 changed files with 61 additions and 1 deletions

View File

@@ -503,7 +503,11 @@ impl Game {
}
match who {
CreatureRef::Player => self.perform(&cmd, reg),
CreatureRef::Enemy(i) => self.enemy_acts(i, reg),
CreatureRef::Enemy(i) if i < self.enemies.len() => self.enemy_acts(i, reg),
// Eine geglueckte Flucht leert `enemies` mitten in der
// Reihenfolge — die stand vor dem Zug fest und zeigt danach ins
// Leere. Kein Gegner mehr da heisst: der Zug ist vorbei.
CreatureRef::Enemy(_) => break,
}
// 4. nach *jeder* Handlung leerarbeiten
self.drain_events(reg);
@@ -1559,4 +1563,36 @@ mod tests {
assert_eq!(game.shop_stock().expect("Korb").len(), ware.len() - 1);
assert!(game.player.inventory.iter().any(|i| i.def == ware[0].def));
}
/// Gefunden im Spiel, nicht im Test: Wer oft genug flieht, trifft den Zug,
/// in dem die Flucht **vor** dem Handeln eines Gegners glueckt — dann zeigt
/// die vorher festgelegte Initiativreihenfolge auf einen geleerten `enemies`.
#[test]
fn geglueckte_flucht_bricht_die_initiativreihenfolge_ab() {
let (mut game, reg) = zwergenkrieger();
// Zwei Gegner, damit die Reihenfolge einen Index >0 enthaelt, und ein
// Held in der Mitte, damit nach seiner Flucht noch jemand drankaeme.
let ratte = reg.creatures.values().next().expect("mindestens ein Gegner");
game.enemies = vec![Creature::from_def(ratte), Creature::from_def(ratte)];
for (i, e) in game.enemies.iter_mut().enumerate() {
e.initiative = i as i32;
}
game.player.initiative = 1;
// Flucht liegt bei 10-90 %, nach 30 Zuegen ist sie praktisch sicher.
for _ in 0..30 {
if game.enemies.is_empty() || game.over.is_some() {
break;
}
game.execute(
Command::UseAbility {
ability: String::from("core:flee"),
target: CreatureRef::Player,
},
&reg,
);
}
assert!(game.enemies.is_empty(), "in 30 Zuegen muss eine Flucht geglueckt sein");
}
}