Add inventory, and the ability to pick up items

Add inventory as a basic vector of items attached to the character, and
the ability to pick up a single item where the character stands
This commit is contained in:
Griffin Smith 2019-08-03 15:59:05 -04:00
parent 82cefedab9
commit 48fb3f6624
8 changed files with 63 additions and 6 deletions

View file

@ -15,6 +15,15 @@ impl Color {
}
}
impl PartialEq for Color {
fn eq(&self, other: &Self) -> bool {
format!("{}{}", color::Fg(self), color::Bg(self))
== format!("{}{}", color::Fg(other), color::Bg(other))
}
}
impl Eq for Color {}
impl color::Color for Color {
fn write_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.write_fg(f)

View file

@ -1,4 +1,5 @@
use crate::display;
use crate::entities::item::Item;
use crate::types::{Position, Speed};
use std::io::{self, Write};
@ -7,6 +8,7 @@ const DEFAULT_SPEED: Speed = Speed(100);
entity! {
pub struct Character {
pub o_name: Option<String>,
pub inventory: Vec<Box<Item>>,
}
}
@ -18,6 +20,7 @@ impl Character {
id: None,
position: Position { x: 0, y: 0 },
o_name: None,
inventory: Vec::new(),
}
}

View file

@ -2,7 +2,7 @@ use crate::display::color::Color;
use std::fmt::{self, Display, Formatter};
use termion::color;
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct EntityChar {
#[serde(default)]
color: Color,

View file

@ -4,7 +4,7 @@ use crate::entities::{Describe, EntityID};
use crate::types::Position;
use std::io::{self, Write};
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Item {
pub id: Option<EntityID>,
pub typ: &'static ItemType<'static>,

View file

@ -17,7 +17,7 @@ pub struct CreatureType<'a> {
pub friendly: bool,
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct EdibleItem<'a> {
#[serde(borrow)]
pub eat_message: Option<Message<'a>>,
@ -26,7 +26,7 @@ pub struct EdibleItem<'a> {
pub hitpoints_healed: u16,
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct ItemType<'a> {
pub name: &'a str,

View file

@ -1,5 +1,7 @@
use crate::description::list_to_sentence;
use crate::display::{self, Viewport};
use crate::entities::entity::Describe;
use crate::entities::entity::Entity;
use crate::entities::{
AnEntity, Character, Creature, EntityID, Identified, Item,
};
@ -187,8 +189,7 @@ impl<'a> Game<'a> {
}
}
/// Returns a list of all creature entities at the given position
fn creatures_at<'b>(&'b self, pos: Position) -> Vec<&'b Creature> {
fn downcast_entities_at<A: Entity>(&self, pos: Position) -> Vec<&A> {
self.entities
.at(pos)
.iter()
@ -196,6 +197,16 @@ impl<'a> Game<'a> {
.collect()
}
/// Returns a list of all creature entities at the given position
fn creatures_at(&self, pos: Position) -> Vec<&Creature> {
self.downcast_entities_at(pos)
}
/// Returns a list of all item entities at the given position
fn items_at(&self, pos: Position) -> Vec<&Item> {
self.downcast_entities_at(pos)
}
/// Returns a collision, if any, at the given Position in the game
fn collision_at(&self, pos: Position) -> Option<Collision> {
if !pos.within(self.viewport.inner) {
@ -436,6 +447,31 @@ impl<'a> Game<'a> {
}
}
fn pick_up(&mut self) -> io::Result<()> {
let pos = self.character().position;
let items = self.items_at(pos);
match items.len() {
0 => Ok(()),
1 => {
let item_id = items.get(0).unwrap().id();
let item: Box<Item> =
self.entities.remove(item_id).unwrap().downcast().unwrap();
let desc = item.description();
self.mut_character().inventory.push(item);
self.say(
"global.pick_up",
&template_params!({
"item" => { "name" => &desc, },
}),
)
}
_ => {
// TODO prompt with a menu of items to pick up
unimplemented!()
}
}
}
fn flush_promises(&mut self) {
unsafe {
let game = self as *mut Self;
@ -498,6 +534,8 @@ impl<'a> Game<'a> {
Some(PreviousMessage) => self.previous_message()?,
Some(PickUp) => self.pick_up()?,
None => (),
}

View file

@ -2,6 +2,7 @@
welcome = "Welcome to Xanthous, {{character.name}}! It's dangerous out there, why not stay inside?"
describe_entities = "You see here {{descriptions}}"
describe_no_entities = "You see nothing here."
pick_up = "You pick up the {{item.name}}."
[combat]
attack = "You attack the {{creature.name}}."

View file

@ -10,6 +10,9 @@ pub enum Command {
/// Move the character in a direction
Move(Direction),
/// Pick up any item(s) at the current position
PickUp,
/// Display the previous message
PreviousMessage,
}
@ -19,6 +22,7 @@ impl Command {
use Command::*;
match k {
Char('q') => Some(Quit),
Char('h') | Char('a') | Key::Left => Some(Move(Left)),
Char('k') | Char('w') | Key::Up => Some(Move(Up)),
Char('j') | Char('s') | Key::Down => Some(Move(Down)),
@ -29,6 +33,8 @@ impl Command {
Char('n') => Some(Move(DownRight)),
Ctrl('p') => Some(PreviousMessage),
Char(',') => Some(PickUp),
_ => None,
}
}