genworldvoronoi

package module
v0.0.0-...-d0756c4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 5, 2024 License: Apache-2.0 Imports: 37 Imported by: 0

README

genworldvoronoi: Graph based planetary map generator

It simulates (somewhat) global winds and attempts to calculate precipitation and temperature for more intricate simulations in the future. It features SVG, PNG, and Wavefront OBJ output.

This is based on https://www.redblobgames.com/x/1843-planet-generation/ and a port of https://github.com/redblobgames/1843-planet-generation to Go.

I draw further inspiration from various other projects such as https://github.com/weigert/SimpleHydrology and https://github.com/mewo2/terrain

... if you haven't noticed yet, this is a placeholder for when I feel less lazy and add more information :D

Dev notes

This thing needs a use, and I think the major drawback right now is the time that it takes to generate a reasonably complex planet with enough detail to be interesting. So here are tne following important points that need to be addressed:

  • Generation speed
    • Use concurrency where sensible
    • Introduce a cache for fitness functions
  • Export / import of generated data
    • Separate generation steps into
      • Geology, Climate
      • Biology, Species, Survivability
      • Civilization, Cities, Empires
    • Binary format for writing to / reading from disk
  • Simulation
    • Seasons, Weather, Disasters
    • Biology, Species, Migrations
    • Population Growth, Migrations
    • Wars, Diplomacy
    • Founding, Development, Abandonment, Fall of Cities, Empires, Religions
    • Written History, Legends

TODO

  • Use cached temperature instead of getRegTemperature every single time
  • Climate
  • Elevation
    • Move away from linear interpolation
    • Add improved noise
  • Winds
    • Push temperature around [DONE]
    • Push dry air around, not just humid air
    • Re-evaluate rainfall and moisture distribution
  • Civilization
    • Industry and trade
      • Introduce industry
      • Introduce production / harvesting of goods
      • Improve trade routes
    • Cities
      • Better city fitness functions
      • Separate world generation better from everything else
      • Assign goods and resources to cities (for trade)
    • Empires
      • Introduce empires with capitals [DONE]
      • Provide simpler means to query information on an empire
    • Cultures
      • Add fitness function for "natural" population density estimates
  • Resources
    • Improve resource distribution
      • Fitness functions
      • Amount / quality / discoverability?
    • Add more resource types
  • Species
    • Allow for overlapping populations
    • Allow for species migration

Here some old pictures what it does...

SVG export with rivers, capital city placement and stuff.

alt text

Leaflet server (and sad flavor text).

alt text

Poor man's relief map.

alt text

Slightly wealthier man's relief map.

alt text

Does political maps.

alt text

Simulates climate (-ish)

alt text

Simulates seasons (-ish)

alt text

Exports to Wavefront OBJ

alt text

Webglearth sample

alt text

Cesium sample

alt text

Documentation

Overview

Package genworldvoronoi is a port of redblobgames' amazing planet generator. See: https://www.redblobgames.com/x/1843-planet-generation And: https://github.com/redblobgames/1843-planet-generation

Index

Constants

View Source
const (
	SkillSurvival  = "survival"
	SkillGeneric   = "generic"
	SkillRiverNav  = "river navigation"
	SkillSeafaring = "seafaring"
	SkillFishery   = "fishery"
	SkillHunting   = "hunting"
	SkillNomadic   = "nomadic"
	SkillClimbing  = "climbing"
)
View Source
const (
	// Expansion modes.
	ReligionExpGlobal  = genreligion.ReligionExpGlobal
	ReligionExpState   = genreligion.ReligionExpState
	ReligionExpCulture = genreligion.ReligionExpCulture
)
View Source
const (
	ObjectTypeCity = iota
	ObjectTypeCityState
	ObjectTypeEmpire
	ObjectTypeCulture
	ObjectTypeReligion
	ObjectTypeRegion
	ObjectTypeMountain
	ObjectTypeRiver
	ObjectTypeLake
	ObjectTypeSea
	ObjectTypeVolcano
	ObjectTypePerson
	ObjectTypeTribe
)
View Source
const (
	DisplayModeDefault          = 0
	DisplayModeOceanPressure    = 1
	DisplayModeMoisture         = 2
	DisplayModeRainfall         = 3
	DisplayModeFlux             = 4
	DisplayModeCompression      = 5
	DisplayModeEarthquake       = 6
	DisplayModeVolcano          = 7
	DisplayModeRockSlide        = 8
	DisplayModeFlood            = 9
	DisplayModeErosion          = 10
	DisplayModeErosion2         = 11
	DisplayModeSteepness        = 12
	DisplayModeSlope            = 13
	DisplayModeCityStates       = 14
	DisplayModeEmpires          = 15
	DisplayModeCultures         = 16
	DisplayModeReligions        = 17
	DisplayModeSpecies          = 18
	DisplayModePlates           = 19
	DisplayModeElevation        = 20
	DisplayModeAirTemperature   = 21
	DisplayModeOceanTemperature = 22
	DisplayModeInsolation       = 23
	DisplayModePopulation       = 24
	DisplayModeSuitability      = 25
	DisplayModeSoilExhaustion   = 26
	DisplayModeTribes           = 27
)

Display modes for tile rendering.

Variables

