120 lines
3.7 KiB
Rust
120 lines
3.7 KiB
Rust
use crate::Currency;
|
|
use crate::game::{Game, State};
|
|
use std::collections::VecDeque;
|
|
use std::fmt::{Debug, Formatter, format};
|
|
use std::ops::Mul;
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) struct UnlockSystem {
|
|
bought: usize,
|
|
last_unlock: Option<String>,
|
|
unlock_queue: VecDeque<Unlock>,
|
|
}
|
|
|
|
pub(crate) struct Unlock {
|
|
pub(crate) name: String,
|
|
pub(crate) cost: Currency,
|
|
pub(crate) apply: Box<dyn Fn(&mut State)>,
|
|
}
|
|
|
|
impl Debug for Unlock {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
f.write_fmt(format_args!(
|
|
"Upgrade {{ name: {:?}, cost: {:?} }}",
|
|
self.name, self.cost
|
|
))
|
|
}
|
|
}
|
|
|
|
impl UnlockSystem {
|
|
pub(crate) fn new(start_state: &State) -> Self {
|
|
let mut upgrades = start_state
|
|
.bars
|
|
.iter()
|
|
.enumerate()
|
|
.flat_map(|(index, bar)| {
|
|
let initial_cost = 10usize.pow(index as u32);
|
|
[
|
|
Unlock {
|
|
name: format!("Start {}", bar.name()),
|
|
cost: initial_cost as f64,
|
|
apply: Box::new(move |game| {
|
|
game.bars[index].enabled = true;
|
|
}),
|
|
},
|
|
Unlock {
|
|
name: format!("{} productivity", bar.name()),
|
|
cost: initial_cost.mul(2) as f64,
|
|
apply: Box::new(move |game| {
|
|
game.bars[index].productivity *= 2.0;
|
|
}),
|
|
},
|
|
Unlock {
|
|
name: format!("{} speed", bar.name()),
|
|
cost: initial_cost.mul(20) as f64,
|
|
apply: Box::new(move |game| {
|
|
game.bars[index].speed *= 1.5;
|
|
}),
|
|
},
|
|
]
|
|
})
|
|
.chain(
|
|
(1..10).map(|level|
|
|
Unlock {
|
|
name: format!("The answer {}", level),
|
|
cost: (42usize * 10usize.pow(level)) as f64,
|
|
apply: Box::new(move |game| {
|
|
game.speed *= 1.1;
|
|
}),
|
|
}
|
|
)
|
|
)
|
|
.chain(
|
|
(1..10).map(|level|
|
|
Unlock {
|
|
name: format!("??? {}", level),
|
|
cost: (23usize * 10usize.pow(level)) as f64,
|
|
apply: Box::new(move |game| {
|
|
game.productivity *= 1.1;
|
|
}),
|
|
},
|
|
)
|
|
)
|
|
.collect::<Vec<_>>();
|
|
upgrades.sort_by(|l, r| l.cost.total_cmp(&r.cost));
|
|
|
|
let unlock_queue = upgrades.into();
|
|
|
|
Self {
|
|
unlock_queue,
|
|
bought: 0,
|
|
last_unlock: None
|
|
}
|
|
}
|
|
|
|
pub(crate) fn peek_next(&self) -> Option<&Unlock> {
|
|
self.unlock_queue.front()
|
|
}
|
|
|
|
pub(crate) fn check_next(&mut self, state: &mut State) {
|
|
if let Some(next_upgrade) = self.peek_next() {
|
|
if next_upgrade.cost <= state.currency {
|
|
log::info!("Applying upgrade {:?}", next_upgrade);
|
|
let next_upgrade = self.unlock_queue.pop_front().unwrap();
|
|
state.currency -= next_upgrade.cost;
|
|
(next_upgrade.apply)(state);
|
|
self.last_unlock = Some(next_upgrade.name);
|
|
self.bought += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn bought(&self) -> usize {
|
|
self.bought
|
|
}
|
|
|
|
pub(crate) fn previous(&self) -> Option<&String> {
|
|
self.last_unlock.as_ref()
|
|
}
|
|
}
|