mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Economy redesign: Cleaner file structure (no code change)
This commit is contained in:
parent
4e116e46b9
commit
546afa86ae
361
world/src/site/economy/map_types.rs
Normal file
361
world/src/site/economy/map_types.rs
Normal file
@ -0,0 +1,361 @@
|
||||
use crate::{
|
||||
assets::{self, AssetExt},
|
||||
util::map_array::{enum_from_index, index_from_enum, GenericIndex, NotFound},
|
||||
};
|
||||
use common::{terrain::BiomeKind, trade::Good};
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
ops::{Index, IndexMut},
|
||||
};
|
||||
|
||||
use Good::*;
|
||||
|
||||
// the opaque index type into the "map" of Goods
|
||||
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct GoodIndex {
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl GenericIndex<Good, 23> for GoodIndex {
|
||||
// static list of all Goods traded
|
||||
const VALUES: [Good; GoodIndex::LENGTH] = [
|
||||
// controlled resources
|
||||
Territory(BiomeKind::Grassland),
|
||||
Territory(BiomeKind::Forest),
|
||||
Territory(BiomeKind::Lake),
|
||||
Territory(BiomeKind::Ocean),
|
||||
Territory(BiomeKind::Mountain),
|
||||
RoadSecurity,
|
||||
Ingredients,
|
||||
// produced goods
|
||||
Flour,
|
||||
Meat,
|
||||
Wood,
|
||||
Stone,
|
||||
Food,
|
||||
Tools,
|
||||
Armor,
|
||||
Potions,
|
||||
Transportation,
|
||||
// exchange currency
|
||||
Coin,
|
||||
// uncontrolled resources
|
||||
Terrain(BiomeKind::Lake),
|
||||
Terrain(BiomeKind::Mountain),
|
||||
Terrain(BiomeKind::Grassland),
|
||||
Terrain(BiomeKind::Forest),
|
||||
Terrain(BiomeKind::Desert),
|
||||
Terrain(BiomeKind::Ocean),
|
||||
];
|
||||
|
||||
fn from_usize(idx: usize) -> Self { Self { idx } }
|
||||
|
||||
fn into_usize(self) -> usize { self.idx }
|
||||
}
|
||||
|
||||
impl TryFrom<Good> for GoodIndex {
|
||||
type Error = NotFound;
|
||||
|
||||
fn try_from(e: Good) -> Result<Self, NotFound> { index_from_enum(e) }
|
||||
}
|
||||
|
||||
impl From<GoodIndex> for Good {
|
||||
fn from(gi: GoodIndex) -> Good { enum_from_index(gi) }
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for GoodIndex {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
GoodIndex::VALUES[self.idx].fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// the "map" itself
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct GoodMap<V> {
|
||||
data: [V; GoodIndex::LENGTH],
|
||||
}
|
||||
|
||||
impl<V: Default + Copy> Default for GoodMap<V> {
|
||||
fn default() -> Self {
|
||||
GoodMap {
|
||||
data: [V::default(); GoodIndex::LENGTH],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Default + Copy + PartialEq + fmt::Debug> fmt::Debug for GoodMap<V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map()
|
||||
.entries(
|
||||
self.iter()
|
||||
.filter(|i| *i.1 != V::default())
|
||||
.map(|i| (Good::from(i.0), i.1)),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<GoodIndex> for GoodMap<V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, index: GoodIndex) -> &Self::Output { &self.data[index.idx] }
|
||||
}
|
||||
|
||||
impl<V> IndexMut<GoodIndex> for GoodMap<V> {
|
||||
fn index_mut(&mut self, index: GoodIndex) -> &mut Self::Output { &mut self.data[index.idx] }
|
||||
}
|
||||
|
||||
impl<V> GoodMap<V> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (GoodIndex, &V)> + '_ {
|
||||
(&self.data)
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, v)| (GoodIndex { idx }, v))
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (GoodIndex, &mut V)> + '_ {
|
||||
(&mut self.data)
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.map(|(idx, v)| (GoodIndex { idx }, v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy> GoodMap<V> {
|
||||
pub fn from_default(default: V) -> Self {
|
||||
GoodMap {
|
||||
data: [default; GoodIndex::LENGTH],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_iter(i: impl Iterator<Item = (GoodIndex, V)>, default: V) -> Self {
|
||||
let mut result = Self::from_default(default);
|
||||
for j in i {
|
||||
result.data[j.0.idx] = j.1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn map<U: Default + Copy>(self, mut f: impl FnMut(GoodIndex, V) -> U) -> GoodMap<U> {
|
||||
let mut result = GoodMap::<U>::from_default(U::default());
|
||||
for j in self.data.iter().enumerate() {
|
||||
result.data[j.0] = f(GoodIndex::from_usize(j.0), *j.1);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn from_list<'a>(i: impl IntoIterator<Item = &'a (GoodIndex, V)>, default: V) -> Self
|
||||
where
|
||||
V: 'a,
|
||||
{
|
||||
let mut result = Self::from_default(default);
|
||||
for j in i {
|
||||
result.data[j.0.idx] = j.1;
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct RawProfession {
|
||||
pub name: String,
|
||||
pub orders: Vec<(Good, f32)>,
|
||||
pub products: Vec<(Good, f32)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Profession {
|
||||
pub name: String,
|
||||
pub orders: Vec<(GoodIndex, f32)>,
|
||||
pub products: (GoodIndex, f32),
|
||||
}
|
||||
|
||||
// reference to profession
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct Labor(u8, PhantomData<Profession>);
|
||||
|
||||
// the opaque index type into the "map" of Labors (as Labor already contains a
|
||||
// monotonous index we reuse it)
|
||||
pub type LaborIndex = Labor;
|
||||
|
||||
impl LaborIndex {
|
||||
fn from_usize(idx: usize) -> Self { Self(idx as u8, PhantomData) }
|
||||
|
||||
fn into_usize(self) -> usize { self.0 as usize }
|
||||
}
|
||||
|
||||
// the "map" itself
|
||||
#[derive(Clone)]
|
||||
pub struct LaborMap<V> {
|
||||
data: Vec<V>,
|
||||
}
|
||||
|
||||
impl<V: Default + Copy> Default for LaborMap<V> {
|
||||
fn default() -> Self {
|
||||
LaborMap {
|
||||
data: std::iter::repeat(V::default()).take(*LABOR_COUNT).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Default + Copy + PartialEq + fmt::Debug> fmt::Debug for LaborMap<V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map()
|
||||
.entries(
|
||||
self.iter()
|
||||
.filter(|i| *i.1 != V::default())
|
||||
.map(|i| (i.0, &*i.1)),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<LaborIndex> for LaborMap<V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, index: LaborIndex) -> &Self::Output { &self.data[index.into_usize()] }
|
||||
}
|
||||
|
||||
impl<V> IndexMut<LaborIndex> for LaborMap<V> {
|
||||
fn index_mut(&mut self, index: LaborIndex) -> &mut Self::Output {
|
||||
&mut self.data[index.into_usize()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> LaborMap<V> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (LaborIndex, &V)> + '_ {
|
||||
(&self.data)
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, v)| (LaborIndex::from_usize(idx), v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy + Default> LaborMap<V> {
|
||||
pub fn from_default(default: V) -> Self {
|
||||
LaborMap {
|
||||
data: std::iter::repeat(default).take(*LABOR_COUNT).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy + Default> LaborMap<V> {
|
||||
pub fn from_iter(i: impl Iterator<Item = (LaborIndex, V)>, default: V) -> Self {
|
||||
let mut result = Self::from_default(default);
|
||||
for j in i {
|
||||
result.data[j.0.into_usize()] = j.1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn map<U: Default + Copy>(&self, f: impl Fn(LaborIndex, &V) -> U) -> LaborMap<U> {
|
||||
LaborMap {
|
||||
data: self.iter().map(|i| f(i.0, i.1)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AreaResources {
|
||||
pub resource_sum: GoodMap<f32>,
|
||||
pub resource_chunks: GoodMap<f32>,
|
||||
pub chunks: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NaturalResources {
|
||||
// resources per distance, we should increase labor cost for far resources
|
||||
pub per_area: Vec<AreaResources>,
|
||||
|
||||
// computation simplifying cached values
|
||||
pub chunks_per_resource: GoodMap<f32>,
|
||||
pub average_yield_per_chunk: GoodMap<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct RawProfessions(Vec<RawProfession>);
|
||||
|
||||
impl assets::Asset for RawProfessions {
|
||||
type Loader = assets::RonLoader;
|
||||
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
pub fn default_professions() -> Vec<Profession> {
|
||||
RawProfessions::load_expect("common.professions")
|
||||
.read()
|
||||
.0
|
||||
.iter()
|
||||
.map(|r| Profession {
|
||||
name: r.name.clone(),
|
||||
orders: r
|
||||
.orders
|
||||
.iter()
|
||||
.map(|i| (i.0.try_into().unwrap_or_default(), i.1))
|
||||
.collect(),
|
||||
products: r
|
||||
.products
|
||||
.first()
|
||||
.map(|p| (p.0.try_into().unwrap_or_default(), p.1))
|
||||
.unwrap_or_default(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref LABOR: Vec<Profession> = default_professions();
|
||||
// used to define resources needed by every person
|
||||
static ref DUMMY_LABOR: Labor = Labor(
|
||||
LABOR
|
||||
.iter()
|
||||
.position(|a| a.name == "_")
|
||||
.unwrap_or(0) as u8,
|
||||
PhantomData
|
||||
);
|
||||
// do not count the DUMMY_LABOR (has to be last entry)
|
||||
static ref LABOR_COUNT: usize = LABOR.len()-1;
|
||||
}
|
||||
|
||||
impl fmt::Debug for Labor {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if (self.0 as usize) < *LABOR_COUNT {
|
||||
f.write_str(&LABOR[self.0 as usize].name)
|
||||
} else {
|
||||
f.write_str("?")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Labor {
|
||||
fn default() -> Self { *DUMMY_LABOR }
|
||||
}
|
||||
|
||||
impl Labor {
|
||||
pub fn list() -> impl Iterator<Item = Self> {
|
||||
(0..LABOR.len())
|
||||
.filter(|&i| i != (DUMMY_LABOR.0 as usize))
|
||||
.map(|i| Self(i as u8, PhantomData))
|
||||
}
|
||||
|
||||
pub fn list_full() -> impl Iterator<Item = Self> {
|
||||
(0..LABOR.len()).map(|i| Self(i as u8, PhantomData))
|
||||
}
|
||||
|
||||
pub fn is_everyone(&self) -> bool { self.0 == DUMMY_LABOR.0 }
|
||||
|
||||
pub fn orders(&self) -> Vec<(GoodIndex, f32)> {
|
||||
LABOR
|
||||
.get(self.0 as usize)
|
||||
.map_or(Vec::new(), |l| l.orders.clone())
|
||||
}
|
||||
|
||||
pub fn products(&self) -> (GoodIndex, f32) {
|
||||
LABOR
|
||||
.get(self.0 as usize)
|
||||
.map_or((GoodIndex::default(), 0.0), |l| l.products)
|
||||
}
|
||||
}
|
@ -1,11 +1,7 @@
|
||||
use crate::{
|
||||
assets::{self, AssetExt},
|
||||
sim::SimChunk,
|
||||
site::Site,
|
||||
util::{
|
||||
map_array::{enum_from_index, index_from_enum, GenericIndex, NotFound},
|
||||
DHashMap,
|
||||
},
|
||||
util::{map_array::GenericIndex, DHashMap},
|
||||
};
|
||||
use common::{
|
||||
store::Id,
|
||||
@ -13,335 +9,11 @@ use common::{
|
||||
trade::{Good, SitePrices},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
ops::{Index, IndexMut},
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use Good::*;
|
||||
|
||||
// the opaque index type into the "map" of Goods
|
||||
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct GoodIndex {
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl GenericIndex<Good, 23> for GoodIndex {
|
||||
// static list of all Goods traded
|
||||
const VALUES: [Good; GoodIndex::LENGTH] = [
|
||||
// controlled resources
|
||||
Territory(BiomeKind::Grassland),
|
||||
Territory(BiomeKind::Forest),
|
||||
Territory(BiomeKind::Lake),
|
||||
Territory(BiomeKind::Ocean),
|
||||
Territory(BiomeKind::Mountain),
|
||||
RoadSecurity,
|
||||
Ingredients,
|
||||
// produced goods
|
||||
Flour,
|
||||
Meat,
|
||||
Wood,
|
||||
Stone,
|
||||
Food,
|
||||
Tools,
|
||||
Armor,
|
||||
Potions,
|
||||
Transportation,
|
||||
// exchange currency
|
||||
Coin,
|
||||
// uncontrolled resources
|
||||
Terrain(BiomeKind::Lake),
|
||||
Terrain(BiomeKind::Mountain),
|
||||
Terrain(BiomeKind::Grassland),
|
||||
Terrain(BiomeKind::Forest),
|
||||
Terrain(BiomeKind::Desert),
|
||||
Terrain(BiomeKind::Ocean),
|
||||
];
|
||||
|
||||
fn from_usize(idx: usize) -> Self { Self { idx } }
|
||||
|
||||
fn into_usize(self) -> usize { self.idx }
|
||||
}
|
||||
|
||||
impl TryFrom<Good> for GoodIndex {
|
||||
type Error = NotFound;
|
||||
|
||||
fn try_from(e: Good) -> Result<Self, NotFound> { index_from_enum(e) }
|
||||
}
|
||||
|
||||
impl From<GoodIndex> for Good {
|
||||
fn from(gi: GoodIndex) -> Good { enum_from_index(gi) }
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for GoodIndex {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
GoodIndex::VALUES[self.idx].fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// the "map" itself
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct GoodMap<V> {
|
||||
data: [V; GoodIndex::LENGTH],
|
||||
}
|
||||
|
||||
impl<V: Default + Copy> Default for GoodMap<V> {
|
||||
fn default() -> Self {
|
||||
GoodMap {
|
||||
data: [V::default(); GoodIndex::LENGTH],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Default + Copy + PartialEq + fmt::Debug> fmt::Debug for GoodMap<V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map()
|
||||
.entries(
|
||||
self.iter()
|
||||
.filter(|i| *i.1 != V::default())
|
||||
.map(|i| (Good::from(i.0), i.1)),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<GoodIndex> for GoodMap<V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, index: GoodIndex) -> &Self::Output { &self.data[index.idx] }
|
||||
}
|
||||
|
||||
impl<V> IndexMut<GoodIndex> for GoodMap<V> {
|
||||
fn index_mut(&mut self, index: GoodIndex) -> &mut Self::Output { &mut self.data[index.idx] }
|
||||
}
|
||||
|
||||
impl<V> GoodMap<V> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (GoodIndex, &V)> + '_ {
|
||||
(&self.data)
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, v)| (GoodIndex { idx }, v))
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (GoodIndex, &mut V)> + '_ {
|
||||
(&mut self.data)
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.map(|(idx, v)| (GoodIndex { idx }, v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy> GoodMap<V> {
|
||||
pub fn from_default(default: V) -> Self {
|
||||
GoodMap {
|
||||
data: [default; GoodIndex::LENGTH],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_iter(i: impl Iterator<Item = (GoodIndex, V)>, default: V) -> Self {
|
||||
let mut result = Self::from_default(default);
|
||||
for j in i {
|
||||
result.data[j.0.idx] = j.1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn map<U: Default + Copy>(self, mut f: impl FnMut(GoodIndex, V) -> U) -> GoodMap<U> {
|
||||
let mut result = GoodMap::<U>::from_default(U::default());
|
||||
for j in self.data.iter().enumerate() {
|
||||
result.data[j.0] = f(GoodIndex::from_usize(j.0), *j.1);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn from_list<'a>(i: impl IntoIterator<Item = &'a (GoodIndex, V)>, default: V) -> Self
|
||||
where
|
||||
V: 'a,
|
||||
{
|
||||
let mut result = Self::from_default(default);
|
||||
for j in i {
|
||||
result.data[j.0.idx] = j.1;
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct RawProfession {
|
||||
pub name: String,
|
||||
pub orders: Vec<(Good, f32)>,
|
||||
pub products: Vec<(Good, f32)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Profession {
|
||||
pub name: String,
|
||||
pub orders: Vec<(GoodIndex, f32)>,
|
||||
pub products: (GoodIndex, f32),
|
||||
}
|
||||
|
||||
// reference to profession
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct Labor(u8, PhantomData<Profession>);
|
||||
|
||||
// the opaque index type into the "map" of Labors (as Labor already contains a
|
||||
// monotonous index we reuse it)
|
||||
pub type LaborIndex = Labor;
|
||||
|
||||
impl LaborIndex {
|
||||
fn from_usize(idx: usize) -> Self { Self(idx as u8, PhantomData) }
|
||||
|
||||
fn into_usize(self) -> usize { self.0 as usize }
|
||||
}
|
||||
|
||||
// the "map" itself
|
||||
#[derive(Clone)]
|
||||
pub struct LaborMap<V> {
|
||||
data: Vec<V>,
|
||||
}
|
||||
|
||||
impl<V: Default + Copy> Default for LaborMap<V> {
|
||||
fn default() -> Self {
|
||||
LaborMap {
|
||||
data: std::iter::repeat(V::default()).take(*LABOR_COUNT).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Default + Copy + PartialEq + fmt::Debug> fmt::Debug for LaborMap<V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map()
|
||||
.entries(
|
||||
self.iter()
|
||||
.filter(|i| *i.1 != V::default())
|
||||
.map(|i| (i.0, &*i.1)),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<LaborIndex> for LaborMap<V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, index: LaborIndex) -> &Self::Output { &self.data[index.into_usize()] }
|
||||
}
|
||||
|
||||
impl<V> IndexMut<LaborIndex> for LaborMap<V> {
|
||||
fn index_mut(&mut self, index: LaborIndex) -> &mut Self::Output {
|
||||
&mut self.data[index.into_usize()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> LaborMap<V> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (LaborIndex, &V)> + '_ {
|
||||
(&self.data)
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, v)| (LaborIndex::from_usize(idx), v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy + Default> LaborMap<V> {
|
||||
pub fn from_default(default: V) -> Self {
|
||||
LaborMap {
|
||||
data: std::iter::repeat(default).take(*LABOR_COUNT).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy + Default> LaborMap<V> {
|
||||
pub fn from_iter(i: impl Iterator<Item = (LaborIndex, V)>, default: V) -> Self {
|
||||
let mut result = Self::from_default(default);
|
||||
for j in i {
|
||||
result.data[j.0.into_usize()] = j.1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn map<U: Default + Copy>(&self, f: impl Fn(LaborIndex, &V) -> U) -> LaborMap<U> {
|
||||
LaborMap {
|
||||
data: self.iter().map(|i| f(i.0, i.1)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AreaResources {
|
||||
pub resource_sum: GoodMap<f32>,
|
||||
pub resource_chunks: GoodMap<f32>,
|
||||
pub chunks: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NaturalResources {
|
||||
// resources per distance, we should increase labor cost for far resources
|
||||
pub per_area: Vec<AreaResources>,
|
||||
|
||||
// computation simplifying cached values
|
||||
pub chunks_per_resource: GoodMap<f32>,
|
||||
pub average_yield_per_chunk: GoodMap<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct RawProfessions(Vec<RawProfession>);
|
||||
|
||||
impl assets::Asset for RawProfessions {
|
||||
type Loader = assets::RonLoader;
|
||||
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
pub fn default_professions() -> Vec<Profession> {
|
||||
RawProfessions::load_expect("common.professions")
|
||||
.read()
|
||||
.0
|
||||
.iter()
|
||||
.map(|r| Profession {
|
||||
name: r.name.clone(),
|
||||
orders: r
|
||||
.orders
|
||||
.iter()
|
||||
.map(|i| (i.0.try_into().unwrap_or_default(), i.1))
|
||||
.collect(),
|
||||
products: r
|
||||
.products
|
||||
.first()
|
||||
.map(|p| (p.0.try_into().unwrap_or_default(), p.1))
|
||||
.unwrap_or_default(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref LABOR: Vec<Profession> = default_professions();
|
||||
// used to define resources needed by every person
|
||||
static ref DUMMY_LABOR: Labor = Labor(
|
||||
LABOR
|
||||
.iter()
|
||||
.position(|a| a.name == "_")
|
||||
.unwrap_or(0) as u8,
|
||||
PhantomData
|
||||
);
|
||||
// do not count the DUMMY_LABOR (has to be last entry)
|
||||
static ref LABOR_COUNT: usize = LABOR.len()-1;
|
||||
}
|
||||
|
||||
impl fmt::Debug for Labor {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if (self.0 as usize) < *LABOR_COUNT {
|
||||
f.write_str(&LABOR[self.0 as usize].name)
|
||||
} else {
|
||||
f.write_str("?")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Labor {
|
||||
fn default() -> Self { *DUMMY_LABOR }
|
||||
}
|
||||
mod map_types;
|
||||
pub use map_types::{GoodIndex, GoodMap, Labor, LaborIndex, LaborMap, NaturalResources};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TradeOrder {
|
||||
@ -459,19 +131,8 @@ impl Economy {
|
||||
}
|
||||
|
||||
pub fn get_orders(&self) -> DHashMap<Option<LaborIndex>, Vec<(GoodIndex, f32)>> {
|
||||
LABOR
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, p)| {
|
||||
(
|
||||
if i == DUMMY_LABOR.0 as usize {
|
||||
None
|
||||
} else {
|
||||
Some(LaborIndex::from_usize(i))
|
||||
},
|
||||
p.orders.clone(),
|
||||
)
|
||||
})
|
||||
Labor::list_full()
|
||||
.map(|l| (if l.is_everyone() { None } else { Some(l) }, l.orders()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -479,11 +140,7 @@ impl Economy {
|
||||
// cache the site independent part of production
|
||||
lazy_static! {
|
||||
static ref PRODUCTS: LaborMap<(GoodIndex, f32)> = LaborMap::from_iter(
|
||||
LABOR
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, p)| p.products.1 > 0.0)
|
||||
.map(|(i, p)| { (LaborIndex::from_usize(i), p.products,) }),
|
||||
Labor::list().map(|p| { (p, p.products(),) }),
|
||||
(GoodIndex::default(), 0.0),
|
||||
);
|
||||
}
|
||||
@ -625,11 +282,3 @@ pub fn direct_use_goods() -> &'static [GoodIndex] {
|
||||
}
|
||||
&*DIRECT_USE
|
||||
}
|
||||
|
||||
impl Labor {
|
||||
pub fn list() -> impl Iterator<Item = Self> {
|
||||
(0..LABOR.len())
|
||||
.filter(|&i| i != (DUMMY_LABOR.0 as usize))
|
||||
.map(|i| Self(i as u8, PhantomData))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user