View Source
var (
	GenderFemale = geneticshuman.GenderFemale
	GenderMale   = geneticshuman.GenderMale
)
View Source
var (
	SSkillHunting = &Skill{
		Name:     "Hunting",
		MinScore: 0.4,
		Chance:   0.4,
		Biomes:   huntingBiomes,
		Requires: []*Skill{SSkillGathering},
	}
	SSkillGathering = &Skill{
		Name:     "Gathering",
		MinScore: 0.2,
		Chance:   0.4,
		Biomes: []int{
			genbiome.WhittakerModBiomeTemperateGrassland,
			genbiome.WhittakerModBiomeTropicalRainforest,
			genbiome.WhittakerModBiomeTemperateRainforest,
			genbiome.WhittakerModBiomeTemperateSeasonalForest,
			genbiome.WhittakerModBiomeWoodlandShrubland,
			genbiome.WhittakerModBiomeTemperateGrassland,
			genbiome.WhittakerModBiomeBorealForestTaiga,
			genbiome.WhittakerModBiomeTundra,
			genbiome.WhittakerModBiomeWetlands,
			genbiome.WhittakerModBiomeSnow,
		},
	}
	SSkillWoodworking = &Skill{
		Name:     "Woodworking",
		MinScore: 0.5,
		Chance:   0.4,
		Wood:     true,
		Requires: []*Skill{SSkillGathering},
	}
	SSkillStoneWorking = &Skill{
		Name:     "Stone Working",
		MinScore: 0.5,
		Chance:   0.4,
		Stone:    true,
		Requires: []*Skill{SSkillGathering},
	}
	SSkillMetalWorking = &Skill{
		Name:     "Metal Working",
		MinScore: 0.5,
		Chance:   0.4,
		Metal:    true,
		Requires: []*Skill{SSkillStoneWorking},
	}
	SSkillGemWorking = &Skill{
		Name:     "Gem Working",
		MinScore: 0.5,
		Chance:   0.4,
		Gems:     true,
		Requires: []*Skill{SSkillStoneWorking},
	}
	SSkillFishing = &Skill{
		Name:           "Fishing",
		MinScore:       0.9,
		Chance:         0.1,
		Biomes:         nil,
		WaterProximity: true,
		Requires:       []*Skill{SSkillGathering},
	}
	SSkillFarming = &Skill{
		Name:     "Farming",
		MinScore: 0.9,
		Chance:   0.4,
		Biomes: []int{
			genbiome.WhittakerModBiomeTemperateGrassland,
			genbiome.WhittakerModBiomeWetlands,
		},
		Requires: []*Skill{SSkillGathering},
	}
	SSkillHerding = &Skill{
		Name:     "Herding",
		MinScore: 0.5,
		Chance:   0.4,
		Biomes: []int{
			genbiome.WhittakerModBiomeTemperateGrassland,
			genbiome.WhittakerModBiomeTundra,
			genbiome.WhittakerModBiomeSubtropicalDesert,
			genbiome.WhittakerModBiomeSavannah,
			genbiome.WhittakerModBiomeColdDesert,
			genbiome.WhittakerModBiomeSnow,
		},
		Requires: []*Skill{SSkillHunting},
	}
	SSkillSettling = &Skill{
		Name:     "Settling",
		MinScore: 0.9,
		Chance:   0.1,
		Requires: []*Skill{SSkillFarming, SSkillHerding},
		Effect: func(t *Tribe) {
			if t.Type < TribeTypeSettling {
				t.Type = TribeTypeSettling
			}
			log.Printf("Tribe %d has developed a taste for settling down.", t.ID)
		},
	}
	SSkillSettlingWetlands = &Skill{
		Name:     "Settling (Wetlands)",
		MinScore: 0.9,
		Chance:   0.1,
		Biomes: []int{
			genbiome.WhittakerModBiomeWetlands,
		},
		Requires: []*Skill{SSkillFarming, SSkillGathering, SSkillFishing},
		Effect: func(t *Tribe) {
			if t.Type < TribeTypeSettling {
				t.Type = TribeTypeSettling
			}
			log.Printf("Tribe %d has developed a taste for settling down in the wetlands.", t.ID)
		},
	}
	SSkillSettlingHighland = &Skill{
		Name:              "Settling (Highland)",
		MinScore:          0.9,
		Chance:            0.1,
		MountainProximity: true,
		Biomes: []int{
			genbiome.WhittakerModBiomeColdDesert,
			genbiome.WhittakerModBiomeSnow,
		},
		Requires: []*Skill{SSkillGathering, SSkillHerding},
		Effect: func(t *Tribe) {
			if t.Type < TribeTypeSettling {
				t.Type = TribeTypeSettling
			}
			log.Printf("Tribe %d has developed a taste for settling down in the highlands.", t.ID)
		},
	}
	SSkillBoating = &Skill{
		Name:           "Boating",
		MinScore:       0.9,
		Chance:         0.1,
		WaterProximity: true,
		Requires:       []*Skill{SSkillWoodworking, SSkillFishing},
		Effect: func(t *Tribe) {

		},
	}
	SSkillSeaFaring = &Skill{
		Name:           "Sea Faring",
		MinScore:       0.9,
		Chance:         0.1,
		OceanProximity: true,
		Requires:       []*Skill{SSkillBoating},
		Effect: func(t *Tribe) {

		},
	}
)

Skills that can be developed. TODO: - Skills might depend on other skills. - There might be a chance to lose a skill if the tribe is not using it.

Possible skills: - Hunting (requires grassland, forest, etc.) - Gathering (requires grassland, forest, etc.) - Fishing (requires water proximity) - Farming (requires grassland) - Herding (requires grassland) - Quarrying (requires mountains) - Mining (requires mountains) - Smithing (requires mining) - Weaving (requires plants) - Pottery (requires water proximity) - Carpentry

View Source
var GenLanguage = genlanguage.GenLanguage
View Source
var GetAdjective = genlanguage.GetAdjective

GetAdjective get adjective form from noun

View Source
var GetNounPlural = genlanguage.GetNounPlural

GetNounPlural returns the plural form of a noun. This takes in account "witch" and "fish" which are irregular.

IsVowel returns true if the given rune is a vowel.

TrimVowels remove vowels from the end of the string.

Functions

func P

func P(probability float64) bool

probability shorthand

Types

type City

type City struct {
	ID                    int                   // Region where the city is located
	Name                  string                // Name of the city
	Type                  TownType              // Type of city
	Score                 float64               // Score of the fitness function
	Population            int                   // Population of the city
	MaxPopulation         int                   // Maximum population of the city
	Culture               *Culture              // Culture of the city region
	Language              *genlanguage.Language // Language of the city
	Religion              *Religion             // Religion originating from the city
	Founded               int64                 // Year when the city was founded
	PotentialEconomic     float64               // Economic potential of the city (DYNAMIC)
	PotentialTrade        float64               // Trade value of the city (DYNAMIC)
	PotentialResources    float64               // Resources value of the city (PARTLY DYNAMIC)
	PotentialAgricultural float64               // Agriculture value of the city (STATIC)
	Attractiveness        float64               // Attractiveness of the city (STATIC)
	TradePartners         []int                 // IDs of cities within trade range
	People                []*Person             // People living in the city
}

City represents a city in the world.

func (*City) MaxPopulationLimit

func (c *City) MaxPopulationLimit() int

MaxPopulationLimit returns the maximum population sustainable by the city.

func (*City) PopulationGrowthRate

func (c *City) PopulationGrowthRate() float64

PopulationGrowthRate returns the population growth rate per year.

func (*City) Ref

func (c *City) Ref() ObjectReference

Ref returns the object reference of the city.

func (*City) String

func (c *City) String() string

String returns a string representation of the city.

type CityState

type CityState struct {
	ID      int      // Region where the city state originates
	Capital *City    // Capital city
	Culture *Culture // Culture of the city state
	Cities  []*City  // Cities within the city state
	Founded int64    // Year when the city state was founded

	// TODO: DO NOT CACHE THIS!
	Regions []int
	*geo.Stats
}

