From 79a59a1a5dc211353b84eedfce18666590d09b11 Mon Sep 17 00:00:00 2001 From: Jared Roberts Date: Wed, 9 Mar 2016 12:21:18 -0800 Subject: [PATCH] town and world maps to unicode --- Cargo.toml | 8 +++ src/main.rs | 49 ++++++++++++++++++ src/transpose.rs | 89 ++++++++++++++++++++++++++++++++ src/world.rs | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/transpose.rs create mode 100644 src/world.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0d3c581 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "vrtue" +version = "0.1.0" +authors = ["Jared Roberts "] + +[dependencies] +itertools = ">=0.4" +memmap = "~0.2" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ddd0953 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,49 @@ +extern crate itertools; +extern crate memmap; + +use std::mem::transmute; +use std::env; + +use itertools::Itertools; +use memmap::{Mmap, Protection}; + +mod world; +mod transpose; + +use world::Map; + +fn mmap_to_rows<'a, M: world::Map>(mmap: &memmap::Mmap) -> &'a world::Map + where M: Copy + 'a +{ + assert!(std::mem::size_of::() <= mmap.len()); + unsafe { transmute::<*const u8, &M>(mmap.ptr()) } +} + +fn main() { + let args: Vec = env::args().collect(); + let filename; + let conv; + if args.len() > 1 { + filename = &args[1] as &str; + conv = mmap_to_rows::; + } else { + filename = "data/WORLD.MAP"; + conv = mmap_to_rows::; + } + + let file_mmap = Mmap::open_path(filename, Protection::Read).unwrap(); + let world = conv(&file_mmap); + + print_rows(world.rows()); +} + +fn print_rows<'a, T: ?Sized, U: ?Sized>(rows: Box) + where T: Iterator> + 'a, + U: Iterator + 'a +{ + for row in rows { + let s1: String = row.into_iter().map(|tile| tile.as_char()).collect(); + let s: String = s1.chars().intersperse(' ').collect(); + println!("{}", s); + } +} diff --git a/src/transpose.rs b/src/transpose.rs new file mode 100644 index 0000000..d4d9c10 --- /dev/null +++ b/src/transpose.rs @@ -0,0 +1,89 @@ +pub trait TransposableIterator: Iterator { + fn transpose(self) -> Transpose + where Self: Iterator + Clone + Sized, + C: IntoIterator, + J: ExactSizeIterator + { + Transpose::new(self) + } +} + +impl TransposableIterator for I where I: Iterator +{} + +#[derive(Clone)] +pub struct Transpose { + loc: ::std::ops::Range, + iter: I, +} + +impl Transpose + where I: Iterator + Clone, + C: IntoIterator, + J: ExactSizeIterator +{ + fn new(base: I) -> Transpose { + let longest = base.clone() + .fold(0, |len, row| ::std::cmp::max(len, row.into_iter().len())); + + Transpose { + loc: 0..longest, + iter: base, + } + } +} + +impl Iterator for Transpose where I: Clone +{ + type Item = TransposeInner; + + #[inline] + fn next(&mut self) -> Option> { + self.loc.next().map(|idx| { + TransposeInner { + iter: self.iter.clone(), + col: idx, + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + (self.loc.end, Some(self.loc.end)) + } +} + +impl ExactSizeIterator for Transpose where I: Clone +{} + +impl DoubleEndedIterator for Transpose where I: Clone +{ + fn next_back(&mut self) -> Option> { + self.loc.next_back().map(|idx| { + TransposeInner { + iter: self.iter.clone(), + col: idx, + } + }) + } +} + +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] +pub struct TransposeInner { + iter: I, + col: usize, +} + +impl Iterator for TransposeInner + where I: Iterator, + J: IntoIterator +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().and_then(|row| row.into_iter().nth(self.col)) + } +} + +// TODO: ExactSizeIterator and DoubleEndedIterator for TransposeInner diff --git a/src/world.rs b/src/world.rs new file mode 100644 index 0000000..29f77f4 --- /dev/null +++ b/src/world.rs @@ -0,0 +1,128 @@ +extern crate core; +extern crate itertools; + +use self::itertools::Itertools; + +use transpose::TransposableIterator; + +#[derive(Clone, Copy)] +pub struct Tile { + val: u8, +} + +impl Tile { + pub fn as_char(&self) -> char { + match self.val { + 0 => '~', // deep water '๐ŸŒŠ' + 1 => 'โ‰ˆ', // medium water + 2 => 'โ‰‹', // shallow water + 3 => ',', // swamp + 4 => 'โขŠ', // plain 'โ–‘' + 5 => '๐ŸŒฟ', // scrub 'แƒฌ' + 6 => '๐ŸŒณ', // forest + 7 => 'โŒ“', // hill 'โˆฉ' + 8 => 'โจ‡', // mountain 'โ–ณ' + 9 => 'โ˜—', // dungeon + 10 => 'โŸ', // city + 11 | 13...15 => 'โ›ซ', // castle + 12 => 'โ–', // village + 22 => 'โŽ”', // tile floor + 23 => 'โŸ—', // bridge + 24 => 'โงฌ', // balloon + 25 => 'โ‰ƒ', // bridge top + 26 => 'โ‰‚', // bridge bottom + 27 => 'โ', // ladder up + 28 => 'โ—', // ladder down + 29 => 'v', // ruin + 30 => 'โ—Œ', // shrine + 48 => 'โ—ฏ', // column + 49 => 'โ—ฃ', // SW + 50 => 'โ—ข', // SE + 51 => 'โ—ค', // NW + 52 => 'โ—ฅ', // NE + 54 => 'โŽˆ', // ship's wheel + 55 => 'แƒค', // rocks 'โ' + 56 => '/', // Lyin down + 57 => 'โฌ›', // stone wall + 58 => 'โงฏ', // '๐Ÿ”’', // locked door + 59 => 'โงฎ', // '๐Ÿ”“', // unlocked door + 60 => '๐Ÿ’ฐ', // chest + 61 => 'โ˜ฅ', // ankh + 62 => 'โจณ', // brick floor 'โŒ—' + 63 => 'โ–ค', // wood planks 'โงป' + 68 => '๐ŸŒซ', // poison field + 69 => 'โšก', // energy field + 70 => '๐Ÿ”ฅ', // fire field + 71 => '๐Ÿ’ค', // sleep field + 72 => 'โ–ฃ', // solid barrier + 73 => 'โ–’', // hidden passage + 75 => '๐Ÿ–', // spit (rotisserie) '๐Ÿณ' + 76 => 'โŒ˜', // lava + 96...121 => ::std::char::from_u32((self.val - 31) as u32).unwrap(), + 122 => '=', // space + 123 => 'โА', // right '' + 124 => 'โŠ', // left 'โŠจ' + 125 => 'โ–ข', // window + 126 => 'โœจ', // space + 127 => 'โ–“', // brick wall + 189 => 'โš”', // phantom 2 + _ => '?', // panic!("{0}", self.val) + } + } +} + +pub trait Map { + fn rows<'a>(&'a self) -> BoxedMapIterator; +} + +pub type BoxedMapIterator<'a> = Box> + 'a>; +pub type ExactBoxedMapIterator<'a> = Box> + 'a>; + +const CHUNKDIM: usize = 32; +pub type ChunkRow = [Tile; CHUNKDIM]; +pub type ChunkRect = [ChunkRow; CHUNKDIM]; +pub type ChunkRowIterator<'a> = Box + 'a>; +#[derive(Clone, Copy)] +pub struct Chunk { + pub rect: ChunkRect, +} + +impl Chunk { + fn rows_exact<'a>(&'a self) -> ExactBoxedMapIterator { + Box::new(self.rect + .iter() + .map(|row| Box::new(row.into_iter()) as ChunkRowIterator<'a>)) + } +} + +impl Map for Chunk { + fn rows<'a>(&'a self) -> BoxedMapIterator { + Box::new(self.rect + .iter() + .map(|row| Box::new(row.into_iter()) as ChunkRowIterator<'a>)) + } +} + +impl<'a> IntoIterator for &'a Chunk { + type Item=ChunkRowIterator<'a>; + type IntoIter=ExactBoxedMapIterator<'a>; + fn into_iter(self) -> Self::IntoIter { + self.rows_exact() + } +} + +const WORLDDIM: usize = 8; +pub type WorldRow = [Chunk; WORLDDIM]; +pub type WorldRect = [WorldRow; WORLDDIM]; +#[derive(Clone, Copy)] +pub struct World { + pub rect: WorldRect, +} + +impl Map for World { + fn rows<'a>(&'a self) -> BoxedMapIterator { + let flipped = self.rect.iter().map(|cr| cr.into_iter().transpose()); + Box::new(flipped.flatten() + .map(|r| Box::new(r.flatten()) as ChunkRowIterator<'a>)) + } +}