An engine for roguelikes. Intended to make seven-hour roguelikes easier. Not finished.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.1 KiB

use super::*;
use crate::world::inventory::Inventory;
use rogue_util::coord::*;
use termion::event::Key;
use std::io;
use std::fmt::{self, Formatter};
pub struct Player<R> {
pos: V2i,
hp: Hp, // TODO
time: usize,
inv: Inventory,
input: R,
}
impl<R> Debug for Player<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Player")
.field("pos", &self.pos)
.field("hp", &self.hp)
.field("time", &self.time)
.field("inventory", &self.inv)
.field("input", &"...")
.finish()
}
}
impl<R> Player<R> {
pub fn new(p: V2i, r: R) -> Player<R> {
Player {
pos: p,
hp: 100,
time: 0,
inv: Default::default(),
input: r,
}
}
}
fn key_to_gen_act(c: termion::event::Key) -> Action {
use termion::event::Key::*;
loop {
match c {
Char('h') | Char('a') | Left => return Action::Move(LinfDir::L),
Char('j') | Char('s') | Down => return Action::Move(LinfDir::D),
Char('k') | Char('w') | Up => return Action::Move(LinfDir::U),
Char('l') | Char('d') | Right => return Action::Move(LinfDir::R),
Char('y') => return Action::Move(LinfDir::UL),
Char('u') => return Action::Move(LinfDir::UR),
Char('b') => return Action::Move(LinfDir::DL),
Char('n') => return Action::Move(LinfDir::DR),
Char('q') => return Action::Quit,
_ => ()
}
}
}
impl<R> Entity for Player<R>
where
R: Iterator<Item=io::Result<Key>>
{
fn as_entity(&self) -> &dyn Entity { self as &dyn Entity }
fn pos(&self) -> V2i { self.pos }
fn set_pos(&mut self, p: V2i) { self.pos = p; }
fn next_time(&self) -> usize { self.time }
fn set_next_time(&mut self, t: usize) { self.time = t; }
fn hp(&self) -> Hp { self.hp }
fn set_hp(&mut self, hp: Hp) { self.hp = hp; }
fn inv(&self) -> &Inventory { &self.inv }
fn inv_mut(&mut self) -> &mut Inventory { &mut self.inv }
fn class(&self) -> usize {
ECLS_LIVING | ECLS_PROTAG
}
fn char(&self) -> char { '@' }
fn base_damage(&self) -> Rc<Vec<DamageDesc>> {
Rc::new(vec![DamageDesc {
kind: DamageKind::Phys,
base: 2 * DEFAULT_DAMAGE,
add: 2 * DEFAULT_DAMAGE,
}])
}
fn act<'w>(&mut self, obs: &Observation<'w>) -> Action {
match key_to_gen_act(self.input.next().unwrap().unwrap()) {
Action::Move(dir) => {
let other = self.pos + dir.to_v2i();
for ewk in obs.sight.entities.iter() {
if let Some(eref) = ewk.upgrade() {
if let Ok(er) = eref.try_borrow() {
if er.pos() == other {
return Action::Attack(ewk.clone(), self.best_damage());
}
}
}
}
Action::Move(dir)
},
x => x,
}
}
}