CityState represents a territory governed by a single city.

func (*CityState) Log

func (c *CityState) Log()

func (*CityState) String

func (c *CityState) String() string

type Civ

type Civ struct {
	*CivConfig
	*geo.Geo
	*History

	People            []*Person    // People in the world
	Empires           []*Empire    // (political) Empires
	RegionToEmpire    []int        // (political) Point / region mapping to territory / empire
	CityStates        []*CityState // (political) City states
	RegionToCityState []int        // (political) Point / region mapping to city / city state
	Cities            []*City      // (political) City seed points / regions
	RegionToCulture   []int        // (cultural) Point / region mapping to culture
	Cultures          []*Culture   // (cultural) Culture seed points / regions
	RegionToReligion  []int        // (cultural) Point / region mapping to religion
	Religions         []*Religion  // (cultural) Religion seed points / regions
	Settled           []int64      // (cultural) Time of settlement per region
	// SettledBySpecies []int // (cultural) Which species settled the region first
	NameGen     *genlandmarknames.NameGenerators
	TradeRoutes [][]int

	// Temp population per region.
	Population     []int
	SoilExhaustion []float64
	Suitability    []float64
	Tribes         []*Tribe
	TribeCount     int // Running count of tribes (for ID generation)
	// contains filtered or unexported fields
}

func NewCiv

func NewCiv(g *geo.Geo, cfg *CivConfig) *Civ

func (*Civ) AddCultureAt

func (m *Civ) AddCultureAt(r int, c *Culture, grow bool) *Culture

AddCultureAt adds a culture at the given region.

func (*Civ) CalcCityScore

func (m *Civ) CalcCityScore(sf func(int) float64, distSeedFunc func() []int) []float64

CalcCityScore calculates the fitness value for settlements for all regions.

'sf': Fitness function for scoring a region. 'distSeedFunc': Returns a number of regions from which we maximize the distance.

func (*Civ) CalcCityScoreWithDistanceField

func (m *Civ) CalcCityScoreWithDistanceField(sf func(int) float64, regDistanceC []float64) []float64

func (*Civ) ExpandCityStates

func (m *Civ) ExpandCityStates()

ExpandCityStates expands the city states on the map based on their culture, terrain preference, and other factors.

func (*Civ) ExpandCultures

func (m *Civ) ExpandCultures()

ExpandCultures expands the cultures on the map based on their expansionism, terrain preference, and distance to other cultures.

func (*Civ) ExpandReligions

func (m *Civ) ExpandReligions()

func (*Civ) GenerateCivilization

func (m *Civ) GenerateCivilization()

func (*Civ) GenerateTimeOfSettlement

func (m *Civ) GenerateTimeOfSettlement()

func (*Civ) GetCity

func (m *Civ) GetCity(r int) *City

GetCity returns the city at the given region / with the given ID.

func (*Civ) GetCityState

func (m *Civ) GetCityState(id int) *CityState

func (*Civ) GetCityStates

func (m *Civ) GetCityStates() []*CityState

func (*Civ) GetCulture

func (m *Civ) GetCulture(r int) *Culture

GetCulture returns the culture of the given region (if any).

func (*Civ) GetEmpire

func (m *Civ) GetEmpire(id int) *Empire

func (*Civ) GetEmpires

func (m *Civ) GetEmpires() []*Empire

func (*Civ) GetReligion

func (m *Civ) GetReligion(r int) *Religion

GetReligion returns the religion of the given region (if any).

func (*Civ) GetTradeRoutes

func (m *Civ) GetTradeRoutes() ([][]int, [][]int)

func (*Civ) InitSim

func (m *Civ) InitSim()

func (*Civ) InitSimSettling

func (m *Civ) InitSimSettling()

func (*Civ) InitSimTribes

func (m *Civ) InitSimTribes()

func (*Civ) LogPopulationStats

func (m *Civ) LogPopulationStats(people []*Person)

func (*Civ) LogTribes

func (m *Civ) LogTribes()

func (*Civ) PlaceCity

func (m *Civ) PlaceCity(cType TownType, scoreFunc func(int) float64, distSeedFunc func() []int) *City

PlaceCity places another city at the region with the highest fitness score.

func (*Civ) PlaceCityStateAt

func (m *Civ) PlaceCityStateAt(r int, c *City) *CityState

func (*Civ) PlaceCulture

func (m *Civ) PlaceCulture(regCultureFunc func(int) CultureType, scoreFunc func(int) float64, distSeedFunc func() []int, lang *genlanguage.Language) *Culture

PlaceCulture places another culture on the map at the region with the highest fitness score.

func (*Civ) PlaceCultureAt

func (m *Civ) PlaceCultureAt(r int, grow bool, lang *genlanguage.Language) *Culture

PlaceCultureAt places a culture at the given region. TODO: Allow specifying the culture type?

func (*Civ) PlaceNCities

func (m *Civ) PlaceNCities(n int, cType TownType)

PlaceNCities places n cities with the highest fitness scores.

func (*Civ) PlaceNCityStates

func (m *Civ) PlaceNCityStates(n int)

func (*Civ) PlaceNCultures

func (m *Civ) PlaceNCultures(n int)

PlaceNCultures places n cultures on the map. This code is based on: https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/modules/cultures-generator.js

func (*Civ) PlaceNEmpires

func (m *Civ) PlaceNEmpires(n int)

func (*Civ) PlaceNFolkReligions

func (m *Civ) PlaceNFolkReligions(n int) []*Religion

PlaceNFolkReligions generates folk religions.

func (*Civ) PlaceNOrganizedReligions

func (m *Civ) PlaceNOrganizedReligions(n int) []*Religion

PlaceNOrganizedReligions generates organized religions.

func (*Civ) Tick

func (m *Civ) Tick()

func (*Civ) TickCity

func (m *Civ) TickCity(c *City, gDisFunc func(int) geo.GeoDisasterChance, cf func(int) *Culture)

func (*Civ) TickN

func (m *Civ) TickN(n int)

func (*Civ) TickSim

func (m *Civ) TickSim()

type CivConfig

