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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
)] )]
#![allow(clippy::branches_sharing_code)] // TODO: evaluate #![allow(clippy::branches_sharing_code)] // TODO: evaluate
#![deny(clippy::clone_on_ref_ptr)] #![deny(clippy::clone_on_ref_ptr)]
#![feature(option_zip)] #![feature(option_zip, let_chains)]
mod all; mod all;
mod block; mod block;
@ -205,6 +205,37 @@ impl World {
wpos, wpos,
})) }))
.collect(), .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()) ..self.sim.get_map(index, self.sim().calendar.as_ref())
} }
}) })

View File

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