| @@ -62,6 +62,7 @@ const DARK_WORK_RATE: u32 = 1; |
| 62 |
62 |
pub const EXPANSION_TILES: usize = 8; |
| 63 |
63 |
pub const MIN_EMPTY_STOCKPILE_TILES: usize = 3; |
| 64 |
64 |
const SEARCH_TILES: usize = 15000; |
|
65 |
+const FORAGE_SEARCH_TILES: usize = 5000; |
| 65 |
66 |
const WANDER_RADIUS: i32 = 8; |
| 66 |
67 |
const IDLE_SECS: Range<f32> = 1.0..4.0; |
| 67 |
68 |
const IDLE_AFTER_ORDER_SECS: f32 = 10.0; |
| @@ -434,8 +435,18 @@ pub fn find_work( |
| 434 |
435 |
from: UVec2, |
| 435 |
436 |
wanted: impl Fn(UVec2, ItemKind) -> bool, |
| 436 |
437 |
) -> Option<Task> { |
|
438 |
+ find_work_within(map, reservations, from, SEARCH_TILES, wanted) |
|
439 |
+} |
|
440 |
+ |
|
441 |
+pub fn find_work_within( |
|
442 |
+ map: &WorldMap, |
|
443 |
+ reservations: &Reservations, |
|
444 |
+ from: UVec2, |
|
445 |
+ max_tiles: usize, |
|
446 |
+ wanted: impl Fn(UVec2, ItemKind) -> bool, |
|
447 |
+) -> Option<Task> { |
| 437 |
448 |
let mut found = None; |
| 438 |
|
- nearest_tile(map, from, SEARCH_TILES, |stand| { |
|
449 |
+ nearest_tile(map, from, max_tiles, |stand| { |
| 439 |
450 |
found = NEIGHBORS.iter().find_map(|&d| { |
| 440 |
451 |
let site = stand.as_ivec2() + d; |
| 441 |
452 |
if site.x < 0 || site.y < 0 { |
| @@ -552,12 +563,11 @@ pub fn find_sowing( |
| 552 |
563 |
reservations: &Reservations, |
| 553 |
564 |
from: UVec2, |
| 554 |
565 |
) -> Option<Task> { |
| 555 |
|
- if !zones.has_farm() { |
| 556 |
|
- return None; |
| 557 |
|
- } |
| 558 |
|
- let site = nearest_tile(map, from, SEARCH_TILES, |p| { |
| 559 |
|
- sowable(map, zones, p) && reservations.is_free(Target::Site(p)) |
| 560 |
|
- })?; |
|
566 |
+ let open: HashSet<UVec2> = zones |
|
567 |
+ .farm_tiles() |
|
568 |
+ .filter(|&p| sowable(map, zones, p) && reservations.is_free(Target::Site(p))) |
|
569 |
+ .collect(); |
|
570 |
+ let site = nearest_of(map, from, SEARCH_TILES, &open)?; |
| 561 |
571 |
Some(Task::Work { |
| 562 |
572 |
site, |
| 563 |
573 |
kind: WorkKind::Sow, |
| @@ -674,6 +684,7 @@ pub struct BuildContext<'a> { |
| 674 |
684 |
pub structures: &'a [(UVec2, StructureKind, u32)], |
| 675 |
685 |
pub planned: &'a [(UVec2, StructureKind)], |
| 676 |
686 |
pub blueprints: &'a Blueprints, |
|
687 |
+ pub occupied: &'a HashSet<UVec2>, |
| 677 |
688 |
} |
| 678 |
689 |
|
| 679 |
690 |
impl BuildContext<'_> { |
| @@ -682,10 +693,8 @@ impl BuildContext<'_> { |
| 682 |
693 |
&& !self.zones.is_stockpile(tile) |
| 683 |
694 |
&& !self.zones.is_farm(tile) |
| 684 |
695 |
&& self.map.plant(tile.as_ivec2()).is_none() |
| 685 |
|
- && !self.structures.iter().any(|(pos, ..)| *pos == tile) |
| 686 |
|
- && !self.planned.iter().any(|(pos, _)| *pos == tile) |
|
696 |
+ && !self.occupied.contains(&tile) |
| 687 |
697 |
&& self.blueprints.get(tile).is_none() |
| 688 |
|
- && !self.items.iter().any(|(_, pos)| pos.0 == tile) |
| 689 |
698 |
&& self.reservations.is_free(Target::Site(tile)) |
| 690 |
699 |
} |
| 691 |
700 |
|
| @@ -983,6 +992,18 @@ fn choose_jobs( |
| 983 |
992 |
plans: (Res<Homes>, Res<Designations>), |
| 984 |
993 |
) { |
| 985 |
994 |
let (homes, designations) = plans; |
|
995 |
+ let mut anyone_ready = false; |
|
996 |
+ for (_, _, path, job, mut idle, _, rest, hunger, ..) in &mut colonists { |
|
997 |
+ let idle_now = job.0.is_none() && path.0.is_empty(); |
|
998 |
+ if idle_now { |
|
999 |
+ idle.0.tick(time.delta()); |
|
1000 |
+ } |
|
1001 |
+ anyone_ready |= |
|
1002 |
+ (idle_now && idle.0.is_finished()) || rest.0 < EXHAUSTED_REST || hunger.0 < STARVING; |
|
1003 |
+ } |
|
1004 |
+ if !anyone_ready { |
|
1005 |
+ return; |
|
1006 |
+ } |
| 986 |
1007 |
let wildlife: Vec<Wildlife> = animals |
| 987 |
1008 |
.iter() |
| 988 |
1009 |
.map(|(e, pos, a, tame)| (e, pos.0, a.kind, tame)) |
| @@ -1057,7 +1078,7 @@ fn choose_jobs( |
| 1057 |
1078 |
job.0 = None; |
| 1058 |
1079 |
path.0.truncate(1); |
| 1059 |
1080 |
} |
| 1060 |
|
- let rested = idle.0.tick(time.delta()).is_finished(); |
|
1081 |
+ let rested = idle.0.is_finished(); |
| 1061 |
1082 |
if job.0.is_some() || !path.0.is_empty() || !(rested || urgent) { |
| 1062 |
1083 |
continue; |
| 1063 |
1084 |
} |
| @@ -1105,6 +1126,12 @@ fn choose_jobs( |
| 1105 |
1126 |
} |
| 1106 |
1127 |
storage.map(|to| Task::Haul { pickup: None, to }) |
| 1107 |
1128 |
} else { |
|
1129 |
+ let occupied: HashSet<UVec2> = structures_list |
|
1130 |
+ .iter() |
|
1131 |
+ .map(|(pos, ..)| *pos) |
|
1132 |
+ .chain(planned.iter().map(|(pos, _)| *pos)) |
|
1133 |
+ .chain(snapshot.iter().map(|(_, pos)| pos.0)) |
|
1134 |
+ .collect(); |
| 1108 |
1135 |
let build = BuildContext { |
| 1109 |
1136 |
map: &map, |
| 1110 |
1137 |
zones: &zones, |
| @@ -1113,6 +1140,7 @@ fn choose_jobs( |
| 1113 |
1140 |
structures: &structures_list, |
| 1114 |
1141 |
planned: &planned, |
| 1115 |
1142 |
blueprints: &blueprints, |
|
1143 |
+ occupied: &occupied, |
| 1116 |
1144 |
}; |
| 1117 |
1145 |
let cooking = || { |
| 1118 |
1146 |
(wanted(ItemKind::Meal) && raw_food_source(&build, tile.0).is_some()) |
| @@ -1141,7 +1169,14 @@ fn choose_jobs( |
| 1141 |
1169 |
find_butchering(&map, &reservations, &snapshot, tile.0) |
| 1142 |
1170 |
}), |
| 1143 |
1171 |
(WorkType::Food, &|| { |
| 1144 |
|
- find_work(&map, &reservations, tile.0, |_, k| k.is_food() && wanted(k)) |
|
1172 |
+ ItemKind::ALL |
|
1173 |
+ .iter() |
|
1174 |
+ .any(|&k| k.is_food() && wanted(k)) |
|
1175 |
+ .then(|| { |
|
1176 |
+ let food = |_, k: ItemKind| k.is_food() && wanted(k); |
|
1177 |
+ find_work_within(&map, &reservations, tile.0, FORAGE_SEARCH_TILES, food) |
|
1178 |
+ }) |
|
1179 |
+ .flatten() |
| 1145 |
1180 |
}), |
| 1146 |
1181 |
(WorkType::Gather, &designated), |
| 1147 |
1182 |
(WorkType::Food, &|| { |
| @@ -1152,7 +1187,11 @@ fn choose_jobs( |
| 1152 |
1187 |
(WorkType::Build, &|| find_bed_site(&build, adults, tile.0)), |
| 1153 |
1188 |
(WorkType::Build, &|| find_blueprint_work(&build, tile.0)), |
| 1154 |
1189 |
(WorkType::Gather, &|| { |
| 1155 |
|
- find_work(&map, &reservations, tile.0, |_, k| wanted(k)) |
|
1190 |
+ ItemKind::ALL |
|
1191 |
+ .iter() |
|
1192 |
+ .any(|&k| wanted(k)) |
|
1193 |
+ .then(|| find_work(&map, &reservations, tile.0, |_, k| wanted(k))) |
|
1194 |
+ .flatten() |
| 1156 |
1195 |
}), |
| 1157 |
1196 |
(WorkType::Food, &|| { |
| 1158 |
1197 |
wanted(ItemKind::Meat) |