type CivConfig struct {
	NumCultures              int  // (Min) Number of generated cultures
	NumOrganizedReligions    int  // (Min) Number of generated religions
	NumEmpires               int  // Number of generated territories
	NumCities                int  // Number of generated cities (regions)
	NumCityStates            int  // Number of generated city states
	NumMiningTowns           int  // Number of generated mining towns
	NumMiningGemsTowns       int  // Number of generated (gem) mining towns
	NumQuarryTowns           int  // Number of generated quarry towns
	NumFarmingTowns          int  // Number of generated farming towns
	NumTradingTowns          int  // Number of generated trading towns
	NumDesertOasis           int  // Number of generated desert oases
	EnableCityAging          bool // Enable city aging
	EnableOrganizedReligions bool // Enable organized religion generation

	// In case of disaster, overpopulation, etc. a percentage of the population might migrate to a new location.
	MigrationOverpopulationExcessPopulationFactor float64 // Factor of excess population to migrate in case of overpopulation.
	MigrationOverpopulationMinPopulationFactor    float64 // Minimum factor of total population to migrate in case of overpopulation.
	MigrationToNClosestCities                     int     // Number of the N closest cities to migrate to (in case of disaster)
	MigrationToNewSettlementWithinNRegions        int     // Depth of graph traversal for finding a suitable new settlement location.
	MigrationFatalityChance                       float64 // Chance of death during migration per region traversed.
}

CivConfig is a struct that holds all configuration options for civilization generation.

func NewCivConfig

func NewCivConfig() *CivConfig

NewCivConfig returns a new config for civilization generation.

type CivStats

type CivStats struct {
	Cultures   map[*Culture]int   // Number of regions per culture.
	Religions  map[*Religion]int  // Number of regions per religion.
	CityStates map[*CityState]int // Number of regions per city state.
	Empires    map[*Empire]int    // Number of regions per empire.
}

CivStats contains statistics about civilization related aspects present given a list of regions. This will allow us for example to determine if the primary culture or religion of the empire is different from the capital, which might be destabilizing, etc.

func (*CivStats) Log

func (s *CivStats) Log()

type ClampedVal

type ClampedVal float64

func (*ClampedVal) Add

func (c *ClampedVal) Add(v float64)

type Config

type Config struct {
	*geo.GeoConfig
	*CivConfig
	*bio.BioConfig
}

Config is a struct that holds all configuration options for the map generation.

func NewConfig

func NewConfig() *Config

NewConfig returns a new Config with default values.

type Culture

type Culture struct {
	ID           int         // Region where the culture originates
	Name         string      // Name of the culture
	Type         CultureType // Type of the culture
	Expansionism float64     // Expansionism of the culture
	Martialism   float64     // Martial skills of the culture
	Spirituality float64     // Spirituality of the culture (religion, superstition, etc.)
	// Sophistication float64
	// Extremism      float64 ?
	// Openness       float64 ?
	// Parent    *Culture
	// Children  []*Culture
	// Extinct   bool
	Language *genlanguage.Language // Language of the culture
	Religion *Religion             // Religion of the culture

	// TODO: DO NOT CACHE THIS!
	Regions []int
	*geo.Stats
}

Culture represents a culture.

Also see: https://ck3.paradoxwikis.com/Culture

TODO:

VALUES

The type of culture will also influence their values. For example, a nomadic or a hunting culture will have higher regart for martial skills and lower regard for sophistication.

I would propose to have a point pool for these attributes and then randomly assign them to the various skills with a certain distribution based on the culture type.

CRAFTS AND SKILLS

The culture will also have a set of crafts, arts, and skills that they are good at. This will be based on their values and the environment they live in.

For example, a nomadic culture will be good at hunting and tracking. They might be exceptional at crafting leather wares (like saddles), and bows.

A river culture will have a ready supply of clay, and will be good at pottery, but not at crafin leather wares like saddles.

A mountain culture will be good at mining, prospecting, and stone carving. If they mine precious metals, they will be good at jewelry making.

A naval culture will be good at ship building, and sailing. Since they might have sea shells as a ready supply, they might be good at jewelry making.

ARTS

Arts will be based on the environment and the values of the culture. For example, a river culture might focus on water and rivers, as well as the flora and fauna related to rivers.

A mountain culture might use iconography to represent the harshness of the mountains, and the gifts of the mines.

func (*Culture) Fork

func (c *Culture) Fork(newID int) *Culture

func (*Culture) Log

func (c *Culture) Log()

func (*Culture) SetNewType

func (c *Culture) SetNewType(t CultureType)

type CultureType

type CultureType int
const (
	CultureTypeWildland CultureType = iota
	CultureTypeGeneric
	CultureTypeRiver
	CultureTypeLake
	CultureTypeNaval
	CultureTypeNomadic
	CultureTypeHunting
	CultureTypeHighland
)

Culture types.

func (CultureType) BiomeCost

func (t CultureType) BiomeCost(biome int) float64

BiomeCost returns the cost for traversion / expanding into a given biome.

func (CultureType) CellTypeCost

func (t CultureType) CellTypeCost(cellType int) float64

CellTypeCost returns the cost of crossing / navigating a given cell type for a given culture.

func (CultureType) Expansionism

func (t CultureType) Expansionism() float64

Expansionism returns the expansionism of a given culture type.

func (CultureType) Martialism

func (t CultureType) Martialism() float64

Martialism returns the martialism of a given culture type.

func (CultureType) Spirituality

func (t CultureType) Spirituality() float64

Spirituality returns the spirituality of a given culture type. TODO: Replace this with a more meaningful value.

func (CultureType) String

func (c CultureType) String() string

String returns the string representation of a given culture type.

type EdgeIndices

type EdgeIndices struct {
	WestVertexCount  uint32
	WestIndices      []uint32 // [westVertexCount]uint32
	SouthVertexCount uint32
	SouthIndices     []uint32 // [southVertexCount]uint32
	EastVertexCount  uint32
	EastIndices      []uint32 // [eastVertexCount]uint32
	NorthVertexCount uint32
	NorthIndices     []uint32 // [northVertexCount]uint32
}

Following the triangle indices is four more lists of indices: Depending on the number of vertices, the tile uses either EdgeIndices16 or EdgeIndices32.

func (*EdgeIndices) Write

func (ei *EdgeIndices) Write(w io.Writer, vertexCount uint32) error

type Empire

type Empire struct {
	ID       int                   // Region where the empire originates (capital)
	Name     string                // Name of the empire
	Emperor  string                // Name of the ruler
	Capital  *City                 // Capital city
	Cities   []*City               // Cities within the territory
	Culture  *Culture              // Primary culture of the empire
	Language *genlanguage.Language // Primary language of the empire

	// TODO: DO NOT CACHE THIS!
	Regions []int // Regions that are part of the empire
	*geo.Stats
}

Empire contains information about a territory with the given ID. TODO: Maybe drop the regions since we can get that info relatively cheaply.

func (*Empire) Log

func (e *Empire) Log()

func (*Empire) String

func (e *Empire) String() string

type Event

type Event struct {
	Year int64           // TODO: Allow different types of time.
	Type string          // Maybe use an enum?
	Msg  string          // Message that describes the event.
	ID   ObjectReference // Reference to the object that the event is about.

}

