diff --git a/tungston/core/altitude.py b/tungston/core/altitude.py index c40f67b..ce26fb9 100644 --- a/tungston/core/altitude.py +++ b/tungston/core/altitude.py @@ -67,8 +67,20 @@ def span(*altitudes): if not altitudes: return ANYWHERE result = Altitude("", ANYWHERE.top, ANYWHERE.bottom) - for altitude in altitudes: - result.bottom = min(result.bottom, altitude.bottom) - result.top = max(result.top, altitude.top) + bottom = OVERGROUND[-1].top + bottomAltitude = None + top = UNDERGROUND[-1].bottom + topAltitude = None + + for altitude in altitudes: + if altitude.bottom < bottom: + bottom = altitude.bottom + bottomAltitude = altitude + + if altitude.top > top: + top = altitude.top + topAltitude = altitude + + result = Altitude(f"{bottomAltitude.name}-{topAltitude.name}", bottom, top) return result diff --git a/tungston/core/altitude_test.py b/tungston/core/altitude_test.py index 27edd03..48fd2b6 100644 --- a/tungston/core/altitude_test.py +++ b/tungston/core/altitude_test.py @@ -13,6 +13,6 @@ def mergeRange(): # Tests ############################################################################################ def test_span(merged): + assert merged.name == "lowlands-uplands" assert merged.bottom == A.LOWLANDS.bottom assert merged.top == A.UPLANDS.top - diff --git a/tungston/core/ecology/biomefilter.py b/tungston/core/ecology/biomefilter.py index a01e517..f02a0ea 100644 --- a/tungston/core/ecology/biomefilter.py +++ b/tungston/core/ecology/biomefilter.py @@ -31,6 +31,30 @@ class BiomeFilter: self.required = required or [] self.prohibited = prohibited or [] + def __str__(self) -> str: + required = [] + for trait in self.required: + if isinstance(trait, BiomeTrait): + required.append(str(trait)) + else: + required.append("(" + + ", ".join([str(option) for option in trait]) + + ")") + + prohibited = [] + for trait in self.prohibited: + prohibited.append(str(trait)) + + result = "".join([ + "must:[", + ", ".join(required), + "], not:[", + ", ".join(prohibited), + "]" + ]) + + return result + def __repr__(self) -> str: return f"BiomeFilter([{repr(self.required)}], [{repr(self.prohibited)}])" diff --git a/tungston/core/fauna/group.py b/tungston/core/fauna/group.py index 24c4145..5001af3 100644 --- a/tungston/core/fauna/group.py +++ b/tungston/core/fauna/group.py @@ -5,7 +5,7 @@ class Group: How many individuals are commonly present when encountering a creature. """ - def __init__(self, name, smallest, largest): + def __init__(self, name:str, smallest:int, largest:int): self.name = name self.smallest = smallest self.largest = largest @@ -42,9 +42,19 @@ ALL = [SOLO, PAIR, FAMILY, TROUP, HERD] def merge(*groups): if not groups: return SOLO - result = Group(f"", HERD.largest, SOLO.smallest) - for group in groups: - result.smallest = min(result.smallest, group.smallest) - result.largest = max(result.largest, group.largest) + smallest = ALL[-1].largest + smallestGroup = None - return result + largest = ALL[0].smallest + largestGroup = None + + for group in groups: + if group.smallest < smallest: + smallest = group.smallest + smallestGroup = group + + if group.largest > largest: + largest = group.largest + largestGroup = group + + return Group(f"{smallestGroup.name}-{largestGroup.name}", smallest, largest) diff --git a/tungston/core/fauna/mobcatalog.py b/tungston/core/fauna/mobcatalog.py index 232dd05..fcda846 100644 --- a/tungston/core/fauna/mobcatalog.py +++ b/tungston/core/fauna/mobcatalog.py @@ -1,16 +1,26 @@ -from tungston.core.fauna.mob import Mob +from collections.abc import Iterator +from tungston.core.fauna.mobplacement import MobPlacement # Class ############################################################################################ class MobCatalog: - def __init__(self, mobs): - self.mobs = mobs + def __init__(self, mobs:tuple[MobPlacement]): + self._mobs = {} - def findByName(self, name): - for mob in self.mobs: - if mob.name == name: - return mob + for mob in mobs: + self.add(mob) - return None + def add(self, placement:MobPlacement) -> "MobCatalog": + if placement.mob.name in self._mobs: + raise Exception("Catalog already has an entry for {mob.name}") + + self._mobs[placement.mob.name] = placement + + def all(self) -> Iterator[MobPlacement]: + for placement in self._mobs.values(): + yield placement + + def get(self, name:str) -> MobPlacement: + return self._mobs.get(name, None) diff --git a/tungston/core/fauna/mobplacement_test.py b/tungston/core/fauna/mobplacement_test.py index 1f6701f..66a2eed 100644 --- a/tungston/core/fauna/mobplacement_test.py +++ b/tungston/core/fauna/mobplacement_test.py @@ -30,7 +30,7 @@ def test_cowsInFields(placement): "Placement{" + "habitats: [" + "Habitat{" + - "altitude: [anywhere <-64 to 320>], " + + "altitude: anywhere <-64 to 320>, " + "biomeFilter: BiomeFilter([[Flora, Heat]], [[]]), " + "seasons: [Season, Season, Season, Season], " + "group: solo<1 to 1>, " + diff --git a/tungston/core/geology/deposit/metaldeposit_test.py b/tungston/core/geology/deposit/metaldeposit_test.py index af39fd9..a171427 100644 --- a/tungston/core/geology/deposit/metaldeposit_test.py +++ b/tungston/core/geology/deposit/metaldeposit_test.py @@ -44,7 +44,7 @@ def test_repr(bifIron): assert repr(bifIron) == ( "MetalDeposit{" + "scarcity: Scarcity, " + - "biomeFilter: BiomeFilter([[Flora]], [[]]), " + + "biomeFilter: must:[Flora: forest], not:[], " + "inclusions: [" + "Inclusion{mineral: iron, weight: 60}, " + "Inclusion{mineral: quartz, weight: 40}" + diff --git a/tungston/core/habitat.py b/tungston/core/habitat.py index d2ec6ce..dbe4e8f 100644 --- a/tungston/core/habitat.py +++ b/tungston/core/habitat.py @@ -22,7 +22,7 @@ class Habitat: def __init__( self, - altitudes:tuple[Altitude]|Altitude=[A.ANYWHERE], + altitude:Altitude=A.ANYWHERE, biomeFilter:BiomeFilter=None, seasons:tuple[Season]=E.ALL, @@ -30,7 +30,7 @@ class Habitat: location:Location=L.OUTSIDE, scarcity:Scarcity=C.SPARSE, ): - self.altitudes = (altitudes,) if isinstance(altitudes, Altitude) else altitudes + self.altitude = altitude self.biomeFilter = biomeFilter or BiomeFilter() self.seasons = (seasons,) if isinstance(seasons, Season) else seasons @@ -41,19 +41,19 @@ class Habitat: self._source = None def __str__(self) -> str: - return "".join(str(p) for p in [ - self.altitude, "|", + return "".join([str(p) for p in [ + ", ".join(self.altitude), "|", self.biomeFilter, "|", - self.seasons, "|", + ", ".join([str(s) for s in self.seasons]), "|", self.group, "|", self.location, "|", self.scarcity - ]) + ]]) def __repr__(self) -> str: return "".join([str(p) for p in [ "Habitat{", - "altitude: [", ", ".join([repr(a) for a in self.altitudes]), "], ", + "altitude: ", repr(self.altitude), ", ", "biomeFilter: ", repr(self.biomeFilter), ", ", "seasons: [", ", ".join([repr(s) for s in self.seasons]), "], ", "group: ", repr(self.group), ", ", @@ -64,7 +64,7 @@ class Habitat: def derive(self, **kwargs): kwargs = { - "altitudes": self.altitudes, + "altitude": self.altitude, "biomeFilter": self.biomeFilter, "seasons": self.seasons, "group": self.group, diff --git a/tungston/core/habitat_test.py b/tungston/core/habitat_test.py index 287df29..95cd64e 100644 --- a/tungston/core/habitat_test.py +++ b/tungston/core/habitat_test.py @@ -35,7 +35,7 @@ def test_derive(derivedHabitats): def test_repr(fields): assert repr(fields) == ( "Habitat{" + - "altitude: [anywhere <-64 to 320>], " + + "altitude: anywhere <-64 to 320>, " + "biomeFilter: BiomeFilter([[Flora, Heat]], [[]]), " + "seasons: [Season, Season, Season, Season], " + "group: solo<1 to 1>, " + diff --git a/tungston/core/placement_test.py b/tungston/core/placement_test.py index 73774c1..054b4e5 100644 --- a/tungston/core/placement_test.py +++ b/tungston/core/placement_test.py @@ -25,7 +25,7 @@ def test_repr(placement): "Placement{" + "habitats: [" + "Habitat{" + - "altitude: [anywhere <-64 to 320>], " + + "altitude: anywhere <-64 to 320>, " + "biomeFilter: BiomeFilter([[Flora, Heat]], [[]]), " + "seasons: [Season, Season, Season, Season], " + "group: solo<1 to 1>, " + diff --git a/tungston/generator/markdown/mobreport.py b/tungston/generator/markdown/mobreport.py new file mode 100644 index 0000000..49d5532 --- /dev/null +++ b/tungston/generator/markdown/mobreport.py @@ -0,0 +1,49 @@ +from tungston.core.world import World +from tungston.core.ecology.biometrait import BiomeTrait +from tungston.generator.markdown.report import Report + + +# Class ############################################################################################ + +class MobReport(Report): + + def __init__(self, world:World): + super().__init__("mobs.md", world) + + def build(self): + for placement in self.world.mobs.all(): + self.line(f"# Mob: {placement.mob.name} <{placement.mob.gameId}>") + self.line() + + self.indent() + for index, habitat in enumerate(placement.habitats, start=1): + self.text("* habitat ").line(index) + self.indent() + self.text("* altitude: ").line(habitat.altitude) + self.line("* biomeFilter:") + + self.indent() + for trait in habitat.biomeFilter.required: + if isinstance(trait, BiomeTrait): + self.text("* ").line(trait) + else: + category = type(trait[0]).__name__ + self.text("* ").\ + text(category).\ + text(": any of: ").\ + line(", ".join([t.name for t in trait])) + + for trait in habitat.biomeFilter.prohibited: + category = type(trait[0]).__name__ + self.text("* ").text(category).text(": not: ").line(trait.name) + + self.outdent() + + self.text("* seasons: ").line(", ".join([s.name for s in habitat.seasons])) + self.text("* group: ").line(habitat.group.name) + self.text("* location: ").line(habitat.location.name) + self.text("* scarcity: ").line(habitat.scarcity.name) + self.outdent() + + self.outdent() + self.line() diff --git a/tungston/modpack/mysteriousisland/biomecatalog_test.py b/tungston/modpack/mysteriousisland/biomecatalog_test.py new file mode 100644 index 0000000..f13729a --- /dev/null +++ b/tungston/modpack/mysteriousisland/biomecatalog_test.py @@ -0,0 +1,7 @@ +import tungston.modpack.mysteriousisland.biomecatalog + + +# Class ############################################################################################ + +def test_syntax(): + pass diff --git a/tungston/modpack/mysteriousisland/depositcatalog_test.py b/tungston/modpack/mysteriousisland/depositcatalog_test.py new file mode 100644 index 0000000..74f962d --- /dev/null +++ b/tungston/modpack/mysteriousisland/depositcatalog_test.py @@ -0,0 +1,7 @@ +import tungston.modpack.mysteriousisland.depositcatalog + + +# Class ############################################################################################ + +def test_syntax(): + pass diff --git a/tungston/modpack/mysteriousisland/mineralcatalog_test.py b/tungston/modpack/mysteriousisland/mineralcatalog_test.py new file mode 100644 index 0000000..ce62f21 --- /dev/null +++ b/tungston/modpack/mysteriousisland/mineralcatalog_test.py @@ -0,0 +1,7 @@ +import tungston.modpack.mysteriousisland.mineralcatalog + + +# Class ############################################################################################ + +def test_syntax(): + pass diff --git a/tungston/modpack/mysteriousisland/mobcatalog.py b/tungston/modpack/mysteriousisland/mobcatalog.py index e462dcf..4fb78a0 100644 --- a/tungston/modpack/mysteriousisland/mobcatalog.py +++ b/tungston/modpack/mysteriousisland/mobcatalog.py @@ -23,22 +23,22 @@ import tungston.core.season as SE CATALOG = MobCatalog([ MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL), Habitat( - altitudes = AL.LOWLANDS, + altitude = AL.LOWLANDS, biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]), seasons = SE.SUMMER, group = GR.merge(GR.SOLO, GR.PAIR), scarcity = SC.COMMON ).derive( - altitudes = AL.UPLANDS, scarcity = SC.SPARSE, + altitude = AL.UPLANDS, scarcity = SC.SPARSE, ).derive( - altitudes = AL.LOWLANDS, seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON, + altitude = AL.LOWLANDS, seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON, ).derive( - altitudes = AL.UPLANDS, scarcity = SC.UNUSUAL, + altitude = AL.UPLANDS, scarcity = SC.UNUSUAL, ) ), MobPlacement(Mob("black_bear", "bearminimum:black_bear"), Habitat( - altitudes = AL.span(AL.LOWLANDS, AL.ALPINE), + altitude = AL.span(AL.LOWLANDS, AL.ALPINE), biomeFilter = BF([HE.TEMPERATE, FL.FOREST]), seasons = SE.AUTUMN, group = GR.merge(GR.SOLO, GR.FAMILY), @@ -59,7 +59,7 @@ CATALOG = MobCatalog([ ), MobPlacement(Mob("blaze", "minecraft:blaze"), Habitat( - altitudes = AL.PLUTONIC, + altitude = AL.PLUTONIC, location = LO.CAVE, group = GR.SOLO, scarcity = SC.UNCOMMON @@ -68,7 +68,7 @@ CATALOG = MobCatalog([ MobPlacement(Mob("bogged", "minecraft:bogged")), MobPlacement(Mob("brown_bear", "bearminimum:brown_bear"), Habitat( - altitudes = AL.span(AL.LOWLANDS, AL.ALPINE), + altitude = AL.span(AL.LOWLANDS, AL.ALPINE), biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), seasons = SE.AUTUMN, group = GR.SOLO, @@ -82,19 +82,19 @@ CATALOG = MobCatalog([ MobPlacement(Mob("bulwark", "immersiveengineering:bulwark")), MobPlacement(Mob("camel", "minecraft:camel", AC.CREPUSCULAR), Habitat( - altitudes = AL.span(AL.DUNES, AL.LOWLANDS), + altitude = AL.span(AL.DUNES, AL.LOWLANDS), biomeFilter = BF([HE.TROPICAL, HU.DRY, FL.BARREN, SO.SANDY]), - seasons = SE.WET, + seasons = SE.DRY, group = GR.FAMILY, scarcity = SC.UNUSUAL, ).derive( - seasons = SE.DRY, scarcity = SC.RARE + seasons = SE.WET, scarcity = SC.RARE ) ), MobPlacement(Mob("cat", "minecraft:cat")), MobPlacement(Mob("cave_spider", "minecraft:cave_spider"), Habitat( - altitudes = AL.span(AL.OVERBURDEN, AL.HILLS), + altitude = AL.span(AL.OVERBURDEN, AL.HILLS), location = LO.CAVE, group = GR.SOLO, scarcity = SC.UNCOMMON @@ -102,7 +102,7 @@ CATALOG = MobCatalog([ ), MobPlacement(Mob("chameleon", "cold_sweat:chameleon"), Habitat( - altitudes = AL.span(AL.DUNES, AL.UPLANDS), + altitude = AL.span(AL.DUNES, AL.UPLANDS), biomeFilter = BF([HE.TROPICAL, HU.WET, [FL.CANOPY, FL.FOREST]]), seasons = SE.WET, group = GR.merge(GR.SOLO, GR.FAMILY), @@ -119,7 +119,7 @@ CATALOG = MobCatalog([ ), MobPlacement(Mob("chicken", "minecraft:chicken"), Habitat( - altitudes = AL.span(AL.LOWLANDS, AL.UPLANDS), + altitude = AL.span(AL.LOWLANDS, AL.UPLANDS), biomeFilter = BF([HE.TROPICAL, HU.WET, FL.within(FL.CANOPY, FL.CLEARING)]), seasons = SE.SUMMER, group = GR.TROUP, diff --git a/tungston/modpack/mysteriousisland/mobcatalog_test.py b/tungston/modpack/mysteriousisland/mobcatalog_test.py new file mode 100644 index 0000000..9c71fa0 --- /dev/null +++ b/tungston/modpack/mysteriousisland/mobcatalog_test.py @@ -0,0 +1,7 @@ +import tungston.modpack.mysteriousisland.mobcatalog + + +# Class ############################################################################################ + +def test_syntax(): + pass diff --git a/tungston/modpack/mysteriousisland/runner.py b/tungston/modpack/mysteriousisland/runner.py index cf2cfdb..513ecf3 100644 --- a/tungston/modpack/mysteriousisland/runner.py +++ b/tungston/modpack/mysteriousisland/runner.py @@ -7,6 +7,7 @@ from tungston.modpack.mysteriousisland.mobcatalog import CATALOG as mobs from tungston.generator.markdown.reportwriter import ReportWriter from tungston.generator.markdown.biomereport import BiomeReport from tungston.generator.markdown.mineralreport import MineralReport +from tungston.generator.markdown.mobreport import MobReport import sys @@ -23,7 +24,8 @@ class Runner(BaseRunner): def _command_writeReports(self): writer = ReportWriter([ BiomeReport(self.world), - MineralReport(self.world) + MineralReport(self.world), + MobReport(self.world), ]) writer.write(REPORT_PATH)