worldhistory

git clone https://git.godosa.eu/worldhistory

master

raw · 4440 bytes

import unittest

import numpy as np

from tests.helpers import fields, line_world, make_history, make_race
from worldhistory.events import apply_event, cull, era_switch, seed
from worldhistory.regions import Regions
from worldhistory.state import new_state


class EventTest(unittest.TestCase):
    def test_seed_totals_and_fringe(self):
        w = line_world(200)
        r = make_race(seed={"clusters": 20, "heads": 100})
        q = np.linspace(0, 1, 200)[None]
        st = new_state(1, 200, np.zeros((1, 6)), seed=0)
        placed = seed(st, w, [r], q, np.ones((1, 200), bool), 0.25, np.random.default_rng(0))
        self.assertAlmostEqual(float(st.P.sum()), 2000.0)
        cells = placed["a"]
        fringe_cells = [c for c in cells if 0.05 < q[0, c] < 0.3]
        self.assertGreaterEqual(len(fringe_cells), 5)                     # 25 % of 20 on the fringe
        self.assertEqual(float(st.P[0, 0]), 0.0)                          # q = 0: never

    def test_seed_realm_land_skips_sea(self):
        ocean = np.arange(200) >= 100                                     # right half is sea, and the best q
        w = line_world(200, ocean=ocean)
        r = make_race(seed={"clusters": 20, "heads": 100, "realm": "land"}, habitat={"realm": "both"})
        q = np.linspace(0.1, 1, 200)[None]
        st = new_state(1, 200, np.zeros((1, 6)), seed=0)
        placed = seed(st, w, [r], q, np.ones((1, 200), bool), 0.25, np.random.default_rng(0))
        self.assertTrue(placed["a"])
        self.assertTrue(all(c < 100 for c in placed["a"]))

    def test_cull_exact_and_by_race(self):
        rs = [make_race("a"), make_race("b")]
        st = new_state(2, 3, np.zeros((2, 6)), seed=0)
        st.P[:] = 100.0
        cull(st, rs, np.array([True, True, False]), 0.6, {"b": 0.8})
        np.testing.assert_allclose(st.P, [[40, 40, 100], [20, 20, 100]])

    def test_cull_noise(self):
        w = line_world(500)
        st = new_state(1, 500, np.zeros((1, 6)), seed=0)
        st.P[:] = 100.0
        cull(st, [make_race()], np.ones(500, bool), 0.3, {}, noise=w.noise(1), amp=0.15)
        self.assertAlmostEqual(float(st.P.mean()), 70.0, delta=2.0)
        self.assertGreater(float(st.P.std()), 5.0)

    def test_era_switch_drowns_land_races(self):
        w = line_world(3)
        w.eras["late"] = fields(3, ocean=[False, True, True])
        land, sea = make_race("l"), make_race("s", habitat={"realm": "sea", "terms": [{"p": "sea", "w": 1}]})
        st = new_state(2, 3, np.zeros((2, 6)), seed=0)
        st.P[0] = 10.0
        st.P[1, 2] = 5.0
        era_switch(st, w, [land, sea], "late")
        np.testing.assert_array_equal(st.P[0], [10, 0, 0])
        np.testing.assert_array_equal(st.P[1], [0, 0, 5])
        self.assertEqual(w.era, "late")

    def test_targeted_seed_places_one_race_in_region(self):
        w = line_world(200)                                               # lon 0 .. ~178°, 0.9° apart
        h = make_history(regions={"west": {"kind": "box", "lat": [-1, 1], "lon": [-1, 45]}},
                         event=[{"year": 0, "kind": "seed", "race": "b", "region": "west", "clusters": 3,
                                 "heads": 50}])
        rs = [make_race("a", seed={"clusters": 5, "heads": 100}), make_race("b", seed={"clusters": 5, "heads": 100})]
        q = np.ones((2, 200)) * 0.5
        st = new_state(2, 200, np.zeros((2, 6)), seed=0)
        log = apply_event(st, w, rs, h.events[0], Regions(w, h.regions), q, np.ones((2, 200), bool), h, 0)
        self.assertEqual(float(st.P[0].sum()), 0.0)                       # race a: untouched
        self.assertAlmostEqual(float(st.P[1].sum()), 150.0)               # 3 clusters × 50
        west = np.flatnonzero(w.lon <= 45)
        self.assertTrue(set(np.flatnonzero(st.P[1])) <= set(west))
        self.assertEqual(len(log["placed"]["b"]), 3)

    def test_apply_event_log(self):
        w = line_world(2)
        h = make_history(regions={"west": {"kind": "box", "lat": [-1, 1], "lon": [-1, 0.5]}},
                         event=[{"year": 20, "kind": "die_off", "region": "west", "share": 0.9}])
        st = new_state(1, 2, np.zeros((1, 6)), seed=0)
        st.P[:] = 100.0
        log = apply_event(st, w, [make_race()], h.events[0], Regions(w, h.regions), None, None, h, 0)
        np.testing.assert_allclose(st.P[0], [10, 100])
        self.assertEqual(log["before"]["a"], 200.0)
        self.assertEqual(log["after"]["a"], 110.0)