func (*Event) String

func (e *Event) String() string

type Faction

type Faction struct {
	Name string // Name of the faction.
	*Leadership
}

Faction represents a faction within a tribe or a city state.

func (*Faction) String

func (f *Faction) String() string

String returns a string representation of the faction.

type HackyBiome

type HackyBiome int

func (HackyBiome) String

func (b HackyBiome) String() string

type History

type History struct {
	*geo.Calendar
	Events []*Event
}

func NewHistory

func NewHistory(c *geo.Calendar) *History

func (*History) AddEvent

func (h *History) AddEvent(t string, msg string, id ObjectReference) *Event

AddEvent adds an event to the history and returns a pointer to the event.

func (*History) GetEvents

func (h *History) GetEvents(id int, t byte) []*Event

type IndexData

type IndexData struct {
	TriangleCount uint32

	// Either Indices16 or Indices32 is used, depending on the number of vertices.
	// Indices16 []uint16 // [triangleCount * 3]uint16
	Indices []uint32 // [triangleCount * 3]uint32
}

Immediately following the vertex data is the index data. Indices specify how the vertices are linked together into triangles. If tile has more than 65536 vertices, the tile uses the IndexData32 structure to encode indices. Otherwise, it uses the IndexData16 structure.

To enforce proper byte alignment, padding is added before the IndexData to ensure 2 byte alignment for IndexData16 and 4 byte alignment for IndexData32.

Indices are encoded using the high water mark encoding from webgl-loader. Each triplet of indices specifies one triangle to be rendered, in counter-clockwise winding order.

func (*IndexData) Write

func (id *IndexData) Write(w io.Writer, vertexCount uint32) error

type Last100

type Last100[T ~int] struct {
	// contains filtered or unexported fields
}

Last100 is a counter that keeps track of the last 100 values.

func (*Last100[T]) Add

func (l *Last100[T]) Add(v T)

Add adds a new value to the counter.

func (*Last100[T]) CopyTo

func (l *Last100[T]) CopyTo(other *Last100[T])

CopyTo copies the counter to the other counter.

func (*Last100[T]) Current

func (l *Last100[T]) Current() T

Current returns the current value.

func (*Last100[T]) GetScoreOf

func (l *Last100[T]) GetScoreOf(v T) float64

GetScoreOf returns the score of the given value in the last 100 values.

func (*Last100[T]) Preferred

func (l *Last100[T]) Preferred() (T, float64)

Preferred returns the preferred value and the score of the preferred value.

func (*Last100[T]) Reset

func (l *Last100[T]) Reset()

Reset resets the counter.

type Last1000

type Last1000[T ~int] struct {
	// contains filtered or unexported fields
}

func (*Last1000[T]) Add

func (l *Last1000[T]) Add(v T)

func (*Last1000[T]) CopyTo

func (l *Last1000[T]) CopyTo(other *Last1000[T])

func (*Last1000[T]) Current

func (l *Last1000[T]) Current() T

func (*Last1000[T]) GetScoreOf

func (l *Last1000[T]) GetScoreOf(v T) float64

getScoreOf returns the score of the given value in the last 1000 values.

func (*Last1000[T]) Preferred

func (l *Last1000[T]) Preferred() (T, float64)

func (*Last1000[T]) Reset

func (l *Last1000[T]) Reset()

Reset resets the counter.

type Leadership

type Leadership struct {
	// TODO: Add leadership properties.
	// Type (e.g. democratic, autocratic, etc.
	// Titles (e.g. king, council, etc.)
	// Leader(s) (e.g. council, king, etc.)
	Leaders []string
	// Influence  ClampedVal // Influence or popularity will determine the power of the leadership.
	Popularity ClampedVal // Popularity will determine the happiness of the tribe.
}

Leadership represents the leadership of a tribe or faction.

func (*Leadership) String

func (l *Leadership) String() string

String returns a string representation of the leadership.

type LifeEvent

type LifeEvent struct {
	Year   int
	Day    int
	Region int
}

LifeEvent represents a date and place in the world.

func (LifeEvent) IsSet

func (l LifeEvent) IsSet() bool

IsSet returns true if the life event is set.

type Map

type Map struct {
	*geo.Geo // Geography / geology
	*bio.Bio // Plants / animals / funghi
	*Civ     // Civilization

}

func NewMap

func NewMap(seed int64, numPlates, numPoints, numVolcanoes int, jitter float64) (*Map, error)

func NewMapFromConfig

func NewMapFromConfig(seed int64, cfg *Config) (*Map, error)

func (*Map) ExportOBJ

func (m *Map) ExportOBJ(path string) error

func (*Map) ExportPng

func (m *Map) ExportPng(name string)

func (*Map) ExportSVG

func (m *Map) ExportSVG(path string) error

ExportSVG exports the terrain as SVG to the given path. NOTE: This produces broken somewhat incomplete output due to the wraparound of the mesh.

func (*Map) ExportWebp

func (m *Map) ExportWebp(name string)

func (*Map) Get3DTile

func (m *Map) Get3DTile(x, y, zoom int) *Tile3D

Get3DTile returns the quantized 3D tile for the given x, y, and zoom. WARNING: THIS DOES NOT WORK YET!!!!!

func (*Map) GetCitiesInTile

func (m *Map) GetCitiesInTile(x, y, zoom int) []*City

GetCitiesInTile returns all cities within the given tile coordinates and zoom level.

func (*Map) GetGeoJSONBorders

func (m *Map) GetGeoJSONBorders(la1, lo1, la2, lo2 float64, zoom, displayMode int) ([]byte, error)

GetGeoJSONBorders returns all borders as GeoJSON within the given bounds and zoom level.

func (*Map) GetGeoJSONCities

func (m *Map) GetGeoJSONCities(la1, lo1, la2, lo2 float64, zoom int) ([]byte, error)

GetGeoJSONCities returns all cities as GeoJSON within the given bounds and zoom level.

func (*Map) GetHeightMapTile

func (m *Map) GetHeightMapTile(x, y, zoom int) []byte

func (*Map) GetTile

func (m *Map) GetTile(x, y, zoom, displayMode, vectorMode int, drawRivers, drawTradeRoutes, drawLakes, drawShadows, aspectShading bool) image.Image

GetTile returns the image of the tile at the given coordinates and zoom level.

func (*Map) Tick

func (m *Map) Tick()

Tick advances the map by one tick.

type MigrationTile

type MigrationTile struct {
	// contains filtered or unexported fields
}

func (*MigrationTile) PathEstimatedCost

func (n *MigrationTile) PathEstimatedCost(to goastar.Pather) float64

