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,
|
SaveGame,
|
||||||
GameOver,
|
GameOver,
|
||||||
NextLevel,
|
NextLevel,
|
||||||
|
PreviousLevel,
|
||||||
HelpScreen,
|
HelpScreen,
|
||||||
MagicMapReveal { row: i32, cursed: bool },
|
MagicMapReveal { row: i32, cursed: bool },
|
||||||
MapGeneration,
|
MapGeneration,
|
||||||
|
|
@ -76,12 +77,12 @@ pub struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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
|
// Visualisation stuff
|
||||||
self.mapgen_index = 0;
|
self.mapgen_index = 0;
|
||||||
self.mapgen_timer = 0.0;
|
self.mapgen_timer = 0.0;
|
||||||
self.mapgen_history.clear();
|
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 {
|
if let Some(history) = map_building_info {
|
||||||
self.mapgen_history = history;
|
self.mapgen_history = history;
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +179,7 @@ impl State {
|
||||||
return to_delete;
|
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
|
// Delete entities that aren't player/player's equipment
|
||||||
let to_delete = self.entities_to_remove_on_level_change();
|
let to_delete = self.entities_to_remove_on_level_change();
|
||||||
for target in to_delete {
|
for target in to_delete {
|
||||||
|
|
@ -192,21 +193,9 @@ impl State {
|
||||||
current_id = worldmap_resource.id;
|
current_id = worldmap_resource.id;
|
||||||
}
|
}
|
||||||
gamelog::record_event("descended", 1);
|
gamelog::record_event("descended", 1);
|
||||||
self.generate_world_map(current_id + 1);
|
self.generate_world_map(current_id + offset, offset);
|
||||||
|
let mapname = self.ecs.fetch::<Map>().name.clone();
|
||||||
// Notify player, restore health up to a point.
|
gamelog::Logger::new().append("You head to").npc_name_n(mapname).period().log();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn game_over_cleanup(&mut self) {
|
fn game_over_cleanup(&mut self) {
|
||||||
|
|
@ -227,7 +216,7 @@ impl State {
|
||||||
}
|
}
|
||||||
// Replace map list
|
// Replace map list
|
||||||
self.ecs.insert(map::dungeon::MasterDungeonMap::new());
|
self.ecs.insert(map::dungeon::MasterDungeonMap::new());
|
||||||
self.generate_world_map(1);
|
self.generate_world_map(1, 0);
|
||||||
|
|
||||||
gamelog::setup_log();
|
gamelog::setup_log();
|
||||||
gamelog::record_event("player_level", 1);
|
gamelog::record_event("player_level", 1);
|
||||||
|
|
@ -408,7 +397,12 @@ impl GameState for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunState::NextLevel => {
|
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);
|
self.mapgen_next_state = Some(RunState::PreRun);
|
||||||
new_runstate = RunState::MapGeneration;
|
new_runstate = RunState::MapGeneration;
|
||||||
}
|
}
|
||||||
|
|
@ -589,7 +583,7 @@ fn main() -> rltk::BError {
|
||||||
|
|
||||||
gamelog::setup_log();
|
gamelog::setup_log();
|
||||||
gamelog::record_event("player_level", 1);
|
gamelog::record_event("player_level", 1);
|
||||||
gs.generate_world_map(1);
|
gs.generate_world_map(1, 0);
|
||||||
|
|
||||||
rltk::main_loop(context, gs)
|
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
|
// Obtain master
|
||||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||||
if dungeon_master.get_map(new_id).is_some() {
|
if dungeon_master.get_map(new_id).is_some() {
|
||||||
std::mem::drop(dungeon_master);
|
std::mem::drop(dungeon_master);
|
||||||
transition_to_existing_map(ecs, new_id);
|
transition_to_existing_map(ecs, new_id, offset);
|
||||||
return None;
|
return None;
|
||||||
} else {
|
} else {
|
||||||
std::mem::drop(dungeon_master);
|
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>();
|
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||||
// Unwrapping here panics if new_id isn't present. But this should
|
// Unwrapping here panics if new_id isn't present. But this should
|
||||||
// never be called without new_id being present by level_transition.
|
// 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>();
|
let player_entity = ecs.fetch::<Entity>();
|
||||||
// Find down stairs, place player
|
// Find down stairs, place player
|
||||||
let w = map.width;
|
let w = map.width;
|
||||||
|
let stair_type = if offset < 0 { TileType::DownStair } else { TileType::UpStair };
|
||||||
for (idx, tt) in map.tiles.iter().enumerate() {
|
for (idx, tt) in map.tiles.iter().enumerate() {
|
||||||
if *tt == TileType::DownStair {
|
if *tt == stair_type {
|
||||||
let mut player_position = ecs.write_resource::<Point>();
|
let mut player_position = ecs.write_resource::<Point>();
|
||||||
*player_position = Point::new(idx as i32 % w, idx as i32 / w);
|
*player_position = Point::new(idx as i32 % w, idx as i32 / w);
|
||||||
let mut position_components = ecs.write_storage::<Position>();
|
let mut position_components = ecs.write_storage::<Position>();
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub fn forest_builder(
|
||||||
difficulty: i32,
|
difficulty: i32,
|
||||||
initial_player_level: i32,
|
initial_player_level: i32,
|
||||||
) -> BuilderChain {
|
) -> 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.start_with(CellularAutomataBuilder::new());
|
||||||
chain.with(AreaStartingPosition::new(XStart::CENTRE, YStart::CENTRE));
|
chain.with(AreaStartingPosition::new(XStart::CENTRE, YStart::CENTRE));
|
||||||
chain.with(CullUnreachable::new());
|
chain.with(CullUnreachable::new());
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ pub fn random_builder(
|
||||||
initial_player_level: i32,
|
initial_player_level: i32,
|
||||||
) -> BuilderChain {
|
) -> BuilderChain {
|
||||||
rltk::console::log(format!("DEBUGINFO: Building random (ID:{}, DIFF:{})", new_id, difficulty));
|
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 type_roll = rng.roll_dice(1, 2);
|
||||||
let mut want_doors = true;
|
let mut want_doors = true;
|
||||||
match type_roll {
|
match type_roll {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub fn town_builder(
|
||||||
initial_player_level: i32,
|
initial_player_level: i32,
|
||||||
) -> BuilderChain {
|
) -> BuilderChain {
|
||||||
rltk::console::log(format!("DEBUGINFO: Building town (ID:{}, DIFF:{})", new_id, difficulty));
|
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());
|
chain.start_with(TownBuilder::new());
|
||||||
|
|
||||||
return chain;
|
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)
|
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 => {
|
VirtualKeyCode::Slash => {
|
||||||
if ctx.shift {
|
if ctx.shift {
|
||||||
return RunState::HelpScreen;
|
return RunState::HelpScreen;
|
||||||
|
|
@ -496,7 +504,19 @@ pub fn try_next_level(ecs: &mut World) -> bool {
|
||||||
if map.tiles[player_idx] == TileType::DownStair {
|
if map.tiles[player_idx] == TileType::DownStair {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue