Browse Source

Add items

master
Graham Northup 6 months ago
parent
commit
c625ae67d9
  1. 32
      src/world/entity/mod.rs
  2. 21
      src/world/entity/player.rs
  3. 22
      src/world/inventory.rs
  4. 25
      src/world/item.rs
  5. 5
      src/world/mod.rs

32
src/world/entity/mod.rs

@ -2,6 +2,7 @@ pub mod player;
pub mod ai;
use super::*;
use crate::world::{inventory::Inventory, item::{Item, ItemRef, Slot}};
use rogue_util::{coord::*, raster, grid::Grid};
use std::fmt::Debug;
use rand::Rng;
@ -100,6 +101,7 @@ impl From<&DamageDesc> for Damage {
pub enum Action {
Move(LinfDir),
Attack(EntWeak, Rc<Vec<DamageDesc>>),
Equip(ItemRef),
Wait,
Quit,
}
@ -179,10 +181,15 @@ impl SightObs {
pub const DEFAULT_SIGHT_RADIUS: usize = 10;
pub const DEFAULT_ACT_TIME: usize = 10000;
pub const DEFAULT_DAMAGE: Hp = 6;
pub const ECLS_LIVING: usize = 1 << 0;
pub const ECLS_PROTAG: usize = 1 << 1;
pub fn expected_damage(atks: Rc<Vec<DamageDesc>>) -> Hp {
atks.iter().map(|a| a.base + a.add / 2).sum()
}
pub trait Entity: Debug {
fn pos(&self) -> V2i;
fn set_pos(&mut self, v: V2i);
@ -190,11 +197,36 @@ pub trait Entity: Debug {
fn set_next_time(&mut self, t: usize);
fn hp(&self) -> Hp;
fn set_hp(&mut self, h: Hp);
fn inv(&self) -> &Inventory;
fn inv_mut(&mut self) -> &mut Inventory;
fn class(&self) -> usize { 0 }
fn char(&self) -> char { 'E' }
fn sight(&self) -> usize { DEFAULT_SIGHT_RADIUS }
fn act_time(&self) -> usize { DEFAULT_ACT_TIME }
fn base_damage(&self) -> Rc<Vec<DamageDesc>> {
Rc::new(vec![DamageDesc {
kind: DamageKind::Phys,
base: DEFAULT_DAMAGE,
add: DEFAULT_DAMAGE,
}])
}
fn best_damage(&self) -> Rc<Vec<DamageDesc>> where Self: Sized {
let mut bestatk = self.base_damage();
let mut bestdmg = expected_damage(Rc::clone(&bestatk));
for slot in Slot::DAMAGING.iter().cloned() {
if let Some(item) = self.inv().in_slot(slot) {
if let Some(atk) = item.borrow().damage(self as &dyn Entity) {
let dmg = expected_damage(Rc::clone(&atk));
if dmg > bestdmg {
bestdmg = dmg;
bestatk = atk;
}
}
}
}
bestatk
}
fn act<'w>(&mut self, _obs: &Observation<'w>) -> Action { Action::Wait }
fn heal(&mut self, amount: Hp) {

21
src/world/entity/player.rs

@ -1,4 +1,5 @@
use super::*;
use crate::world::inventory::Inventory;
use rogue_util::coord::*;
use termion::event::Key;
use std::io;
@ -8,6 +9,7 @@ pub struct Player<R> {
pos: V2i,
hp: Hp, // TODO
time: usize,
inv: Inventory,
input: R,
}
@ -17,6 +19,7 @@ impl<R> Debug for Player<R> {
.field("pos", &self.pos)
.field("hp", &self.hp)
.field("time", &self.time)
.field("inventory", &self.inv)
.field("input", &"...")
.finish()
}
@ -28,6 +31,7 @@ impl<R> Player<R> {
pos: p,
hp: 100,
time: 0,
inv: Default::default(),
input: r,
}
}
@ -61,11 +65,20 @@ impl<R> Entity for Player<R>
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()) {
@ -75,13 +88,7 @@ impl<R> Entity for Player<R>
if let Some(eref) = ewk.upgrade() {
if let Ok(er) = eref.try_borrow() {
if er.pos() == other {
return Action::Attack(ewk.clone(),
Rc::new(vec![DamageDesc {
kind: DamageKind::Phys,
base: 10,
add: 10,
}])
);
return Action::Attack(ewk.clone(), self.best_damage());
}
}
}

22
src/world/inventory.rs

@ -1,9 +1,27 @@
use std::rc::Rc;
use std::cell::RefCell;
use super::item::{Item, ItemRef};
use super::item::{Item, ItemRef, Slot};
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct Inventory {
items: Vec<Rc<RefCell<dyn Item>>>,
items: Vec<ItemRef>,
equip: HashMap<Slot, ItemRef>,
}
impl Inventory {
pub fn equip_slot(&mut self, slot: Slot, item: ItemRef) {
self.equip.insert(slot, item);
}
pub fn in_slot(&self, slot: Slot) -> Option<ItemRef> {
self.equip.get(&slot).map(Rc::clone)
}
pub fn add(&mut self, item: ItemRef) {
self.items.push(item);
}
pub fn list(&self) -> &Vec<ItemRef> { &self.items }
}

25
src/world/item.rs

@ -1,14 +1,31 @@
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use super::entity::{Entity, DamageDesc};
use std::fmt::Debug;
pub type ItemRef = Rc<RefCell<dyn Item>>;
pub type ItemWeak = Weak<RefCell<dyn Item>>;
pub trait Item {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Slot {
Head, Chest, LeftArm, RightArm, LeftLeg, RightLeg, LeftRing, RightRing,
}
impl Slot {
pub const ALL: &'static [Slot] = &[
Slot::Head, Slot::Chest, Slot::LeftArm, Slot::RightArm,
Slot::LeftLeg, Slot::RightLeg, Slot::LeftRing, Slot::RightRing,
];
pub const DAMAGING: &'static [Slot] = &[Slot::LeftArm, Slot::RightArm];
}
pub trait Item: Debug {
fn slot(&self) -> Option<Slot>;
fn damage(&self, wielder: &dyn Entity) -> Option<Rc<Vec<DamageDesc>>> { None }
}
pub fn item_ref<I: Item + 'static>(item: I) -> ItemRef{
Rc::new(RefCell::new(item))
pub fn item_ref<I: Item + 'static>(item: I) -> ItemRef {
Rc::new(RefCell::new(item))
}

5
src/world/mod.rs

@ -217,6 +217,11 @@ impl World {
}
}
},
Equip(item) => {
if let Some(slot) = item.borrow().slot() {
e.inv_mut().equip_slot(slot, Rc::clone(&item));
}
},
Quit => {
return Some(());
},

Loading…
Cancel
Save