PathEstimatedCost is a heuristic method for estimating movement costs between non-adjacent nodes.

func (*MigrationTile) PathNeighborCost

func (n *MigrationTile) PathNeighborCost(to goastar.Pather) float64

PathNeighborCost calculates the exact movement cost to neighbor nodes.

func (*MigrationTile) PathNeighbors

func (n *MigrationTile) PathNeighbors() []goastar.Pather

PathNeighbors returns the direct neighboring nodes of this node which can be pathed to.

func (*MigrationTile) SetUsed

func (n *MigrationTile) SetUsed()

type ObjectReference

type ObjectReference struct {
	ID   int  // ID of the object that the event is about.
	Type byte // Type of the object that the event is about.
}

type Path

type Path struct {
	From, To int
	Steps    []int
	Idx      int
}

func (*Path) Done

func (p *Path) Done() bool

Done returns true if the path is done.

func (*Path) Next

func (p *Path) Next() int

Next returns the next region in the path and advances the path.

func (*Path) NumRemaining

func (p *Path) NumRemaining() int

NumRemaining returns the number of steps remaining in the path.

func (*Path) Peek

func (p *Path) Peek() int

Peek returns the next region in the path without advancing the path.

func (*Path) PeekDone

func (p *Path) PeekDone() bool

PeekDone returns true if the path is done after the next step.

type Person

type Person struct {
	ID      int            // ID of the person
	Region  int            // Location of the person
	Genes   genetics.Genes // Genes.
	City    *City          // City of the person
	Culture *Culture       // Culture of the person

	// Todo: Allow different naming conventions.
	FirstName string
	LastName  string
	NickName  string

	// Birth, death...
	// TODO: Add death cause.
	Age   int // Age of the person.
	Birth LifeEvent
	Death LifeEvent

	// Pregnancy
	PregnancyCounter int     // Days of pregnancy
	Prengancy        *Person // baby (TODO: twins, triplets, etc.)

	// Family (TODO: Distinguish between known and unknown family members.)
	// Maybe use a map of relations to people?
	Mother   *Person
	Father   *Person
	Spouse   *Person   // TODO: keep track of spouses that might have perished?
	Children []*Person // TODO: Split into known and unknown children.
}

Person represents a person in the world. TODO: Improve efficiency of this struct.

  • We could drop age, and use day-ticks for birth and death instead.
  • Also, we can get the gender directly from the genes.
  • We might be able to drop the pregnancy counter and use the birth life event of the child as a counter.
  • We can use use the Region for the location and derive the city from that.
  • A lot of this stuff is identical to simvillage_simple, so we could probably merge the person logic somehow, or move it to a separate package.

func (*Person) Gender

func (p *Person) Gender() geneticshuman.Gender

Gender returns the gender of the person.

func (*Person) Name

func (p *Person) Name() string

Name returns the name of the person.

func (*Person) Ref

func (p *Person) Ref() ObjectReference

Ref returns the object reference of the person.

func (*Person) String

func (p *Person) String() string

String returns the string representation of the person.

type QuantizedMeshHeader

type QuantizedMeshHeader struct {
	// The center of the tile in Earth-centered Fixed coordinates.
	CenterX float64
	CenterY float64
	CenterZ float64

	// The minimum and maximum heights in the area covered by this tile.
	// The minimum may be lower and the maximum may be higher than
	// the height of any vertex in this tile in the case that the min/max vertex
	// was removed during mesh simplification, but these are the appropriate
	// values to use for analysis or visualization.
	MinimumHeight float32
	MaximumHeight float32

	// The tile’s bounding sphere.  The X,Y,Z coordinates are again expressed
	// in Earth-centered Fixed coordinates, and the radius is in meters.
	BoundingSphereCenterX float64
	BoundingSphereCenterY float64
	BoundingSphereCenterZ float64
	BoundingSphereRadius  float64

	// The horizon occlusion point, expressed in the ellipsoid-scaled Earth-centered Fixed frame.
	// If this point is below the horizon, the entire tile is below the horizon.
	// See http://cesiumjs.org/2013/04/25/Horizon-culling/ for more information.
	HorizonOcclusionPointX float64
	HorizonOcclusionPointY float64
	HorizonOcclusionPointZ float64
}

type Religion

type Religion struct {
	ID                          int                 // The region where the religion was founded
	Name                        string              // The name of the religion
	NameGen                     *genstory.Generated // The name generation information
	Culture                     *Culture            // The culture that the religion is based on
	Parent                      *Religion           // The parent religion (if any)
	*genreligion.Classification                     // The religion classification
	Deity                       *genreligion.Deity  // The deity of the religion (if any)
	Expansion                   string              // How the religion wants to expand
	Expansionism                float64             // How much the religion wants to expand
	Founded                     int64               // Year when the religion was founded
}

Religion represents a religion in the world.

TODO: Ensure we can infer symbolisms from events and other things.

For example, if they worship the 99 beer bottles on the wall, we should be able to infer that they highly value beer and the number 99, as well as walls. They might be fearful of the number 100, and might have a taboo against the number 1. They might look kindly on people who can drink 99 beers in a row.

Another example: If they worship the sun, we should be able to infer that they highly value the sun, and that they might be fearful of the moon. They might have a celebration during the summer solstice and consider a total eclipse of the sun to be a bad omen and a moon eclipse to be a good omen.

DEITIES AND SYMBOLS

Folk religions that are purely based on the culture might warship nature itself, such as the sun, summer, the rain, a particular animal, or a particular plant. They might worship one or multiple deities that represent nature, like the sun god, the rain god, the god of the forest.

Organized religions might either worship one or multiple gods, or a single person that is considered to be a god (or chosen).

GRAPH

All these themes and connections could be represented as a graph, which would allow us to infer the relationships between deities and symbols and if mundane events hold any significance for a particular religion.

func (*Religion) String

func (r *Religion) String() string

type ResourceStorage

type ResourceStorage struct {
	Wood    [geo.ResMaxWoods]int
	Stone   [geo.ResMaxStones]int
	Metal   [geo.ResMaxMetals]int
	Gem     [geo.ResMaxGems]int
	Various [geo.ResMaxVarious]int
	// contains filtered or unexported fields
}

func (*ResourceStorage) Log

func (rs *ResourceStorage) Log()

type RunningAverage

type RunningAverage struct {
	// contains filtered or unexported fields
}

RunningAverage is a running average that takes the historical values into account.

func (*RunningAverage) Add

func (ra *RunningAverage) Add(v float64)

Add adds a new value to the running average.

func (*RunningAverage) CopyTo

func (ra *RunningAverage) CopyTo(other *RunningAverage)

