banished_game/work/construction/
machine.rs1use super::*;
5
6#[derive(Debug, Clone, Default)]
10pub struct Machine {
11 pub controllers: Vec<Controller>,
13 pub current: usize,
15 pub state: i8,
17 pub index: i8,
19 pub pending: i8,
21 pub transition: i8,
23}
24
25pub fn run(host: &mut impl Callbacks, jobs: &mut Jobs, site: usize, scheduled: bool, update: bool) {
30 let mut update = update;
31 loop {
32 while host.machine(site).pending >= 0 {
33 let m = host.machine(site);
34 if m.state >= 0 {
35 let (state, mut node, mut index) = (m.state, m.current, m.index as i32);
37 loop {
38 let m = host.machine(site);
39 let f = if index >= 0 {
40 m.controllers[node].table()[index as usize].exit
41 } else {
42 C::None
43 };
44 if index >= 0 && host.call(jobs, site, f) {
45 break;
46 }
47 let Some(prev) = node.checked_sub(1) else {
48 break;
49 };
50 node = prev;
51 index = host.machine(site).controllers[node]
52 .find(state)
53 .map_or(-1, |i| i as i32);
54 }
55 let m = host.machine(site);
56 if m.transition >= 0 && m.index >= 0 {
57 let f = m.controllers[m.current].table()[m.index as usize].transitions
58 [m.transition as usize]
59 .1;
60 host.call(jobs, site, f);
61 }
62 }
63 let m = host.machine(site);
64 m.state = m.pending;
65 let last = m.controllers.len() - 1;
66 let Some((node, index)) = m.find_from(last, m.state) else {
67 m.pending = -1;
68 m.transition = -1;
69 m.index = -1;
70 break;
71 };
72 m.current = node;
73 m.index = index as i8;
74 m.pending = -1;
75 m.transition = -1;
76 let state = m.state;
77 let (mut node, mut index) = (node, index as i32);
79 loop {
80 let f = if index >= 0 {
81 host.machine(site).controllers[node].table()[index as usize].enter
82 } else {
83 C::None
84 };
85 if index >= 0 && host.call(jobs, site, f) {
86 break;
87 }
88 let Some(prev) = node.checked_sub(1) else {
89 break;
90 };
91 node = prev;
92 index = host.machine(site).controllers[node]
93 .find(state)
94 .map_or(-1, |i| i as i32);
95 }
96 }
97 if update && host.machine(site).state >= 0 {
98 update = false;
99 if scheduled {
100 let m = host.machine(site);
101 let (state, mut node, mut index) = (m.state, m.current, m.index as i32);
102 loop {
103 let f = if index >= 0 {
104 host.machine(site).controllers[node].table()[index as usize].update
105 } else {
106 C::None
107 };
108 if index >= 0 && host.call(jobs, site, f) {
109 break;
110 }
111 let Some(prev) = node.checked_sub(1) else {
112 break;
113 };
114 node = prev;
115 index = host.machine(site).controllers[node]
116 .find(state)
117 .map_or(-1, |i| i as i32);
118 }
119 }
120 }
122 if host.machine(site).pending < 0 {
123 return;
124 }
125 }
126}
127
128impl Machine {
129 pub fn new(controllers: Vec<Controller>) -> Machine {
133 let pending = controllers.first().map_or(-1, |c| c.initial());
134 Machine {
135 current: controllers.len().saturating_sub(1),
136 controllers,
137 state: -1,
138 index: -1,
139 pending,
140 transition: -1,
141 }
142 }
143
144 pub(super) fn find_from(&self, mut node: usize, state: i8) -> Option<(usize, usize)> {
146 loop {
147 if let Some(i) = self.controllers[node].find(state) {
148 return Some((node, i));
149 }
150 node = node.checked_sub(1)?;
151 }
152 }
153
154 pub fn request(&mut self, msg: i8) {
158 if self.index < 0 {
159 return;
160 }
161 let def = &self.controllers[self.current].table()[self.index as usize];
162 if let Some(t) = def.transitions.iter().position(|t| t.0 == msg) {
163 self.transition = t as i8;
164 self.pending = msg;
165 }
166 }
167}