<commit_before>use rand::StdRng;
use rand::Rng;
use rand::SeedableRng;
use std::iter;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::BTreeMap;
use super::terrain::TerrainType;
use super::location::Location;
use super::mapgen;
use super::{AreaSpec};
use super::components::{Category};
use super::spawn::Spawn;

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values.

#[derive(Copy, Clone, RustcDecodable, RustcEncodable)]
pub struct AreaSeed {
    pub rng_seed: u32,
    pub spec: AreaSpec,
}

#[derive(Clone)]
/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    /// Random number generator seed. Must uniquely define the Area contents.
    pub seed: AreaSeed,
    /// Stored terrain.
    pub terrain: BTreeMap<Location, TerrainType>,
    /// Valid slots to spawn things in, basically open floor and connected to
    /// areas the player can reach. (Does not handle stuff like monsters that
    /// spawn in water for now.)
    _open_slots: Vec<Location>,
    /// Where the player should enter the area.
    player_entrance: Location,
    /// Non-player entities to create when first initializing the map.
    spawns: Vec<(Spawn, Location)>,
}<commit_msg>Note about HashMap nondeterminism in mapgen comment<commit_after>use rand::StdRng;
use rand::Rng;
use rand::SeedableRng;
use std::iter;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::BTreeMap;
use super::terrain::TerrainType;
use super::location::Location;
use super::mapgen;
use super::{AreaSpec};
use super::components::{Category};
use super::spawn::Spawn;

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values. Relying on the iteration order of collections::HashMap has
// introduced at least one nondeterminism bug to map generation.

#[derive(Copy, Clone, RustcDecodable, RustcEncodable)]
pub struct AreaSeed {
    pub rng_seed: u32,
    pub spec: AreaSpec,
}

#[derive(Clone)]
/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    /// Random number generator seed. Must uniquely define the Area contents.
    pub seed: AreaSeed,
    /// Stored terrain.
    pub terrain: BTreeMap<Location, TerrainType>,
    /// Valid slots to spawn things in, basically open floor and connected to
    /// areas the player can reach. (Does not handle stuff like monsters that
    /// spawn in water for now.)
    _open_slots: Vec<Location>,
    /// Where the player should enter the area.
    player_entrance: Location,
    /// Non-player entities to create when first initializing the map.
    spawns: Vec<(Spawn, Location)>,
}
{'fraction_non_alphanumeric': 0.09013230429988975, 'fraction_numerical': 0.0011025358324145535, 'mean_word_length': 4.125706214689266, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1602254', 'n_tokens_mistral': 1000, 'n_tokens_neox': 993, 'n_words': 439}