CopyTo copies the running average to the other running average.

func (*RunningAverage) Current

func (ra *RunningAverage) Current() float64

Current returns the current average.

func (*RunningAverage) Reset

func (ra *RunningAverage) Reset()

Reset resets the running average.

type RunningAverageLimit

type RunningAverageLimit struct {
	RunningAverage
	// contains filtered or unexported fields
}

RunningaverageLimit is a running average that limits the number of historical values that are taken into account.

func NewRunningAverageLimit

func NewRunningAverageLimit(limit int) *RunningAverageLimit

NewRunningAverageLimit creates a new running average with a limit.

func (*RunningAverageLimit) Add

func (ra *RunningAverageLimit) Add(v float64)

Add adds a new value to the running average.

func (*RunningAverageLimit) CopyTo

func (ra *RunningAverageLimit) CopyTo(other *RunningAverageLimit)

CopyTo copies the running average to the other running average.

type RunningBool

type RunningBool struct {
	RunningAverage
}

func NewRunningBool

func NewRunningBool() *RunningBool

func (*RunningBool) Add

func (ra *RunningBool) Add(v bool)

func (*RunningBool) CopyTo

func (ra *RunningBool) CopyTo(other *RunningBool)

func (*RunningBool) Current

func (ra *RunningBool) Current() bool

func (*RunningBool) Reset

func (ra *RunningBool) Reset()

type Skill

type Skill struct {
	Name              string
	MinScore          float64        // The minimum score required to develop the skill.
	Chance            float64        // The chance of developing the skill.
	Biomes            []int          // The biomes the skill can be developed in.
	Wood              bool           // If the skill requires wood.
	Stone             bool           // If the skill requires stone.
	Metal             bool           // If the skill requires metal.
	Gems              bool           // If the skill requires gems.
	WaterProximity    bool           // If the skill requires water proximity.
	RiverProximity    bool           // If the skill requires river proximity.
	LakeProximity     bool           // If the skill requires lake proximity.
	OceanProximity    bool           // If the skill requires ocean proximity.
	MountainProximity bool           // If the skill requires mountain proximity. (e.g. mining)
	Requires          []*Skill       // Required skills to develop this skill.
	Effect            func(t *Tribe) // The effect of the skill on the tribe.
}

func (*Skill) CanDevelopIn

func (s *Skill) CanDevelopIn(curRegProp *regionProp, wood, stone, metal, gems bool) bool

func (*Skill) DevelopAt

func (s *Skill) DevelopAt(score float64) bool

DevelopAt returns true if the skill can be developed at the given score.

func (*Skill) EffectOnTribe

func (s *Skill) EffectOnTribe(t *Tribe)

EffectOnTribe applies the effect of the skill on the tribe.

func (*Skill) GetBonusForBiome

func (s *Skill) GetBonusForBiome(curRegProp *regionProp, wood, stone, metal, gems bool) float64

GetBonusForBiome returns a bonus score derived from the skill based on the biome and water proximity.

type Tile3D

type Tile3D struct {
	Header QuantizedMeshHeader
	Vertex VertexData
	Index  IndexData
	Edge   EdgeIndices
}

Each tile is a specially-encoded triangle mesh where vertices overlap their neighbors at tile edges. In other words, at the root, the eastern-most vertices in the western tile have the same longitude as the western-most vertices in the eastern tile.

Terrain tiles are served gzipped. Once extracted, tiles are little-endian, binary data.

func (*Tile3D) Write

func (t *Tile3D) Write(w *bytes.Buffer) error

type TownType

type TownType string

TownType represents the type of a city.

const (
	TownTypeDefault     TownType = "town"
	TownTypeTrading     TownType = "trading"
	TownTypeMining      TownType = "mining"
	TownTypeMiningGems  TownType = "mining (gems)"
	TownTypeQuarry      TownType = "quarry"
	TownTypeFarming     TownType = "agricultural"
	TownTypeDesertOasis TownType = "desert oasis"
)

The different types of cities.

func (TownType) FoundingPopulation

func (t TownType) FoundingPopulation() int

FoundingPopulation returns the starting population of a city type.

func (TownType) GetDistanceSeedFunc

func (t TownType) GetDistanceSeedFunc(m *Civ) func() []int

GetDistanceSeedFunc returns the distance seed function for a city type.

func (TownType) GetFitnessFunction

func (t TownType) GetFitnessFunction(m *Civ) func(int) float64

GetFitnessFunction returns the fitness function for a city type.

type TradeTile

type TradeTile struct {
	// contains filtered or unexported fields
}

func (*TradeTile) PathEstimatedCost

func (n *TradeTile) PathEstimatedCost(to goastar.Pather) float64

PathEstimatedCost is a heuristic method for estimating movement costs between non-adjacent nodes.

func (*TradeTile) PathNeighborCost

func (n *TradeTile) PathNeighborCost(to goastar.Pather) float64

PathNeighborCost calculates the exact movement cost to neighbor nodes.

func (*TradeTile) PathNeighbors

func (n *TradeTile) PathNeighbors() []goastar.Pather

PathNeighbors returns the direct neighboring nodes of this node which can be pathed to.

func (*TradeTile) SetUsed

func (n *TradeTile) SetUsed()

type Tribe

type Tribe struct {
	ID         int                   // Unique ID for the tribe.
	RegionID   int                   // The region the tribe is currently in.
	Population int                   // The population of the tribe.
	Type       TribeType             // The type of the tribe (nomadic, settled, city state, empire, etc.)
	Parent     *Tribe                // The parent tribe of the tribe.
	Language   *genlanguage.Language // The language of the tribe.
	Settlement *City                 // The city the tribe has settled in.
	Culture    *Culture              // Culture that the tribe might have developed.
	Religion   *Religion             // Religion that the tribe might have developed.
	CityState  *CityState            // City state that the tribe might have developed.
	Empire     *Empire               // Empire that the tribe might have developed.

	// TODO: Change this to a running average.
	Satisfaction    ClampedVal           // Happiness of the tribe overall.
	SatisfactionAvg *RunningAverageLimit // Running average of the tribe's satisfaction.
	Leadership      *Faction             // Current leadership of the tribe.
	Factions        []*Faction           // Factions within the tribe / opposition, etc.
	Skills          map[*Skill]bool      // Skills of the tribe.

	// Preferences of the tribe.
	LastBiomes        *Last100[HackyBiome]  // The last 1000 biomes the tribe has been in.
	LastCultures      *Last100[CultureType] // The last 1000 cultures the tribe has been in.
	RiverProximity    *RunningBool
	LakeProximity     *RunningBool
	OceanProximity    *RunningBool
	MountainProximity *RunningBool

	*Path // Pathfinding for migrating tribes.

	*ResourceStorage // Resources the tribe has.
	// contains filtered or unexported fields
}

