Better starting site choices

This commit is contained in:
Joshua Barretto 2023-04-13 18:32:21 +01:00
parent 8249675a72
commit a835ce7e26
5 changed files with 47 additions and 8 deletions

View File

@ -218,6 +218,7 @@ pub struct Client {
player_list: HashMap<Uid, PlayerInfo>,
character_list: CharacterList,
sites: HashMap<SiteId, SiteInfoRich>,
possible_starting_sites: Vec<SiteId>,
pois: Vec<PoiInfo>,
pub chat_mode: ChatMode,
recipe_book: RecipeBook,
@ -654,6 +655,7 @@ impl Client {
Grid::from_raw(map_size.map(|e| e as i32), lod_horizon),
(world_map_layers, map_size, map_bounds),
world_map.sites,
world_map.possible_starting_sites,
world_map.pois,
recipe_book,
component_recipe_book,
@ -670,6 +672,7 @@ impl Client {
lod_horizon,
world_map,
sites,
possible_starting_sites,
pois,
recipe_book,
component_recipe_book,
@ -709,6 +712,7 @@ impl Client {
})
})
.collect(),
possible_starting_sites,
pois,
recipe_book,
component_recipe_book,
@ -1348,6 +1352,8 @@ impl Client {
/// Unstable, likely to be removed in a future release
pub fn sites(&self) -> &HashMap<SiteId, SiteInfoRich> { &self.sites }
pub fn possible_starting_sites(&self) -> &[SiteId] { &self.possible_starting_sites }
/// Unstable, likely to be removed in a future release
pub fn pois(&self) -> &Vec<PoiInfo> { &self.pois }

View File

@ -121,6 +121,7 @@ pub struct WorldMapMsg {
/// (256 possible angles).
pub horizons: [(Vec<u8>, Vec<u8>); 2],
pub sites: Vec<SiteInfo>,
pub possible_starting_sites: Vec<SiteId>,
pub pois: Vec<PoiInfo>,
/// Default chunk (representing the ocean outside the map bounds). Sea
/// level (used to provide a base altitude) is the lower bound of this

View File

@ -29,7 +29,7 @@ use common::{
vol::RectVolSize,
LoadoutBuilder,
};
use common_net::msg::world_msg::{SiteId, SiteInfo, SiteKind};
use common_net::msg::world_msg::{SiteId, SiteInfo};
use i18n::{Localization, LocalizationHandle};
//ImageFrame, Tooltip,
use crate::settings::Settings;
@ -1978,10 +1978,10 @@ impl CharSelectionUi {
Arc::clone(client.world_data().topo_map_image()),
Some(default_water_color()),
)),
client.sites()
.values()
// TODO: Enforce this server-side and add some way to customise it?
.filter(|info| matches!(&info.site.kind, SiteKind::Town /*| SiteKind::Castle | SiteKind::Bridge*/))
client
.possible_starting_sites()
.iter()
.filter_map(|site_id| client.sites().get(site_id))
.map(|info| info.site.clone())
.collect(),
client.world_data().chunk_size().as_(),

View File

@ -6,7 +6,7 @@
)]
#![allow(clippy::branches_sharing_code)] // TODO: evaluate
#![deny(clippy::clone_on_ref_ptr)]
#![feature(option_zip)]
#![feature(option_zip, let_chains)]
mod all;
mod block;
@ -205,6 +205,37 @@ impl World {
wpos,
}))
.collect(),
possible_starting_sites: {
const STARTING_SITE_COUNT: usize = 4;
let mut candidates = self
.civs()
.sites
.iter()
.filter_map(|(_, civ_site)| Some((civ_site, civ_site.site_tmp?)))
.map(|(civ_site, site_id)| {
// Score the site according to how suitable it is to be a starting site
let mut score = 0.0;
if let SiteKind::Refactor(site2) = &index.sites[site_id].kind {
// Strongly prefer towns
score += 1000.0;
// Prefer sites of a medium size
score += 2.0 / (1.0 + (site2.plots().len() as f32 - 20.0).abs() / 10.0);
};
// Prefer sites in hospitable climates
if let Some(chunk) = self.sim().get(civ_site.center) {
score += 1.0 / (1.0 + chunk.temp.abs());
score += 1.0 / (1.0 + (chunk.humidity - CONFIG.forest_hum).abs() * 2.0);
}
// Prefer sites that are close to the centre of the world
score += 4.0 / (1.0 + civ_site.center.map2(self.sim().get_size(), |e, sz| (e as f32 / sz as f32 - 0.5).abs() * 2.0).reduce_partial_max());
(site_id.id(), score)
})
.collect::<Vec<_>>();
candidates.sort_by_key(|(_, score)| -(*score * 1000.0) as i32);
candidates.into_iter().map(|(site_id, _)| site_id).take(STARTING_SITE_COUNT).collect()
},
..self.sim.get_map(index, self.sim().calendar.as_ref())
}
})

View File

@ -1683,6 +1683,7 @@ impl WorldSim {
horizons,
sites: Vec::new(), // Will be substituted later
pois: Vec::new(), // Will be substituted later
possible_starting_sites: Vec::new(), // Will be substituted later
default_chunk: Arc::new(self.generate_oob_chunk()),
}
}