generated upgrades and bars
This commit is contained in:
parent
e07fac4211
commit
74d146242b
|
@ -21,9 +21,11 @@ impl Bar {
|
|||
progress: 0f64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
pub(crate) fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
|
||||
pub(crate) fn progress(&mut self, delta: Duration) -> Currency {
|
||||
if !self.enabled {
|
||||
return 0.0;
|
||||
|
@ -36,9 +38,7 @@ impl Bar {
|
|||
|
||||
completions * self.productivity
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
pub fn draw<C: GridMut<char>, P: GridMut<bool>>(&self, chars: &mut C, bitmap: &mut P) {
|
||||
if !self.enabled {
|
||||
return;
|
||||
|
|
119
src/game.rs
119
src/game.rs
|
@ -1,4 +1,4 @@
|
|||
use crate::unlocks::UnlockSystem;
|
||||
use crate::unlocks::{Unlock, UnlockSystem};
|
||||
use crate::{Currency, bar::Bar};
|
||||
use servicepoint::{Bitmap, CharGrid, CharGridMutExt, TILE_SIZE, WindowMut};
|
||||
use std::time::Duration;
|
||||
|
@ -11,36 +11,50 @@ pub struct Game {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct State<const STEP_COUNT: usize = 11> {
|
||||
pub struct State {
|
||||
pub(crate) currency: Currency,
|
||||
pub(crate) speed: f64,
|
||||
pub(crate) productivity: f64,
|
||||
pub(crate) bars: [Bar; STEP_COUNT],
|
||||
pub(crate) bars: Vec<Bar>,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
const BAR_NAMES: [&'static str; 11] = [
|
||||
"Powering infrastructure",
|
||||
"Dusting ServicePoint",
|
||||
"Activating colorful lights",
|
||||
"Dimming darkroom",
|
||||
"Refilling Matemat",
|
||||
"Pre-heating convectiomat",
|
||||
"Resetting chair heights",
|
||||
"Untangling 'block chain'",
|
||||
"Refilling sticker box",
|
||||
"Setting room to public",
|
||||
"Welcoming creatures",
|
||||
];
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
total_currency: 0f64,
|
||||
unlocks: UnlockSystem::new(),
|
||||
state: State {
|
||||
currency: 0f64,
|
||||
let bars = Self::BAR_NAMES
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, name)| {
|
||||
Bar::new(
|
||||
2usize.pow(index as u32) as f64,
|
||||
1.0 * (0.5f64.powi(index as i32)),
|
||||
*name,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let state = State {
|
||||
bars,
|
||||
currency: 1f64,
|
||||
speed: 1f64,
|
||||
productivity: 1f64,
|
||||
bars: [
|
||||
Bar::new(1f64, 1.0, "Powering infrastructure"),
|
||||
Bar::new(2f64, 0.5, "Dusting ServicePoint"),
|
||||
Bar::new(4f64, 0.25, "Activating colorful lights"),
|
||||
Bar::new(8f64, 0.125, "Dimming darkroom"),
|
||||
Bar::new(16f64, 0.0625, "Refilling Matemat"),
|
||||
Bar::new(32f64, 0.03125, "Pre-heating convectiomat"),
|
||||
Bar::new(64f64, 0.015625, "Resetting chair heights"),
|
||||
Bar::new(128f64, 0.0078125, "Untangling 'block chain'"),
|
||||
Bar::new(256f64, 0.00390625, "Refilling sticker box"),
|
||||
Bar::new(512f64, 0.001953125, "Setting room to public"),
|
||||
Bar::new(1024f64, 0.000976562, "Welcoming creatures"),
|
||||
],
|
||||
},
|
||||
};
|
||||
Self {
|
||||
total_currency: 0f64,
|
||||
unlocks: UnlockSystem::new(&state),
|
||||
state,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,34 +81,33 @@ impl Game {
|
|||
text_layer
|
||||
.set_row_str(0, "Discordia Boot Procedure")
|
||||
.unwrap();
|
||||
let middle = text_layer.width() / 2;
|
||||
text_layer
|
||||
.window_mut(middle, 0, middle, 1)
|
||||
.unwrap()
|
||||
.set_row_str(0, &format!(" Hacks: {}", self.state.currency.floor()))
|
||||
.unwrap();
|
||||
self.draw_bars(text_layer, pixel_layer, 1);
|
||||
|
||||
for (index, bar) in self.state.bars.iter().enumerate() {
|
||||
let row = 2 + index;
|
||||
let mut bar_window = pixel_layer
|
||||
.window_mut(0, row * TILE_SIZE, pixel_layer.width(), TILE_SIZE)
|
||||
.unwrap();
|
||||
let mut label_window = text_layer
|
||||
.window_mut(0, row, text_layer.width(), 1)
|
||||
.unwrap();
|
||||
bar.draw(&mut label_window, &mut bar_window);
|
||||
}
|
||||
let mut row = text_layer.height() - 1;
|
||||
self.draw_stats(text_layer, row);
|
||||
row -= 1;
|
||||
|
||||
if let Some(next_upgrade) = self.unlocks.peek_next() {
|
||||
self.draw_next_upgrade(text_layer, row, next_upgrade);
|
||||
row -= 1;
|
||||
}
|
||||
|
||||
if let Some(prev_unlock) = self.unlocks.previous() {
|
||||
self.draw_prev_unlock(text_layer, row, prev_unlock);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_next_upgrade(&self, text_layer: &mut WindowMut<char, CharGrid>, row: usize, next_upgrade: &Unlock) {
|
||||
text_layer
|
||||
.window_mut(0, text_layer.height() - 2, text_layer.width(), 1)
|
||||
.window_mut(0, row, text_layer.width(), 1)
|
||||
.unwrap()
|
||||
.set_row_str(0, &format!("Next unlock for {} Hacks", next_upgrade.cost))
|
||||
.set_row_str(0, &format!("Next unlock: {:.0}/{} Hacks", self.state.currency, next_upgrade.cost))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn draw_stats(&self, text_layer: &mut WindowMut<char, CharGrid>, row: usize) {
|
||||
text_layer
|
||||
.window_mut(0, text_layer.height() - 1, text_layer.width() / 2, 1)
|
||||
.window_mut(0, row, text_layer.width() / 2, 1)
|
||||
.unwrap()
|
||||
.set_row_str(0, &format!("Hack Score: {:.2}", self.total_currency))
|
||||
.unwrap();
|
||||
|
@ -103,7 +116,7 @@ impl Game {
|
|||
text_layer
|
||||
.window_mut(
|
||||
text_layer.width() / 2,
|
||||
text_layer.height() - 1,
|
||||
row,
|
||||
text_layer.width() / 2,
|
||||
1,
|
||||
)
|
||||
|
@ -112,4 +125,26 @@ impl Game {
|
|||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_bars(&self, text_layer: &mut WindowMut<char, CharGrid>, pixel_layer: &mut WindowMut<bool, Bitmap>, mut row: usize) {
|
||||
for bar in self.state.bars.iter() {
|
||||
let mut bar_window = pixel_layer
|
||||
.window_mut(0, row * TILE_SIZE, pixel_layer.width(), TILE_SIZE)
|
||||
.unwrap();
|
||||
let mut label_window = text_layer
|
||||
.window_mut(0, row, text_layer.width(), 1)
|
||||
.unwrap();
|
||||
bar.draw(&mut label_window, &mut bar_window);
|
||||
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_prev_unlock(&self, chars: &mut WindowMut<char, CharGrid>, row: usize, prev: &String) {
|
||||
chars
|
||||
.window_mut(0, row, chars.width(), 1)
|
||||
.unwrap()
|
||||
.set_row_str(0, &format!("Unlocked: {}", prev))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,6 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
sleep(FRAME_PACING);
|
||||
sleep(FRAME_PACING / 2);
|
||||
}
|
||||
}
|
||||
|
|
179
src/unlocks.rs
179
src/unlocks.rs
|
@ -1,18 +1,20 @@
|
|||
use crate::Currency;
|
||||
use crate::game::{Game, State};
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
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: &'static str,
|
||||
pub(crate) name: String,
|
||||
pub(crate) cost: Currency,
|
||||
pub(crate) apply: fn(&mut State),
|
||||
pub(crate) apply: Box<dyn Fn(&mut State)>,
|
||||
}
|
||||
|
||||
impl Debug for Unlock {
|
||||
|
@ -25,124 +27,68 @@ impl Debug for Unlock {
|
|||
}
|
||||
|
||||
impl UnlockSystem {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
bought: 0,
|
||||
unlock_queue: vec![
|
||||
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: "Start Powering infrastructure",
|
||||
cost: 0f64,
|
||||
apply: |game| {
|
||||
game.bars[0].enabled = true;
|
||||
},
|
||||
name: format!("Start {}", bar.name()),
|
||||
cost: initial_cost as f64,
|
||||
apply: Box::new(move |game| {
|
||||
game.bars[index].enabled = true;
|
||||
}),
|
||||
},
|
||||
Unlock {
|
||||
name: "More power",
|
||||
cost: 10f64,
|
||||
apply: |game| {
|
||||
game.bars[0].productivity *= 2.0;
|
||||
},
|
||||
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: "",
|
||||
cost: 23f64,
|
||||
apply: |game| {
|
||||
game.productivity *= 1.1;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "The answer",
|
||||
cost: 42f64,
|
||||
apply: |game| {
|
||||
game.speed *= 1.1;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Dusting ServicePoint",
|
||||
cost: 64f64,
|
||||
apply: |game| {
|
||||
game.bars[1].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Dust filters",
|
||||
cost: 100f64,
|
||||
apply: |game| {
|
||||
game.bars[1].productivity *= 2.0;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "HASS automation",
|
||||
cost: 128f64,
|
||||
apply: |game| {
|
||||
game.bars[0].speed *= 1.5;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Activating colorful lights",
|
||||
cost: 256f64,
|
||||
apply: |game| {
|
||||
game.bars[2].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Dimming darkroom",
|
||||
cost: 1024f64,
|
||||
apply: |game| {
|
||||
game.bars[3].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Refilling Matemat",
|
||||
cost: 4096f64,
|
||||
apply: |game| {
|
||||
game.bars[4].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Pre-heating convectiomat",
|
||||
cost: 16384f64,
|
||||
apply: |game| {
|
||||
game.bars[5].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Resetting chair heights",
|
||||
cost: 65536f64,
|
||||
apply: |game| {
|
||||
game.bars[6].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Untangling 'block chain'",
|
||||
cost: 262144f64,
|
||||
apply: |game| {
|
||||
game.bars[7].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Refilling sticker box",
|
||||
cost: 1048576f64,
|
||||
apply: |game| {
|
||||
game.bars[8].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Setting room to public",
|
||||
cost: 4194304f64,
|
||||
apply: |game| {
|
||||
game.bars[9].enabled = true;
|
||||
},
|
||||
},
|
||||
Unlock {
|
||||
name: "Start Welcoming creatures",
|
||||
cost: 16777216f64,
|
||||
apply: |game| {
|
||||
game.bars[10].enabled = true;
|
||||
},
|
||||
name: format!("{} speed", bar.name()),
|
||||
cost: initial_cost.mul(20) as f64,
|
||||
apply: Box::new(move |game| {
|
||||
game.bars[index].speed *= 1.5;
|
||||
}),
|
||||
},
|
||||
]
|
||||
.into(),
|
||||
})
|
||||
.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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +103,7 @@ impl UnlockSystem {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -165,4 +112,8 @@ impl UnlockSystem {
|
|||
pub(crate) fn bought(&self) -> usize {
|
||||
self.bought
|
||||
}
|
||||
|
||||
pub(crate) fn previous(&self) -> Option<&String> {
|
||||
self.last_unlock.as_ref()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue