1use super::*;
4
5impl WorkHost for Sim<'_, '_> {
6 fn profession(&self, c: usize) -> usize {
7 self.states[c].profession
8 }
9 fn workplace(&self, c: usize) -> Option<usize> {
10 self.states[c].workplace
11 }
12 fn cell(&self, c: usize) -> i32 {
13 self.citizen_cell(c)
14 }
15 fn has_emergency(&self, c: usize) -> bool {
16 let s = &self.states[c];
17 crate::disasters::fire::has_emergency(
18 self.cells,
19 self.placed,
20 s.home,
21 s.workplace,
22 self.characters[c].position,
23 )
24 }
25 fn works_anywhere(&self, p: usize) -> bool {
26 self.professions.works_anywhere(p)
27 }
28 fn rank(&mut self, a: i32, b: i32) -> i32 {
29 self.rank_or_distance(a, b)
30 }
31 fn stock(&self, slot: usize) -> (i32, i32) {
32 self.stock[slot]
33 }
34 fn laborer(&self) -> usize {
35 self.professions.laborer
36 }
37 fn builder(&self) -> usize {
38 self.professions.builder
39 }
40 fn rng(&mut self) -> &mut Random {
41 self.rng
42 }
43 fn take_events(&mut self) -> Vec<JobEvent> {
44 std::mem::take(&mut self.events)
45 }
46
47 fn refresh(&mut self, work: &mut Work) {
49 let id = work.id;
50 let gone: Vec<usize> = match &work.kind {
51 WorkKind::Gather(g) => g.workers.iter().copied(),
52 WorkKind::Build(b) => b.workers.iter().copied(),
53 WorkKind::Clear(_) => return self.clear_refresh(work),
54 WorkKind::Pickup(_) => return self.pickup_refresh(work),
55 WorkKind::Produce(_) => return self.produce_refresh(work),
56 WorkKind::Fishing(_) => return self.fishing_refresh(work),
57 WorkKind::PlantArea(_) | WorkKind::Harvest(_) | WorkKind::PickFruit(_) => {
58 return self.area_refresh(work)
59 }
60 WorkKind::PlantOrchard(_) => return self.plant_orchard_refresh(work),
61 WorkKind::Herbalist(h)
63 | WorkKind::Forester(h)
64 | WorkKind::Hunt(h)
65 | WorkKind::TendArea(h)
66 | WorkKind::Pasture(h)
67 | WorkKind::ClearStorage(h)
68 | WorkKind::Fire(h) => h.workers.iter().copied(),
69 WorkKind::Road(r) => {
71 if let Some(c) = r.builder {
72 if self.characters[c].stack.holds_task(id).is_none() {
73 if let WorkKind::Road(r) = &mut work.kind {
74 r.builder = None;
75 }
76 }
77 }
78 return;
79 }
80 WorkKind::Trade(t) => {
82 let gone: Vec<usize> = t
83 .haulers
84 .keys()
85 .copied()
86 .filter(|&c| self.characters[c].stack.holds_task(id).is_none())
87 .collect();
88 if let WorkKind::Trade(t) = &mut work.kind {
89 for c in gone {
90 t.haulers.remove(&c);
91 }
92 }
93 return;
94 }
95 WorkKind::Location(l) => {
97 if let Some(c) = l.worker {
98 if self.characters[c].stack.holds_task(id).is_none() {
99 if let WorkKind::Location(l) = &mut work.kind {
100 l.worker = None;
101 }
102 }
103 }
104 return;
105 }
106 WorkKind::Market(m) => {
108 let gone: Vec<usize> = m
109 .plans
110 .keys()
111 .copied()
112 .filter(|&c| self.characters[c].stack.holds_task(id).is_none())
113 .collect();
114 if let WorkKind::Market(m) = &mut work.kind {
115 for c in gone {
116 m.plans.remove(&c);
117 }
118 }
119 return;
120 }
121 WorkKind::Test(_) => return,
122 }
123 .filter(|&c| self.characters[c].stack.holds_task(id).is_none())
124 .collect();
125 if gone.is_empty() {
126 return;
127 }
128 match &mut work.kind {
129 WorkKind::Gather(g) => {
130 for c in &gone {
131 g.workers.remove(c);
132 }
133 }
134 WorkKind::Build(b) => {
135 for c in &gone {
136 b.workers.remove(c);
137 }
138 let held: Vec<i32> = b
139 .workers
140 .iter()
141 .filter_map(|&c| self.characters[c].stack.holds_task(id))
142 .collect();
143 for (k, o) in b.occupied.iter_mut().enumerate() {
144 *o = held.contains(&(k as i32));
145 }
146 }
147 WorkKind::Herbalist(h)
148 | WorkKind::Forester(h)
149 | WorkKind::Hunt(h)
150 | WorkKind::TendArea(h)
151 | WorkKind::Pasture(h)
152 | WorkKind::ClearStorage(h)
153 | WorkKind::Fire(h) => {
154 for c in &gone {
155 h.workers.remove(c);
156 }
157 }
158 WorkKind::Clear(_)
159 | WorkKind::Pickup(_)
160 | WorkKind::Produce(_)
161 | WorkKind::Fishing(_)
162 | WorkKind::PlantArea(_)
163 | WorkKind::Harvest(_)
164 | WorkKind::PlantOrchard(_)
165 | WorkKind::PickFruit(_)
166 | WorkKind::Location(_)
167 | WorkKind::Market(_)
168 | WorkKind::Trade(_)
169 | WorkKind::Road(_)
170 | WorkKind::Test(_) => {}
171 }
172 if let WorkKind::Gather(_) = work.kind {
173 self.cancel(work);
174 if let WorkKind::Gather(g) = &mut work.kind {
175 g.transit.iter_mut().for_each(|t| *t = 0);
176 }
177 }
178 }
179
180 fn try_assign(&mut self, work: &mut Work, c: usize, time: i64) -> u8 {
181 match work.kind {
182 WorkKind::Gather(_) => self.gather_try(work, c, time),
183 WorkKind::Build(_) => self.build_try(work, c),
184 WorkKind::Clear(_) => self.clear_try(work, c, time),
185 WorkKind::Pickup(_) => self.pickup_try(work, c, time),
186 WorkKind::Produce(_) => self.produce_try(work, c, time),
187 WorkKind::Location(_) => self.location_try(work, c),
188 WorkKind::ClearStorage(_) => self.clear_storage_try(work, c, time),
189 WorkKind::Fire(_) => self.fire_try(work, c, time),
190 WorkKind::Trade(_) => self.trade_try(work, c),
191 WorkKind::Road(_) => self.road_try(work, c, time),
192 WorkKind::Market(_) => self.market_try(work, c),
193 WorkKind::Fishing(_) => self.fishing_try(work, c),
194 WorkKind::PlantArea(_) => self.plant_try(work, c),
195 WorkKind::PlantOrchard(_) => self.plant_orchard_try(work, c),
196 WorkKind::TendArea(_) => {
197 if self
198 .sites
199 .get(&work.entity)
200 .is_some_and(|s| s.orchard.is_some())
201 {
202 self.tend_orchard_try(work, c)
203 } else {
204 self.tend_try(work, c)
205 }
206 }
207 WorkKind::PickFruit(_) => {
208 let works: BTreeSet<i32> = self.piles.values().map(|p| p.work).collect();
209 if self.auto_pickup_offers(work.entity, |id| works.contains(&id)) {
210 return NESTED;
211 }
212 self.pick_fruit_try(work, c)
213 }
214 WorkKind::Harvest(_) => {
215 let works: BTreeSet<i32> = self.piles.values().map(|p| p.work).collect();
216 if self.auto_pickup_offers(work.entity, |id| works.contains(&id)) {
217 return NESTED;
218 }
219 self.harvest_try(work, c)
220 }
221 WorkKind::Herbalist(_)
222 | WorkKind::Forester(_)
223 | WorkKind::Hunt(_)
224 | WorkKind::Pasture(_) => {
225 self.pasture_stage = false;
226 let works: BTreeSet<i32> = self.piles.values().map(|p| p.work).collect();
227 if self.auto_pickup_offers(work.entity, |id| works.contains(&id)) {
228 return NESTED;
229 }
230 self.resume(work, c)
231 }
232 WorkKind::Test(_) => 0,
233 }
234 }
235
236 fn take_offers(&mut self) -> Vec<i32> {
237 std::mem::take(&mut self.offers)
238 }
239
240 fn offers_again(&mut self) -> bool {
241 std::mem::take(&mut self.offers_again)
242 }
243
244 fn resume(&mut self, work: &mut Work, c: usize) -> u8 {
245 match work.kind {
246 WorkKind::Produce(_) => self.produce_resume(work, c),
247 WorkKind::Herbalist(_) => self.herbalist_try(work, c),
248 WorkKind::Forester(_) => self.forester_try(work, c),
249 WorkKind::Hunt(_) => self.hunt_try(work, c),
250 WorkKind::Harvest(_) => self.harvest_try(work, c),
251 WorkKind::PickFruit(_) => self.pick_fruit_try(work, c),
252 WorkKind::Pasture(_) => self.pasture_try(work, c),
253 _ => 1,
254 }
255 }
256
257 fn complete(&mut self, work: &mut Work, c: usize, param: i32) -> bool {
258 match &mut work.kind {
259 WorkKind::Gather(g) => {
260 g.workers.remove(&c);
261 let i = (param & 0xff) as usize;
262 if let Some(t) = g.transit.get_mut(i) {
263 *t -= param >> 8;
264 }
265 if let Some(s) = g.stored.get_mut(i) {
266 *s += param >> 8;
267 }
268 }
269 WorkKind::Build(b) => {
270 b.workers.remove(&c);
271 if let Some(o) = b.occupied.get_mut(param as usize) {
272 *o = false;
273 }
274 }
275 WorkKind::Clear(cl) => {
277 cl.resources.retain(|_, &mut w| w != c);
278 cl.cells.remove(¶m);
279 }
280 WorkKind::Pickup(_) => {
282 if let Some(p) = self.piles.get_mut(&work.entity) {
283 p.claimer = None;
284 p.state = 2;
285 }
286 }
287 WorkKind::Produce(_) => Self::produce_complete(work, param, false),
288 WorkKind::Fishing(_) => Self::fishing_complete(work, param),
289 WorkKind::PlantArea(_) | WorkKind::Harvest(_) => Self::area_complete(work, param),
290 WorkKind::PlantOrchard(_) => Self::plant_orchard_done(work, param),
291 WorkKind::PickFruit(_) => Self::pick_done(work, param, false),
292 WorkKind::Location(l) => l.worker = None,
294 WorkKind::Herbalist(h)
296 | WorkKind::Forester(h)
297 | WorkKind::Hunt(h)
298 | WorkKind::TendArea(h)
299 | WorkKind::Pasture(h)
300 | WorkKind::ClearStorage(h)
301 | WorkKind::Fire(h) => {
303 h.workers.remove(&c);
304 }
305 WorkKind::Market(m) => {
307 m.plans.remove(&c);
308 }
309 WorkKind::Trade(t) => {
311 t.haulers.remove(&c);
312 }
313 WorkKind::Road(r) => {
315 r.builder = None;
316 return param == 1;
317 }
318 WorkKind::Test(_) => {}
319 }
320 false
321 }
322
323 fn fail(&mut self, work: &mut Work, c: usize, param: i32) {
324 match &mut work.kind {
325 WorkKind::Gather(g) => {
326 g.workers.remove(&c);
327 if let Some(t) = g.transit.get_mut((param & 0xff) as usize) {
328 *t -= param >> 8;
329 }
330 }
331 WorkKind::Build(b) => {
332 b.workers.remove(&c);
333 if let Some(o) = b.occupied.get_mut(param as usize) {
334 *o = false;
335 }
336 }
337 WorkKind::Clear(cl) => {
339 cl.resources.retain(|_, &mut w| w != c);
340 cl.cells.remove(¶m);
341 }
342 WorkKind::Pickup(_) => {
344 if let Some(p) = self.piles.get_mut(&work.entity) {
345 p.claimer = None;
346 p.state = 0;
347 }
348 }
349 WorkKind::Produce(_) => Self::produce_complete(work, param, true),
350 WorkKind::Fishing(_) => Self::fishing_complete(work, param),
352 WorkKind::PlantArea(_) | WorkKind::Harvest(_) => Self::area_fail(work, param),
353 WorkKind::PlantOrchard(_) => Self::plant_orchard_done(work, param),
354 WorkKind::PickFruit(_) => Self::pick_done(work, param, true),
355 WorkKind::Location(l) => l.worker = None,
356 WorkKind::Pasture(_) => self.pasture_fail(work, c, param),
357 WorkKind::ClearStorage(h) | WorkKind::Fire(h) => {
359 h.workers.remove(&c);
360 }
361 WorkKind::Herbalist(h)
362 | WorkKind::Forester(h)
363 | WorkKind::Hunt(h)
364 | WorkKind::TendArea(h) => {
365 h.workers.remove(&c);
366 }
367 WorkKind::Market(m) => {
369 m.plans.remove(&c);
370 }
371 WorkKind::Trade(t) => {
373 t.haulers.remove(&c);
374 }
375 WorkKind::Road(r) => r.builder = None,
377 WorkKind::Test(_) => {}
378 }
379 }
380
381 fn cancel(&mut self, work: &mut Work) {
384 if let WorkKind::Produce(_) = work.kind {
385 return self.produce_cancel(work);
386 }
387 loop {
388 let next = match &work.kind {
389 WorkKind::Gather(g) => g.workers.first().copied(),
390 WorkKind::Build(b) => b.workers.first().copied(),
391 WorkKind::Clear(cl) => cl
393 .resources
394 .values()
395 .chain(cl.cells.values())
396 .next()
397 .copied(),
398 WorkKind::Pickup(_) => self
400 .piles
401 .get(&work.entity)
402 .filter(|p| p.state == 1)
403 .and_then(|p| p.claimer),
404 WorkKind::Location(l) => l.worker,
406 WorkKind::Fishing(fw) => fw.workers.iter().flatten().next().copied(),
408 WorkKind::PlantArea(_)
410 | WorkKind::Harvest(_)
411 | WorkKind::PlantOrchard(_)
412 | WorkKind::PickFruit(_) => Self::area_workers(work).first().copied(),
413 WorkKind::Herbalist(h)
415 | WorkKind::Forester(h)
416 | WorkKind::Hunt(h)
417 | WorkKind::TendArea(h)
418 | WorkKind::Pasture(h)
419 | WorkKind::ClearStorage(h)
420 | WorkKind::Fire(h) => h.workers.first().copied(),
422 WorkKind::Market(m) => m.plans.keys().next().copied(),
424 WorkKind::Trade(t) => t.haulers.keys().next().copied(),
426 WorkKind::Road(r) => r.builder,
428 WorkKind::Produce(_) | WorkKind::Test(_) => None,
429 };
430 let Some(c) = next else { return };
431 self.clear_citizen(c, Some(work));
432 match &mut work.kind {
434 WorkKind::Gather(g) => {
435 g.workers.remove(&c);
436 }
437 WorkKind::Build(b) => {
438 b.workers.remove(&c);
439 }
440 WorkKind::Clear(cl) => {
441 cl.resources.retain(|_, &mut w| w != c);
442 cl.cells.retain(|_, &mut w| w != c);
443 }
444 WorkKind::Pickup(_) => {
445 if let Some(p) = self.piles.get_mut(&work.entity) {
446 p.claimer = None;
447 p.state = 0;
448 }
449 }
450 WorkKind::Location(l) => l.worker = None,
451 WorkKind::Herbalist(h)
452 | WorkKind::Forester(h)
453 | WorkKind::Hunt(h)
454 | WorkKind::TendArea(h)
455 | WorkKind::Pasture(h)
456 | WorkKind::ClearStorage(h)
457 | WorkKind::Fire(h) => {
458 h.workers.remove(&c);
459 }
460 WorkKind::Fishing(fw) => {
461 for w in fw.workers.iter_mut().filter(|w| **w == Some(c)) {
462 *w = None;
463 }
464 }
465 WorkKind::PlantArea(a)
466 | WorkKind::Harvest(a)
467 | WorkKind::PlantOrchard(a)
468 | WorkKind::PickFruit(a) => {
469 let cells: Vec<i32> = a
470 .claims
471 .iter()
472 .filter(|(_, &w)| w == c)
473 .map(|(&i, _)| i)
474 .collect();
475 for i in cells {
476 a.claims.remove(&i);
477 if let Some(n) = a.need.get_mut(i as usize) {
478 *n = true;
479 }
480 }
481 }
482 WorkKind::Market(m) => {
483 m.plans.remove(&c);
484 }
485 WorkKind::Trade(t) => {
486 t.haulers.remove(&c);
487 }
488 WorkKind::Road(r) => r.builder = None,
489 WorkKind::Produce(_) | WorkKind::Test(_) => {}
490 }
491 }
492 }
493}