Checkpoint initial implementation
This commit is contained in:
@@ -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,
|
||||
])
|
||||
@@ -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
|
||||
@@ -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"]
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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]
|
||||
@@ -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)
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -0,0 +1,9 @@
|
||||
from pytest import fixture
|
||||
|
||||
import tungston.core.ecology.geology as geology
|
||||
|
||||
|
||||
# Tests ############################################################################################
|
||||
|
||||
def test_syntax():
|
||||
pass
|
||||
@@ -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)
|
||||
@@ -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]
|
||||
)
|
||||
@@ -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)
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -0,0 +1,9 @@
|
||||
from pytest import fixture
|
||||
|
||||
import tungston.core.ecology.soil as soil
|
||||
|
||||
|
||||
# Tests ############################################################################################
|
||||
|
||||
def test_syntax():
|
||||
pass
|
||||
@@ -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)
|
||||
@@ -0,0 +1,9 @@
|
||||
from pytest import fixture
|
||||
|
||||
import tungston.core.ecology.water as water
|
||||
|
||||
|
||||
# Tests ############################################################################################
|
||||
|
||||
def test_syntax():
|
||||
pass
|
||||
Reference in New Issue
Block a user