Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic win/lose event and screen logic #336

Merged
merged 2 commits into from Sep 3, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.
+95 −5
Diff settings

Always

Just for now

Copy path View file
@@ -150,11 +150,11 @@ impl Iterator for HexIter {
#[allow(dead_code)]
pub fn dump_map<F: Fn(PosHex) -> char>(radius: Distance, f: F) {
let s = radius.0;
for r in -s..s + 1 {
for r in -s..=s {
for _ in -s..r {
print!(" ");
}
for q in -s..s + 1 {
for q in -s..=s {
let pos = PosHex { q, r };
if is_inboard(radius, pos) {
print!("{} ", f(pos));
@@ -27,6 +27,7 @@ fn apply_event(state: &mut State, event: &Event) {
ActiveEvent::MoveTo(ref ev) => apply_event_move_to(state, ev),
ActiveEvent::Attack(ref ev) => apply_event_attack(state, ev),
ActiveEvent::EndTurn(ref ev) => apply_event_end_turn(state, ev),
ActiveEvent::EndBattle(ref ev) => apply_event_end_battle(state, ev),
ActiveEvent::BeginTurn(ref ev) => apply_event_begin_turn(state, ev),
ActiveEvent::UseAbility(ref ev) => apply_event_use_ability(state, ev),
ActiveEvent::UsePassiveAbility(ref ev) => apply_event_use_passive_ability(state, ev),
@@ -109,6 +110,10 @@ fn reset_moves_and_attacks(state: &mut State, player_id: PlayerId) {
}
}

fn apply_event_end_battle(state: &mut State, event: &event::EndBattle) {
state.set_battle_result(event.result.clone());
}

fn apply_event_begin_turn(state: &mut State, event: &event::BeginTurn) {
state.set_player_id(event.player_id);
reset_moves_and_attacks(state, event.player_id);
@@ -7,6 +7,9 @@ use core::tactical_map::{
};

pub fn check(state: &State, command: &Command) -> Result<(), Error> {
if state.battle_result().is_some() {
return Err(Error::BattleEnded);
}
match *command {
Command::Create(ref command) => check_command_create(state, command),
Command::MoveTo(ref command) => check_command_move_to(state, command),
@@ -32,6 +35,7 @@ pub enum Error {
NoTarget,
BadPos,
BadActorType,
BattleEnded,
}

fn check_command_move_to(state: &State, command: &command::MoveTo) -> Result<(), Error> {
@@ -4,6 +4,7 @@ use core::tactical_map::{
ability::{Ability, PassiveAbility},
effect::{Effect, LastingEffect, TimedEffect},
movement::Path,
state::BattleResult,
Moves, ObjId, PlayerId, PosHex,
};

@@ -22,6 +23,7 @@ pub struct Event {
#[derive(Debug, Clone)]
pub enum ActiveEvent {
Create,
EndBattle(EndBattle),
EndTurn(EndTurn),
BeginTurn(BeginTurn),
UseAbility(UseAbility),
@@ -52,6 +54,11 @@ pub struct Attack {
pub mode: AttackMode,
}

#[derive(Debug, Clone)]
pub struct EndBattle {
pub result: BattleResult,
}

#[derive(Debug, Clone)]
pub struct EndTurn {
pub player_id: PlayerId,
@@ -13,7 +13,8 @@ use core::tactical_map::{
effect::{self, Duration, Effect, LastingEffect, TimedEffect},
event::{self, ActiveEvent, Event},
movement::Path,
state, Moves, ObjId, Phase, PlayerId, State, TileType,
state::{self, BattleResult, State},
Moves, ObjId, Phase, PlayerId, TileType,
};

#[derive(PartialEq, Clone, Copy, Debug)]
@@ -39,6 +40,10 @@ pub fn execute(state: &mut State, command: &Command, cb: Cb) -> Result<(), Error
Command::UseAbility(ref command) => execute_use_ability(state, cb, command),
}
execute_planned_abilities(state, cb);
match *command {
Command::Create(_) => {}
_ => try_execute_end_battle(state, cb),
}
Ok(())
}

@@ -486,6 +491,26 @@ fn execute_planned_abilities(state: &mut State, cb: Cb) {
}
}

fn try_execute_end_battle(state: &mut State, cb: Cb) {
for &i in &[0, 1] {
let player_id = PlayerId(i);
let enemies_count = state::enemy_agent_ids(state, player_id).len();
if enemies_count == 0 {
let result = BattleResult {
winner_id: player_id,
};
let active_event = event::EndBattle { result };
let event = Event {
active_event: ActiveEvent::EndBattle(active_event),
actor_ids: Vec::new(),
instant_effects: HashMap::new(),
timed_effects: HashMap::new(),
};
do_event(state, cb, &event);
}
}
}

// TODO: simplify
/// Ticks and kills all the lasting effects.
fn execute_effects(state: &mut State, cb: Cb) {
Copy path View file
@@ -1,7 +1,7 @@
use core::map::{self, PosHex};
use core::tactical_map::{ability::PassiveAbility, utils, ObjId, PlayerId, TileType};

pub use self::private::State;
pub use self::private::{BattleResult, State};

mod private {
use core::map::{self, HexMap};
@@ -10,13 +10,19 @@ mod private {
ObjId, PlayerId, TileType,
};

#[derive(Clone, Debug)]
pub struct BattleResult {
pub winner_id: PlayerId,
}

#[derive(Clone, Debug)]
pub struct State {
parts: Parts,
map: map::HexMap<TileType>,
player_id: PlayerId,
players_count: i32,
prototypes: Prototypes,
battle_result: Option<BattleResult>,
}

impl State {
@@ -28,6 +34,7 @@ mod private {
players_count: 2, // TODO: Read from the `Options` struct
parts: Parts::new(),
prototypes,
battle_result: None,
}
}

@@ -57,6 +64,10 @@ mod private {
let prototypes = &self.prototypes.0;
prototypes[name].clone()
}

pub fn battle_result(&self) -> &Option<BattleResult> {
&self.battle_result
}
}

/// Mutators. Be carefull with them!
@@ -74,6 +85,10 @@ mod private {
self.player_id = new_value;
}

pub(in core) fn set_battle_result(&mut self, result: BattleResult) {
self.battle_result = Some(result);
}

pub(in core) fn alloc_id(&mut self) -> ObjId {
self.parts.alloc_id()
}
Copy path View file
@@ -181,7 +181,7 @@ fn prepare_map_and_state(
execute::create_objects(state, &mut |state, event, phase| {
let action = visualize::visualize(state, view, context, event, phase)
.expect("Can't visualize the event");
let action = action::Fork::new(action).boxed();
let action = action::Fork::new(action).boxed(); // TODO: Use helper `fork` method
actions.push(action);
});
view.add_action(action::Sequence::new(actions).boxed());
@@ -255,6 +255,9 @@ impl Battle {
if let command::Command::EndTurn(_) = command {
break;
}
if self.state.battle_result().is_some() {
break;
}
}
debug!("AI: >");
action::Sequence::new(actions).boxed()
@@ -457,6 +460,9 @@ impl Screen for Battle {
fn update(&mut self, context: &mut Context, dtime: Duration) -> ZResult<Transition> {
self.view.tick(dtime);
self.update_block_timer(context, dtime)?;
if self.block_timer.is_none() && self.state.battle_result().is_some() {
return Ok(Transition::Pop);
}
Ok(Transition::None)
}

Copy path View file
@@ -286,6 +286,7 @@ fn visualize_event(
ActiveEvent::UsePassiveAbility(_) | ActiveEvent::Create => action::Empty::new().boxed(),
ActiveEvent::MoveTo(ref ev) => visualize_event_move_to(state, view, context, ev)?,
ActiveEvent::Attack(ref ev) => visualize_event_attack(state, view, context, ev)?,
ActiveEvent::EndBattle(ref ev) => visualize_event_end_battle(state, view, context, ev)?,
ActiveEvent::EndTurn(ref ev) => visualize_event_end_turn(state, view, context, ev),
ActiveEvent::BeginTurn(ref ev) => visualize_event_begin_turn(state, view, context, ev)?,
ActiveEvent::EffectTick(ref ev) => visualize_event_effect_tick(state, view, ev)?,
@@ -415,6 +416,33 @@ fn visualize_event_attack(
Ok(seq(actions))
}

// TODO: code duplication with `visualize_event_begin_turn` - extract a helper function
fn visualize_event_end_battle(
_: &State,
view: &mut BattleView,
context: &mut Context,
event: &event::EndBattle,
) -> ZResult<Box<dyn Action>> {
let visible = [0.0, 0.0, 0.0, 1.0].into();
let invisible = Color { a: 0.0, ..visible };
let text = match event.result.winner_id {
PlayerId(0) => "YOU WON!",
PlayerId(1) => "YOU LOSE!",
_ => unreachable!(),
};
let text = Text::new(context, &text, view.font())?;
let mut sprite = Sprite::from_image(text.into_inner(), 0.2);
sprite.set_centered(true);
sprite.set_color(invisible);
Ok(seq(vec![
action::Show::new(&view.layers().text, &sprite).boxed(),
action::ChangeColorTo::new(&sprite, visible, time_s(0.5)).boxed(),
action::Sleep::new(time_s(3.0)).boxed(),
action::ChangeColorTo::new(&sprite, invisible, time_s(1.0)).boxed(),
action::Hide::new(&view.layers().text, &sprite).boxed(),
]))
}

fn visualize_event_end_turn(
_: &State,
_: &mut BattleView,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.