Skip to content

Commit e52c60c

Browse files
authored
Merge pull request #72 from facundoolano/chest_refactor
Unify chest and tombstone handling
2 parents ed2c1b2 + bb35668 commit e52c60c

6 files changed

Lines changed: 86 additions & 61 deletions

File tree

src/datafile/game040.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::character::Character;
22
use crate::game;
3-
use crate::game::tombstone::Tombstone;
3+
use crate::game::chest::Chest;
44
use crate::item::Item;
55
use crate::location::Location;
66
use serde::{Deserialize, Serialize};
@@ -15,7 +15,7 @@ struct Game040 {
1515
pub location: Location,
1616
pub gold: i32,
1717
inventory: HashMap<String, Vec<Box<dyn Item>>>,
18-
tombstones: HashMap<Location, Tombstone>,
18+
tombstones: HashMap<Location, Chest>,
1919
}
2020

2121
/// Get a new Game instance out of a v0.4.0 one
@@ -60,7 +60,7 @@ mod tests {
6060
tombstone_game.add_item("potion", Box::new(item::Potion::new(1)));
6161
game_v4
6262
.tombstones
63-
.insert(Location::home(), Tombstone::drop(&mut tombstone_game));
63+
.insert(Location::home(), Chest::drop(&mut tombstone_game));
6464

6565
let data = bincode::serialize(&game_v4).unwrap();
6666
let mut new_game = deserialize(&data).unwrap();

src/event.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ pub enum Event<'a> {
5959
ChestFound {
6060
items: &'a [String],
6161
gold: i32,
62-
},
63-
TombstoneFound {
64-
items: &'a [String],
65-
gold: i32,
62+
is_tombstone: bool,
6663
},
6764
}
6865

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,56 @@
11
use crate::game;
22
use crate::item::equipment::{Shield, Sword};
3-
use crate::item::{equipment::Equipment, Item};
3+
use crate::item::{equipment::Equipment, Item, Potion};
4+
use crate::randomizer::random;
5+
use crate::randomizer::Randomizer;
46
use serde::{Deserialize, Serialize};
57
use std::collections::HashMap;
68

