Skip to main content
Verticopolis engineGitHub

verticopolis_engine/view/
mod.rs

1//! What a renderer reads, sized for a frame budget. Three reads cover it:
2//!
3//! - [`structure_view`]: the floors, lobbies, rooms and shafts, as flat
4//!   records. Read it when you start, after a load, and whenever the frame
5//!   header's tower revision moves (a build, a sale, a fire).
6//! - [`ViewReader::frame`]: everything that moves, every frame: the clock,
7//!   money and rating, the people, the cars, and only the rooms whose
8//!   fields changed since this reader's last frame.
9//! - [`meta_since`]: room names and subtypes that changed, read when the
10//!   frame header's meta revision moves.
11//!
12//! [`layout`] names every slot, and [`layout_json`] hands the same tables
13//! and every code over as JSON. None of these reads changes the game.
14//!
15//! ```
16//! use verticopolis_engine::clock::GameMode;
17//! use verticopolis_engine::facilities::Kind;
18//! use verticopolis_engine::sim::Simulation;
19//! use verticopolis_engine::view::{layout, structure_view, ViewReader};
20//!
21//! let mut sim = Simulation::new_game(1, GameMode::Classic);
22//! let tiles: Vec<i64> = (100..124).collect();
23//! sim.paint_brush(Kind::Lobby, 1, &tiles);
24//!
25//! let structure = structure_view(&sim);
26//! assert_eq!(structure[layout::structure::LOWEST_FLOOR], 1.0);
27//!
28//! let mut reader = ViewReader::new();
29//! let first = reader.frame(&sim, false);
30//! assert_eq!(first[layout::header::FRAME_SEQ], 1.0);
31//! sim.tick(1.0);
32//! let next = reader.frame(&sim, false);
33//! assert_eq!(next[layout::header::FRAME_SEQ], 2.0);
34//! ```
35pub mod layout;
36mod marks;
37mod meta;
38mod reader;
39mod signature;
40mod structure;
41#[cfg(any(feature = "wasm", test))]
42mod tally;
43
44use std::cell::RefCell;
45
46pub use layout::{layout_json, VIEW_LAYOUT_VERSION};
47use marks::FrameMarks;
48pub use meta::meta_since;
49pub(crate) use meta::FIRST_META_REVISION;
50#[doc(hidden)]
51pub use meta::{meta_changed, whole_revision, MetaLog};
52pub use reader::ViewReader;
53pub use structure::structure_view;
54#[cfg(all(feature = "wasm", test))]
55pub(crate) use tally::TallyPasses;
56#[cfg(any(feature = "wasm", test))]
57pub(crate) use tally::{CensusTally, RecyclingCounts};
58
59use crate::sim::Simulation;
60
61#[doc(hidden)]
62/// What the view keeps on the tower between reads: the metadata log and the
63/// frame mark log the setters write, and the binding's frame reader.
64pub struct ViewState {
65    pub(crate) meta_log: MetaLog,
66    pub(crate) marks: FrameMarks,
67    pub(crate) reader: RefCell<ViewReader>,
68}
69
70impl Default for ViewState {
71    fn default() -> ViewState {
72        ViewState {
73            meta_log: MetaLog::new(),
74            marks: FrameMarks::default(),
75            reader: RefCell::new(ViewReader::new()),
76        }
77    }
78}
79
80#[doc(hidden)]
81/// The dynamic frame from the tower's own reader (the binding's): one
82/// reader per engine, so a second caller sees only what changed since the
83/// first one's read. `full` asks for every room.
84pub fn view_frame(sim: &Simulation, full: bool) -> Vec<f64> {
85    sim.tower.view.reader.borrow_mut().frame(sim, full)
86}
87
88#[cfg(test)]
89#[path = "census_reads_tests.rs"]
90mod census_reads_tests;
91#[cfg(test)]
92#[path = "frame_tests.rs"]
93mod frame_tests;
94#[cfg(test)]
95#[path = "layout_tests.rs"]
96mod layout_tests;
97#[cfg(test)]
98#[path = "lexer_tests.rs"]
99mod lexer_tests;
100#[cfg(test)]
101#[path = "marks_guard_tests.rs"]
102mod marks_guard_tests;
103#[cfg(test)]
104#[path = "marks_tests.rs"]
105mod marks_tests;
106#[cfg(test)]
107#[path = "merge_guard_tests.rs"]
108mod merge_guard_tests;
109#[cfg(test)]
110#[path = "meta_tests.rs"]
111mod meta_tests;
112#[cfg(test)]
113#[path = "oracle_tests.rs"]
114mod oracle_tests;
115#[cfg(test)]
116#[path = "session_tests.rs"]
117mod session_tests;
118#[cfg(test)]
119#[path = "signature_tests.rs"]
120mod signature_tests;
121#[cfg(test)]
122#[path = "source_scan_tests.rs"]
123mod source_scan_tests;
124#[cfg(test)]
125#[path = "structure_tests.rs"]
126mod structure_tests;
127#[cfg(test)]
128#[path = "tally_tests.rs"]
129mod tally_tests;
130#[cfg(test)]
131#[path = "unit_scan_tests.rs"]
132mod unit_scan_tests;
133#[cfg(test)]
134#[path = "write_cases_tests.rs"]
135mod write_cases_tests;