We start with one tribe. This tribe will be nomadic, and will move around. After a while, the tribe might be big enough to split into two tribes.

A tribe can split due to: - Survival reasons (not enough food, etc. in the regions in their proximity). - Religious reasons (a new vision from the gods, etc.). - TODO: Cultural reasons (a different culture type preference, etc.). - TODO: Unhappiness (a string of bad events, deaths, famine, etc.).

When a tribe splits, the new tribe will have a part of the population of the original tribe and retain some of the culture, religion, etc. of the original tribe. (In the future, we might want to consider that we fork the culture, religion, etc. of the original tribe as soon as the new tribe is created, not only when the tribe settles.).

Settled Tribes:

Tribes can either be settled or nomadic. Once a tribe has developed enough skills to permanently survive sustainably in a region type, it will look for a region to settle in within a certain radius. The radius depends on the form of discovery (e.g. a vision from the gods might have a larger radius, while a region discovered by the tribe itself through scouting might have a smaller radius). The tribe will then move to the region and settle there, if it is not already occupied by another tribe.

If the region is already occupied, the tribe will either: - try to find another region to settle in - TODO: fight for the region - TODO: merge with the other tribe if the conditions are right

Once the tribe has settled in a region, it will develop a new culture and a religion. If the tribe has inherited a religion or culture from the parent tribe, it will fork the culture and religion and develop a new one based on the preferences of the tribe. The tribe's language will be also become independent from the parent tribe from this point on. The tribe will also create a settlement in the region, which will be the cultural and religious center of the tribe.

Nomadic Tribes:

Tribes can also be nomadic. Nomadic tribes will move around, always looking for the most prosperous / suitable region to settle in. If the most prosperous region cannot sustain the entire tribe, the tribe will split into two or more tribes. The new tribes will move to the most suitable regions, while the original tribe will try to survive in the current region.

The tribe will gain skills and preferences based on the regions it has been in. The tribe will start to prefer the types of regions (biomes, water proximity, mountain proximity, etc.) it has been in the most. The tribe will also develop skills based on the regions it has been in.

Skills:

Skills should provide a bonus to the tribe's sustainability in a region. Skills can be developed based on the region type, the tribe's preferences, and influence the tribe's culture.

Skills can be developed based on: - Biome type and tribe preference for the biome - Water proximity - Mountain proximity - Existing skills of the tribe - TODO: Culture of the tribe - TODO: Religion of the tribe - TODO: Available resources in the region - TODO: Available species in the region

  • Grains (wheat, barley, etc.) for farming, beer, bread, etc.
  • Animals (cows, buffalos, etc.) for herding, milk, meat, etc.
  • Fish (salmon, trout, etc.) for fishing, food, etc.

TODO: Happiness:

The happiness of the tribe will depend on various factors:

- Growth rate of the tribe - The tribe's preferences (if the tribe is in a region it prefers or not) - Deaths (from conflicts, famine, etc.) - Randomized events like:

  • Corrupt leaders
  • Famine
  • Disease
  • Natural disasters
  • Accidents

TODO: - Keep track of the type of regions we are at and at some point adjust the culture to prefer certain regions. - Keep note of skills and knowledge of the tribe (e.g. farming, mining, etc.) Skills can develop based on the biome and region type the tribe is in. TODO: Based on the counts, we can evaluate the chances of the tribe discovering new skills, knowledge, etc. TODO: Keep track of water proximity, etc.

func NewTribe

func NewTribe(id, regionID, population int) *Tribe

NewTribe returns a new tribe with the given population.

func (*Tribe) DevelopSkills

func (t *Tribe) DevelopSkills(curRegProp *regionProp, wood, stone, metal, gems bool)

DevelopSkills develops the skills of the tribe based on the biome and region type.

func (*Tribe) GetCultureType

func (t *Tribe) GetCultureType() CultureType

GetCultureType returns the culture type of the tribe.

func (*Tribe) Grow

func (t *Tribe) Grow()

Grow the population of the tribe for one year.

func (*Tribe) RandomSplit

func (t *Tribe) RandomSplit(nextID int) *Tribe

func (*Tribe) Ref

func (t *Tribe) Ref() ObjectReference

Ref returns the object reference of the city.

func (*Tribe) SetPath

func (t *Tribe) SetPath(path *Path)

func (*Tribe) Split

func (t *Tribe) Split(id int, newPopulation int) *Tribe

Split the tribe into two tribes with a new one with the given population.

func (*Tribe) String

func (t *Tribe) String() string

func (*Tribe) SustainabilityFactor

func (t *Tribe) SustainabilityFactor(curRegProp *regionProp, wood, stone, metal, gems bool) float64

type TribeType

type TribeType int
const (
	TribeTypeNomadic TribeType = iota
	TribeTypeSettling
	TribeTypeCity
	TribeTypeCityState
	TribeTypeEmpire
)

type VertexData

type VertexData struct {
	VertexCount uint32
	// The horizontal coordinate of the vertex in the tile.
	// - When the u value is 0, the vertex is on the Western edge of the tile.
	// - When the value is 32767, the vertex is on the Eastern edge of the tile.
	// - For other values, the vertex's longitude is a linear interpolation between
	// the longitudes of the Western and Eastern edges of the tile.
	U []uint16 // [vertexCount]uint16
	// The vertical coordinate of the vertex in the tile.
	// - When the v value is 0, the vertex is on the Southern edge of the tile.
	// - When the value is 32767, the vertex is on the Northern edge of the tile.
	// - For other values, the vertex's latitude is a linear interpolation between
	// the latitudes of the Southern and Nothern edges of the tile.
	V []uint16 // [vertexCount]uint16
	// The height of the vertex in the tile.
	// - When the height value is 0, the vertex's height is equal to the minimum
	// height within the tile, as specified in the tile's header.
	// - When the value is 32767, the vertex's height is equal to the maximum height
	// within the tile.
	// - For other values, the vertex's height is a linear interpolation between the
	// minimum and maximum heights.
	Height []uint16 // [vertexCount]uint16
}

The vertexCount field indicates the size of the three arrays that follow. The three arrays contain the delta from the previous value that is then zig-zag encoded in order to make small integers, regardless of their sign, use a small number of bits.

func (*VertexData) Write

func (vd *VertexData) Write(w io.Writer) error

Directories

Path Synopsis
cmd
maptiles
Package maptiles implements a map tiles skeleton package implementing the tiles á la Google maps.
Package maptiles implements a map tiles skeleton package implementing the tiles á la Google maps.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL