diff --git a/src/game/mod.rs b/src/game/mod.rs index d52c9f0..a72ab60 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -892,10 +892,13 @@ impl Game { let Some(def) = reg.items.get(&inst.def) else { return }; let name = self.item_label(&inst, reg); - let target = if self.enemies.is_empty() { - CreatureRef::Player - } else { - CreatureRef::Enemy(0) + // TODO(M5): Ein Gegenstand trifft immer den ersten Gegner. Seit der + // Kampf-Screen einen Zielcursor hat, ist das eine Luecke — + // sie faellt erst auf, wenn `core` den ersten Wurfgegenstand + // bekommt. Dann traegt `UseItem` ein Ziel wie `UseAbility`. + let target = match self.enemies.iter().position(|e| e.is_alive()) { + Some(i) => CreatureRef::Enemy(i), + None => CreatureRef::Player, }; for action in &def.actions { self.apply(action, CreatureRef::Player, target, reg); @@ -1749,4 +1752,23 @@ mod tests { assert!(game.enemies.is_empty()); assert!(game.journal.iter().any(|z| z.contains("geräumt")), "{:?}", game.journal); } + + /// Im Kampf trinken zu koennen ist eine Entscheidung — Zug gegen Leben. + /// Der Spielkern hat es immer erlaubt, nur der Kampf-Screen hatte keine + /// Taste dafuer; der Test haelt fest, dass die Erlaubnis echt ist. + #[test] + fn ein_trank_im_kampf_kostet_einen_zug() { + let (mut game, reg) = zwergenkrieger(); + let ratte = reg.creatures.get("core:rat").expect("Riesenratte"); + game.enemies = vec![Creature::from_def(ratte)]; + game.give(ItemInstance::stack("core:health_potion", 2), ®); + let platz = game.player.inventory.len() - 1; + game.player.health = 10.0; + + let vorher = game.turn; + assert!(matches!(game.execute(Command::UseItem(platz), ®), Outcome::TurnPassed)); + assert!(game.player.health > 10.0, "der Trank wirkt auch im Kampf"); + assert_eq!(game.turn, vorher + 1, "und er kostet den Zug"); + assert_eq!(game.count_of("core:health_potion"), 1); + } } diff --git a/src/ui/app.rs b/src/ui/app.rs index d0efb10..4a36e23 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -483,7 +483,7 @@ fn draw_combat( zeilen.push(Line::from(namen.join(", ")).style(Style::new().fg(Color::Green))); } zeilen.push( - Line::from("Tab Seite · ↑↓ wählen · 1-9 Ziel · Enter angreifen · . warten · c Bogen") + Line::from("Tab Seite · ↑↓ wählen · Enter angreifen · i Inventar · . warten · c Bogen") .style(Style::new().fg(Color::DarkGray)), ); diff --git a/src/ui/screen.rs b/src/ui/screen.rs index f3f80b5..2178c04 100644 --- a/src/ui/screen.rs +++ b/src/ui/screen.rs @@ -162,6 +162,9 @@ impl Screen { } KeyCode::Char('.') => Response::Command(Command::Wait), KeyCode::Char('c') => Response::Push(Screen::CharacterSheet), + // Derselbe Screen wie draussen. `rejects` verbietet + // `UseItem` im Kampf nicht — es fehlte nur die Tuer. + KeyCode::Char('i') => Response::Push(Screen::Inventory { pick: 0 }), KeyCode::F(12) => Response::Push(Screen::Debug { pick: 0 }), _ => Response::None, }