generic goto_level, implements backtracking
This commit is contained in:
parent
25befa9343
commit
dab0683ffd
6 changed files with 44 additions and 29 deletions
36
src/main.rs
36
src/main.rs
|
|
@ -62,6 +62,7 @@ pub enum RunState {
|
|||
SaveGame,
|
||||
GameOver,
|
||||
NextLevel,
|
||||
PreviousLevel,
|
||||
HelpScreen,
|
||||
MagicMapReveal { row: i32, cursed: bool },
|
||||
MapGeneration,
|
||||
|
|
@ -76,12 +77,12 @@ pub struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
fn generate_world_map(&mut self, new_id: i32) {
|
||||
fn generate_world_map(&mut self, new_id: i32, offset: i32) {
|
||||
// Visualisation stuff
|
||||
self.mapgen_index = 0;
|
||||
self.mapgen_timer = 0.0;
|
||||
self.mapgen_history.clear();
|
||||
let map_building_info = map::level_transition(&mut self.ecs, new_id);
|
||||
let map_building_info = map::level_transition(&mut self.ecs, new_id, offset);
|
||||
if let Some(history) = map_building_info {
|
||||
self.mapgen_history = history;
|
||||
}
|
||||
|
|
@ -178,7 +179,7 @@ impl State {
|
|||
return to_delete;
|
||||
}
|
||||
|
||||
fn goto_next_level(&mut self) {
|
||||
fn goto_level(&mut self, offset: i32) {
|
||||
// Delete entities that aren't player/player's equipment
|
||||
let to_delete = self.entities_to_remove_on_level_change();
|
||||
for target in to_delete {
|
||||
|
|
@ -192,21 +193,9 @@ impl State {
|
|||
current_id = worldmap_resource.id;
|
||||
}
|
||||
gamelog::record_event("descended", 1);
|
||||
self.generate_world_map(current_id + 1);
|
||||
|
||||
// Notify player, restore health up to a point.
|
||||
let player_entity = self.ecs.fetch::<Entity>();
|
||||
gamelog::Logger::new()
|
||||
.append("Taking a short rest, you manage to")
|
||||
.colour((0, 255, 0))
|
||||
.append_n("recover some of your strength")
|
||||
.period()
|
||||
.log();
|
||||
let mut pools = self.ecs.write_storage::<Pools>();
|
||||
let stats = pools.get_mut(*player_entity);
|
||||
if let Some(stats) = stats {
|
||||
stats.hit_points.current = i32::max(stats.hit_points.current, stats.hit_points.max / 2);
|
||||
}
|
||||
self.generate_world_map(current_id + offset, offset);
|
||||
let mapname = self.ecs.fetch::<Map>().name.clone();
|
||||
gamelog::Logger::new().append("You head to").npc_name_n(mapname).period().log();
|
||||
}
|
||||
|
||||
fn game_over_cleanup(&mut self) {
|
||||
|
|
@ -227,7 +216,7 @@ impl State {
|
|||
}
|
||||
// Replace map list
|
||||
self.ecs.insert(map::dungeon::MasterDungeonMap::new());
|
||||
self.generate_world_map(1);
|
||||
self.generate_world_map(1, 0);
|
||||
|
||||
gamelog::setup_log();
|
||||
gamelog::record_event("player_level", 1);
|
||||
|
|
@ -408,7 +397,12 @@ impl GameState for State {
|
|||
}
|
||||
}
|
||||
RunState::NextLevel => {
|
||||
self.goto_next_level();
|
||||
self.goto_level(1);
|
||||
self.mapgen_next_state = Some(RunState::PreRun);
|
||||
new_runstate = RunState::MapGeneration;
|
||||
}
|
||||
RunState::PreviousLevel => {
|
||||
self.goto_level(-1);
|
||||
self.mapgen_next_state = Some(RunState::PreRun);
|
||||
new_runstate = RunState::MapGeneration;
|
||||
}
|
||||
|
|
@ -589,7 +583,7 @@ fn main() -> rltk::BError {
|
|||
|
||||
gamelog::setup_log();
|
||||
gamelog::record_event("player_level", 1);
|
||||
gs.generate_world_map(1);
|
||||
gs.generate_world_map(1, 0);
|
||||
|
||||
rltk::main_loop(context, gs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ impl MasterDungeonMap {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn level_transition(ecs: &mut World, new_id: i32) -> Option<Vec<Map>> {
|
||||
pub fn level_transition(ecs: &mut World, new_id: i32, offset: i32) -> Option<Vec<Map>> {
|
||||
// Obtain master
|
||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||
if dungeon_master.get_map(new_id).is_some() {
|
||||
std::mem::drop(dungeon_master);
|
||||
transition_to_existing_map(ecs, new_id);
|
||||
transition_to_existing_map(ecs, new_id, offset);
|
||||
return None;
|
||||
} else {
|
||||
std::mem::drop(dungeon_master);
|
||||
|
|
@ -44,7 +44,7 @@ pub fn level_transition(ecs: &mut World, new_id: i32) -> Option<Vec<Map>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn transition_to_existing_map(ecs: &mut World, new_id: i32) {
|
||||
fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32) {
|
||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||
// Unwrapping here panics if new_id isn't present. But this should
|
||||
// never be called without new_id being present by level_transition.
|
||||
|
|
@ -53,8 +53,9 @@ fn transition_to_existing_map(ecs: &mut World, new_id: i32) {
|
|||
let player_entity = ecs.fetch::<Entity>();
|
||||
// Find down stairs, place player
|
||||
let w = map.width;
|
||||
let stair_type = if offset < 0 { TileType::DownStair } else { TileType::UpStair };
|
||||
for (idx, tt) in map.tiles.iter().enumerate() {
|
||||
if *tt == TileType::DownStair {
|
||||
if *tt == stair_type {
|
||||
let mut player_position = ecs.write_resource::<Point>();
|
||||
*player_position = Point::new(idx as i32 % w, idx as i32 / w);
|
||||
let mut position_components = ecs.write_storage::<Position>();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub fn forest_builder(
|
|||
difficulty: i32,
|
||||
initial_player_level: i32,
|
||||
) -> BuilderChain {
|
||||
let mut chain = BuilderChain::new(new_id, width, height, difficulty, "Into the Woods", initial_player_level);
|
||||
let mut chain = BuilderChain::new(new_id, width, height, difficulty, "the woods", initial_player_level);
|
||||
chain.start_with(CellularAutomataBuilder::new());
|
||||
chain.with(AreaStartingPosition::new(XStart::CENTRE, YStart::CENTRE));
|
||||
chain.with(CullUnreachable::new());
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ pub fn random_builder(
|
|||
initial_player_level: i32,
|
||||
) -> BuilderChain {
|
||||
rltk::console::log(format!("DEBUGINFO: Building random (ID:{}, DIFF:{})", new_id, difficulty));
|
||||
let mut builder = BuilderChain::new(new_id, width, height, difficulty, "<PLACEHOLDER>", initial_player_level);
|
||||
let mut builder = BuilderChain::new(new_id, width, height, difficulty, "the dungeon", initial_player_level);
|
||||
let type_roll = rng.roll_dice(1, 2);
|
||||
let mut want_doors = true;
|
||||
match type_roll {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub fn town_builder(
|
|||
initial_player_level: i32,
|
||||
) -> BuilderChain {
|
||||
rltk::console::log(format!("DEBUGINFO: Building town (ID:{}, DIFF:{})", new_id, difficulty));
|
||||
let mut chain = BuilderChain::new(new_id, width, height, difficulty, "<PLACEHOLDER>", initial_player_level);
|
||||
let mut chain = BuilderChain::new(new_id, width, height, difficulty, "the town", initial_player_level);
|
||||
chain.start_with(TownBuilder::new());
|
||||
|
||||
return chain;
|
||||
|
|
|
|||
|
|
@ -457,6 +457,14 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
|||
result = skip_turn(&mut gs.ecs); // (Wait a turn)
|
||||
}
|
||||
}
|
||||
VirtualKeyCode::Comma => {
|
||||
if ctx.shift {
|
||||
if !try_previous_level(&mut gs.ecs) {
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
return RunState::PreviousLevel; // < to ascend
|
||||
}
|
||||
}
|
||||
VirtualKeyCode::Slash => {
|
||||
if ctx.shift {
|
||||
return RunState::HelpScreen;
|
||||
|
|
@ -496,7 +504,19 @@ pub fn try_next_level(ecs: &mut World) -> bool {
|
|||
if map.tiles[player_idx] == TileType::DownStair {
|
||||
return true;
|
||||
} else {
|
||||
gamelog::Logger::new().append("You don't see a way down.").log();
|
||||
gamelog::Logger::new().append("You don't see a way down from here.").log();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_previous_level(ecs: &mut World) -> bool {
|
||||
let player_pos = ecs.fetch::<Point>();
|
||||
let map = ecs.fetch::<Map>();
|
||||
let player_idx = map.xy_idx(player_pos.x, player_pos.y);
|
||||
if map.tiles[player_idx] == TileType::UpStair {
|
||||
return true;
|
||||
} else {
|
||||
gamelog::Logger::new().append("You don't see a way up from here.").log();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue