Checkpoint initial implementation

This commit is contained in:
Andrew Miner
2025-10-06 17:41:18 -06:00
parent 773e0a3d85
commit a8b6e6b15e
106 changed files with 3012 additions and 0 deletions
View File
+70
View File
@@ -0,0 +1,70 @@
from tungston.core.ecology.biometrait import BiomeTrait
from tungston.core.ecology.flora import Flora
from tungston.core.ecology.geology import Geology
from tungston.core.ecology.heat import Heat
from tungston.core.ecology.humidity import Humidity
from tungston.core.ecology.soil import Soil
from tungston.core.ecology.water import Water
####################################################################################################
class Biome(object):
"""
A region of the world defined by a unique combination of geology, topography, and ecology.
"""
def __init__(
self,
city:str,
gameId:str,
flora:Flora,
geology:Geology,
heat:Heat,
humidity:Humidity,
soil:Soil,
water:Water,
):
self.city = city
self.gameId = gameId
self.flora = flora
self.geology = geology
self.heat = heat
self.humidity = humidity
self.soil = soil
self.water = water
def __eq__(self, other) -> bool:
if type(self) != type(other): return False
if self.biomeId != other.biomeId: return False
if self.city != other.city: return False
return True
def __hash__(self) -> int:
return hash((self.biomeId, self.city))
def __str__(self) -> str:
return f"{self.city}<{self.gameId}>"
def __repr__(self) -> str:
return "".join([str(p) for p in [
str(self), "{",
repr(self.flora), ", ",
repr(self.geology), ", ",
repr(self.heat), ", ",
repr(self.humidity), ", ",
repr(self.soil), ", ",
repr(self.water),
"}"
]])
def traits(self) -> set[BiomeTrait]:
return set([
self.flora,
self.geology,
self.heat,
self.humidity,
self.soil,
self.water,
])
+25
View File
@@ -0,0 +1,25 @@
from pytest import fixture
from tungston.core.ecology.biome import Biome
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Fixtures #########################################################################################
@fixture(name="desert")
def createDesert():
return Biome(
"phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
)
# Tests ############################################################################################
def test_createBiome(desert):
assert desert.city == "phoenix"
assert desert.soil == S.SANDY
+25
View File
@@ -0,0 +1,25 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomefilter import BiomeFilter
# Classes ##########################################################################################
class BiomeCatalog:
"""
A comprehensive list of all available biomes in the modpack.
"""
def __init__(self, biomes):
self.biomes = sorted(biomes, key=lambda b: b.city)
def all(self) -> list[Biome]:
return list(self.biomes)
def matching(self, biomeFilter:BiomeFilter) -> list[Biome]:
result = []
for biome in self.biomes:
if biomeFilter.accepts(biome):
result.append(biome)
return result
@@ -0,0 +1,46 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomecatalog import BiomeCatalog
from tungston.core.ecology.biomefilter import BiomeFilter
from pytest import fixture
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Fixtures #########################################################################################
@fixture(name="jungles")
def createJungleFilter():
yield BiomeFilter([U.WET, E.TROPICAL, F.within(F.CANOPY, F.CLEARING)])
@fixture(name="catalog")
def createCatalog():
yield BiomeCatalog([
Biome("dallas", "minecraft:savanna",
F.FIELD, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("kansascity", "minecraft:plains",
F.FIELD, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("mobile", "minecraft:swamp",
F.CLEARING, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.PEATY, W.SWAMP
),
Biome("phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("portland", "minecraft:forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("singapore", "minecraft:jungle",
F.CANOPY, G.SEDIMENTARY, E.TROPICAL, U.WET, S.ACIDIC, W.INLAND
),
])
# Tests ############################################################################################
def test_findJungles(catalog, jungles):
assert [b.city for b in catalog.matching(jungles)] == ["singapore"]
+57
View File
@@ -0,0 +1,57 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class BiomeFilter:
"""
A description of which biomes may be considered for a given purpose.
This class works by allowing *both* allowed and prohibited traits.
The list of allowed traits may contain either individual trait objects, or a list of such
objects. When an individual trait is given, only biomes with that exact trait are permitted.
When a list of traits is given, biomes containing any of the listed traits are permitted. To
put it another way, each individual item in the required list is an "OR" filter, and the results
of the entire list are "AND"ed together.
The list of prohibited traits only permits individual traits, but multiple traits of the same
sort may be given.
The filter only accepts biomes which pass *both* lists. That is, it must possess *all* the
required traits while simultaneously not possessing *any* of the prohibited ones.
"""
def __init__(
self,
required:list[BiomeTrait|list[BiomeTrait]]=None,
prohibited:list[BiomeTrait]=None,
):
self.required = required or []
self.prohibited = prohibited or []
def __repr__(self) -> str:
return f"BiomeFilter([{repr(self.required)}], [{repr(self.prohibited)}])"
def accepts(self, biome: Biome) -> bool:
biomeTraits = biome.traits()
for condition in self.required:
if isinstance(condition, BiomeTrait):
trait = condition
if trait not in biomeTraits: return False
else:
traitOptions = condition
foundMatch = False
for trait in traitOptions:
if trait in biomeTraits:
foundMatch = True
break
if not foundMatch: return False
for prohibitedTrait in self.prohibited:
if prohibitedTrait in biomeTraits: return False
return True
+61
View File
@@ -0,0 +1,61 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomefilter import BiomeFilter
from pytest import fixture
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Fixtures #########################################################################################
@fixture(name="barren")
def createBarrenFilter():
yield BiomeFilter([F.BARREN])
@fixture(name="barrenNotSandy")
def createBarrenNotSandFilter():
yield BiomeFilter([F.BARREN], [S.SANDY])
@fixture(name="desert")
def createDesertBiome():
yield Biome(
"phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
)
@fixture(name="fertile")
def createFertileFilter():
yield BiomeFilter([(S.LOAMY, S.PEATY)])
@fixture(name="forest")
def createForestBiome():
yield Biome(
"portland", "minecraft:forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
)
@fixture(name="notDry")
def createNotDryFilter():
yield BiomeFilter([], [U.DRY])
# Tests ############################################################################################
def test_prohibitsSingleTrait(notDry, desert, forest):
assert notDry.accepts(forest)
assert not notDry.accepts(desert)
def test_requireSingleTrait(barren, desert, forest):
assert barren.accepts(desert)
assert not barren.accepts(forest)
def test_requireOptions(fertile, desert, forest):
assert fertile.accepts(forest)
assert not fertile.accepts(desert)
def test_vetoed(barrenNotSandy, desert):
assert not barrenNotSandy.accepts(desert)
+49
View File
@@ -0,0 +1,49 @@
# Class ############################################################################################
class BiomeTrait:
"""
Any of the many characteristics which uniquely define a biome.
"""
def __init__(self, name:str):
self.name = name
def __eq__(self, other) -> bool:
if type(self).__name__ != type(other).__name__: return False
if self.name != other.name: return False
return True
def __hash__(self) -> int:
return hash((type(self).__name__, self.name))
def __str__(self):
return self.name
def __repr__(self) -> str:
return f"{type(self).__name__}<{self.name}>"
# Helper Functions #################################################################################
def within(allTraits:list[BiomeTrait], start:BiomeTrait, end:BiomeTrait) -> list[BiomeTrait]:
if not allTraits: return []
start = start if start else allTraits[0]
end = end if end else allTraits[-1]
minIndex = 0
maxIndex = len(allTraits) - 1
for index, trait in enumerate(allTraits):
if trait == start:
minIndex = index
elif trait == end:
maxIndex = index
if minIndex > maxIndex:
minIndex, maxIndex = maxIndex, minIndex
result = []
for index in range(minIndex, maxIndex+1):
result.append(allTraits[index])
return result
+58
View File
@@ -0,0 +1,58 @@
from tungston.core.ecology.biometrait import BiomeTrait
from pytest import fixture
import tungston.core.ecology.biometrait as biomeTrait
# Fixtures #########################################################################################
@fixture(name="blue")
def defineBlue():
yield BiomeTrait("blue")
@fixture(name="green")
def defineGreen():
yield BiomeTrait("green")
@fixture(name="yellow")
def defineYellow():
yield BiomeTrait("yellow")
@fixture(name="orange")
def defineOrange():
yield BiomeTrait("orange")
@fixture(name="red")
def defineRed():
yield BiomeTrait("red")
@fixture(name="traitMap")
def createTraitMap(green, blue):
yield {
green: "emerald",
blue: "sapphire"
}
@fixture(name="traitList")
def createTraitList(green, blue, yellow, orange, red):
yield [blue, green, yellow, orange, red]
# Tests ############################################################################################
def test_eq(green, blue):
assert green == BiomeTrait("green")
assert green != blue
def test_hash(green, blue, traitMap):
assert traitMap[green] == "emerald"
assert traitMap[blue] == "sapphire"
def test_repr(green):
assert repr(green) == "BiomeTrait<green>"
def test_str(green):
assert str(green) == "green"
def test_within(traitList, green, yellow, orange):
assert biomeTrait.within(traitList, green, orange) == [green, yellow, orange]
+28
View File
@@ -0,0 +1,28 @@
from tungston.core.ecology.biometrait import BiomeTrait
import tungston.core.ecology.biometrait as biomeTrait
# Class ############################################################################################
class Flora(BiomeTrait):
"""
Describes how densely the foiliage covers a biome.
"""
pass
# Constants ########################################################################################
CANOPY = Flora("canopy")
FOREST = Flora("forest")
CLEARING = Flora("clearing")
FIELD = Flora("field")
BARREN = Flora("barren")
ALL = [CANOPY, FOREST, CLEARING, FIELD, BARREN]
# Helpers ##########################################################################################
def within(start:Flora, end:Flora) -> list[Flora]:
return biomeTrait.within(ALL, start, end)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.flora as flora
# Tests ############################################################################################
def test_within():
assert flora.within(flora.FOREST, flora.FIELD) == [flora.FOREST, flora.CLEARING, flora.FIELD]
+19
View File
@@ -0,0 +1,19 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Geology(BiomeTrait):
"""
The natural of the rock strata in a biome.
"""
pass
# Constants ########################################################################################
IGNEOUS = Geology("igneous")
METAMORPHIC = Geology("metamorphic")
SEDIMENTARY = Geology("sedimentary")
ALL = [IGNEOUS, METAMORPHIC, SEDIMENTARY]
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.geology as geology
# Tests ############################################################################################
def test_syntax():
pass
+33
View File
@@ -0,0 +1,33 @@
from tungston.core.ecology.biometrait import BiomeTrait
import tungston.core.ecology.biometrait as biomeTrait
# Class ############################################################################################
class Heat(BiomeTrait):
"""
The general range of ambient temperatures in a biome (in °F).
"""
def __init__(self, name, low:int, high:int):
super().__init__(name)
self.low = low
self.high = high
# Constants ########################################################################################
TROPICAL = Heat("tropical", 75, 88)
SUBTROPICAL = Heat("subtropical", 58, 82)
TEMPERATE = Heat("temperate", 36, 66)
BOREAL = Heat("boreal", 10, 54)
FROZEN = Heat("frozen", -20, 32)
ALL = [TROPICAL, SUBTROPICAL, TEMPERATE, BOREAL, FROZEN]
# Helpers ##########################################################################################
def within(start:Heat, end:Heat) -> list[Heat]:
return biomeTrait.within(ALL, start, end)
+13
View File
@@ -0,0 +1,13 @@
from pytest import fixture
import tungston.core.ecology.heat as heat
# Tests ############################################################################################
def test_within():
assert (
heat.within(heat.SUBTROPICAL, heat.BOREAL)
==
[heat.SUBTROPICAL, heat.TEMPERATE, heat.BOREAL]
)
+26
View File
@@ -0,0 +1,26 @@
from tungston.core.ecology.biometrait import BiomeTrait
import tungston.core.ecology.biometrait as biomeTrait
# Class ############################################################################################
class Humidity(BiomeTrait):
"""
The general level of humidity present in the air.
"""
pass
# Constants ########################################################################################
WET = Humidity("wet")
DAMP = Humidity("damp")
DRY = Humidity("dry")
ALL = [WET, DAMP, DRY]
# Helpers ##########################################################################################
def within(start:Humidity, end:Humidity) -> list[Humidity]:
return biomeTrait.within(ALL, start, end)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.humidity as humidity
# Tests ############################################################################################
def test_within():
assert humidity.within(humidity.DAMP, humidity.DRY) == [humidity.DAMP, humidity.DRY]
+23
View File
@@ -0,0 +1,23 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Soil(BiomeTrait):
"""
The nature of the soil within a certain region.
"""
pass
# Constants ########################################################################################
ACIDIC = Soil("acidic")
CLAYEY = Soil("clayey")
FUNGAL = Soil("fungal")
LOAMY = Soil("loamy")
PEATY = Soil("peaty")
ROCKY = Soil("rocky")
SANDY = Soil("sandy")
ALL = [ACIDIC, CLAYEY, FUNGAL, LOAMY, PEATY, ROCKY, SANDY]
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.soil as soil
# Tests ############################################################################################
def test_syntax():
pass
+21
View File
@@ -0,0 +1,21 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Water(BiomeTrait):
"""
The kind of large body of water which dominates a biome.
"""
pass
# Constants ########################################################################################
RIVER = Water("river")
SWAMP = Water("swamp")
OCEAN = Water("ocean")
COAST = Water("coast")
INLAND = Water("inland")
ALL = (RIVER, SWAMP, OCEAN, COAST, INLAND)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.water as water
# Tests ############################################################################################
def test_syntax():
pass