79
/// The tombstone is a bag of items left at the hero's dying location.
810
/// When the next hero visits that location, it can pick up the items.
911
#[derive(Serialize, Deserialize)]
10-
pub struct Tombstone {
12+
pub struct Chest {
1113
items: HashMap<String, Vec<Box<dyn Item>>>,
1214
sword: Option<Sword>,
1315
shield: Option<Shield>,
1416
gold: i32,
1517
}
1618

17-
impl Tombstone {
18-
/// Dump the equipment, items and gold from a hero.
19+
impl Chest {
20+
/// Randomly generate a chest at the current location.
21+
pub fn generate(game: &game::Game) -> Option<Self> {
22+
// FIXME improve random generation logic
23+
// FIXME inlcude other items
24+
25+
match random().range(6) {
26+
0 => {
27+
let gold = random().gold_gained(game.player.level * 200);
28+
Some(Self {
29+
items: HashMap::new(),
30+
sword: None,
31+
shield: None,
32+
gold,
33+
})
34+
}
35+
1 => {
36+
let potion = Box::new(Potion::new(game.player.level));
37+
let potions: Vec<Box<dyn Item>> = vec![potion];
38+
39+
let mut items = HashMap::new();
40+
items.insert("potion".to_string(), potions);
41+
42+
Some(Self {
43+
items,
44+
sword: None,
45+
shield: None,
46+
gold: 0,
47+
})
48+
}
49+
_ => None,
50+
}
51+
}
52+
53+
/// Remove the gold, items and equipment from a hero and return them as a new chest.
1954
pub fn drop(game: &mut game::Game) -> Self {
2055
let sword = game.player.sword.take();
2156
let shield = game.player.shield.take();
@@ -31,7 +66,7 @@ impl Tombstone {
3166
}
3267
}
3368

34-
/// Add the items of the tombstone to the current game
69+
/// Add the items of this chest to the current game/hero
3570
pub fn pick_up(&mut self, game: &mut game::Game) -> (Vec<String>, i32) {
3671
let mut to_log = Vec::new();
3772

@@ -74,7 +109,7 @@ mod tests {
74109
#[test]
75110
fn test_empty_drop_pickup() {
76111
let mut game = game::Game::new();
77-
let mut tomb = Tombstone::drop(&mut game);
112+
let mut tomb = Chest::drop(&mut game);
78113

79114
assert_eq!(0, tomb.gold);
80115
assert!(tomb.sword.is_none());
@@ -99,7 +134,7 @@ mod tests {
99134
game.player.shield = Some(Shield::new(1));
100135
game.gold = 100;
101136

102-
let mut tomb = Tombstone::drop(&mut game);
137+
let mut tomb = Chest::drop(&mut game);
103138

104139
assert_eq!(100, tomb.gold);
105140
assert!(tomb.sword.is_some());
@@ -124,7 +159,7 @@ mod tests {
124159
game.player.shield = Some(Shield::new(10));
125160
game.gold = 100;
126161

127-
let mut tomb = Tombstone::drop(&mut game);
162+
let mut tomb = Chest::drop(&mut game);
128163

129164
// set some defaults for the new game before picking up
130165
let mut game = game::Game::new();

src/game/mod.rs

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ extern crate dirs;
33
use crate::character;
44
use crate::character::Character;
55
use crate::event::Event;
6-
use crate::item::{Item, Potion};
6+
use crate::item::Item;
77
use crate::location::Location;
88
use crate::quest::QuestList;
99
use crate::randomizer::random;
1010
use crate::randomizer::Randomizer;
11+
use chest::Chest;
1112
use serde::{Deserialize, Serialize};
1213
use std::collections::{HashMap, HashSet};
13-
use tombstone::Tombstone;
1414

1515
pub mod battle;
16-
pub mod tombstone;
16+
pub mod chest;
1717

1818
#[derive(Serialize, Deserialize)]
1919
#[serde(default)]
@@ -23,7 +23,7 @@ pub struct Game {
2323
pub gold: i32,
2424
pub quests: QuestList,
2525
pub inventory: HashMap<String, Vec<Box<dyn Item>>>,
26-
pub tombstones: HashMap<String, Tombstone>,
26+
pub tombstones: HashMap<String, Chest>,
2727
inspected: HashSet<Location>,
2828
}
2929

@@ -77,35 +77,28 @@ impl Game {
7777
}
7878

7979
/// Look for chests and tombstones at the current location.
80-
/// Remembers previous checks for consistency.
80+
/// Remembers previously visited locations for consistency.
8181
pub fn inspect(&mut self) {
82-
self.pick_up_tombstone();
82+
let maybe_tomb = self.tombstones.remove(&self.location.to_string());
83+
self.pick_up_chest(maybe_tomb, true);
8384

8485
if !self.inspected.contains(&self.location) {
8586
self.inspected.insert(self.location.clone());
87+
self.pick_up_chest(Chest::generate(self), false);
88+
}
89+
}
8690

87-
// this could be extended to find better items, with a non uniform
88-
// probability, and to change according to the distance from home
89-
// it's likely better to extract to an item generator module at that point
90-
match random().range(6) {
91-
0 => {
92-
let gold = random().gold_gained(self.player.level * 200);
93-
Event::emit(self, Event::ChestFound { items: &[], gold });
94-
self.gold += gold;
95-
}
96-
1 => {
97-
let potion = Potion::new(self.player.level);
98-
Event::emit(
99-
self,
100-
Event::ChestFound {
101-
items: &["potion".to_string()],
102-
gold: 0,
103-
},
104-
);
105-
self.add_item("potion", Box::new(potion));
106-
}
107-
_ => {}
108-
}
91+
fn pick_up_chest(&mut self, maybe_chest: Option<Chest>, is_tombstone: bool) {
92+
if let Some(mut chest) = maybe_chest {
93+
let (items, gold) = chest.pick_up(self);
94+
Event::emit(
95+
self,
96+
Event::ChestFound {
97+
items: &items,
98+
gold,
99+
is_tombstone,
100+
},
101+
);
109102
}
110103
}
111104

@@ -177,20 +170,6 @@ impl Game {
177170
.collect::<HashMap<&str, usize>>()
178171
}
179172

180-
/// If there's a tombstone laying in the current location, pick up its items
181-
fn pick_up_tombstone(&mut self) {
182-
if let Some(mut tombstone) = self.tombstones.remove(&self.location.to_string()) {
183-
let (items, gold) = tombstone.pick_up(self);
184-
Event::emit(
185-
self,
186-
Event::TombstoneFound {
187-
items: &items,
188-
gold,
189-
},
190-
);
191-
}
192-
}
193-
194173
pub fn maybe_spawn_enemy(&mut self) -> Option<Character> {
195174
let distance = self.location.distance_from_home();
196175
if random().should_enemy_appear(&distance) {
@@ -272,7 +251,7 @@ impl Game {
272251
}
273252
Err(character::Dead) => {
274253
// leave hero items in the location
275-
let tombstone = Tombstone::drop(self);
254+
let tombstone = Chest::drop(self);
276255
self.tombstones.insert(self.location.to_string(), tombstone);
277256

278257
Event::emit(self, Event::BattleLost);

src/log.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,18 @@ pub fn handle(game: &Game, event: &Event) {
5555
Event::BattleLost => {
5656
battle_lost(&game.player);
5757
}
58-
Event::ChestFound { items, gold } => {
58+
Event::ChestFound {
59+
is_tombstone: false,
60+
items,
61+
gold,
62+
} => {
5963
chest(items, *gold);
6064
}
61-
Event::TombstoneFound { items, gold } => {
65+
Event::ChestFound {
66+
is_tombstone: true,
67+
items,
68+
gold,
69+
} => {
6270
tombstone(items, *gold);
6371
}
6472
Event::Bribe { cost } => {

src/quest/tutorial.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ impl Quest for VisitTomb {
103103
}
104104

105105
fn handle(&mut self, event: &Event) -> bool {
106-
matches!(event, Event::TombstoneFound { .. })
106+
matches!(
107+
event,
108+
Event::ChestFound {
109+
is_tombstone: true,
110+
..
111+
}
112+
)
107113
}
108114
}

0 commit comments

Comments
 (0)