Files
Flora/tests/test_extraction.py

230 lines
9.7 KiB
Python

import os
import pathlib
import tempfile
import unittest
os.environ.setdefault("SDL_VIDEODRIVER", "dummy")
import engine.collection as collection
from engine.plants import POOL, make
from engine.unit import TEAM_PLAYER
class ExtractionTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._orig = collection._DATA_FILE
fd, cls._path = tempfile.mkstemp(suffix=".json")
os.close(fd)
collection._DATA_FILE = pathlib.Path(cls._path)
@classmethod
def tearDownClass(cls):
collection._DATA_FILE = cls._orig
if os.path.exists(cls._path):
os.unlink(cls._path)
def setUp(self):
data = collection.load()
data["owned"] = ["Lavender", "Zinnia", "Marigold", "Sunflower", "Hydrangea", "Hellebore"]
for n in data["owned"]:
data["progress"].setdefault(n, {"level": 1, "stage": 1, "xp": 0,
"duplicates": 0, "watered_at": 0})
data["extracted"] = []
for n in data["owned"]:
data["progress"][n].pop("injected", None)
collection.save(data)
def _maxed(self, name):
data = collection.load()
data["progress"][name]["level"] = 50
data["progress"][name]["stage"] = 3
collection.save(data)
def test_extraction_requires_maxed(self):
self.assertNotEqual(collection.can_extract("Lavender"), "")
self._maxed("Lavender")
self.assertEqual(collection.can_extract("Lavender"), "")
def test_extract_excludes_basic_and_blocks_inject_of_self_type(self):
self._maxed("Lavender")
idxs = [i for i, _ in collection.extractable_skills("Lavender")]
self.assertTrue(all(i > 0 for i in idxs))
def test_hydrangea_has_no_extractable_abilities(self):
self._maxed("Hydrangea")
self.assertEqual(collection.extractable_skills("Hydrangea"), [])
self.assertNotEqual(collection.can_extract("Hydrangea"), "")
def test_extract_resets_plant_and_stores_ability(self):
self._maxed("Lavender")
idx, sk = collection.extractable_skills("Lavender")[0]
self.assertTrue(collection.extract_skill("Lavender", idx))
prog = collection.load()["progress"]["Lavender"]
self.assertEqual(prog["level"], 1)
self.assertEqual(prog["stage"], 1)
ext = collection.extracted_skills()
self.assertEqual(len(ext), 1)
self.assertEqual(ext[0]["skill_name"], sk.name)
self.assertEqual(ext[0]["role"], POOL["Lavender"]["role"])
# extraction again is blocked (no longer maxed)
self.assertNotEqual(collection.can_extract("Lavender"), "")
def test_inject_requires_same_role_and_is_single_use(self):
self._maxed("Lavender")
idx, _ = collection.extractable_skills("Lavender")[0]
collection.extract_skill("Lavender", idx)
rec = collection.extracted_skills()[0]
self.assertNotEqual(collection.can_inject("Marigold", rec), "") # tank
self.assertEqual(collection.can_inject("Zinnia", rec), "") # attacker
self.assertTrue(collection.inject_skill(0, "Zinnia", 1))
self.assertEqual(collection.extracted_skills(), []) # consumed
# one injected ability per plant
self.assertNotEqual(collection.can_inject("Zinnia", rec), "")
self.assertFalse(collection.inject_skill(0, "Zinnia", 2))
def test_unit_uses_injected_skill_and_remove_reverts(self):
self._maxed("Lavender")
idx, sk = collection.extractable_skills("Lavender")[0]
collection.extract_skill("Lavender", idx)
collection.inject_skill(0, "Zinnia", 1)
unit = make("Zinnia", TEAM_PLAYER)
self.assertEqual(unit.skills[1].name, sk.name)
self.assertEqual(unit.skills[0].name, POOL["Zinnia"]["skills"][0].name)
self.assertTrue(collection.remove_injection("Zinnia"))
unit = make("Zinnia", TEAM_PLAYER)
self.assertEqual(unit.skills[1].name, POOL["Zinnia"]["skills"][1].name)
def test_madness_is_not_extractable(self):
self._maxed("Hellebore")
names = [sk.name for _, sk in collection.extractable_skills("Hellebore")]
self.assertNotIn("Madness", names)
idx = POOL["Hellebore"]["skills"].index(next(s for s in POOL["Hellebore"]["skills"]
if s.name == "Madness"))
self.assertFalse(collection.extract_skill("Hellebore", idx))
def test_inject_cannot_replace_same_ability(self):
from engine.skills import skill_to_dict
data = collection.load()
data["extracted"] = [{
"source": "Lavender", "role": "attacker",
"skill_name": "Glitter", "skill": skill_to_dict(POOL["Zinnia"]["skills"][1]),
}]
collection.save(data)
rec = collection.extracted_skills()[0]
# Zinnia's 2nd skill IS Glitter -> cannot replace it with Glitter
self.assertNotEqual(collection.injection_slot_reason("Zinnia", rec, 1), "")
self.assertFalse(collection.inject_skill(0, "Zinnia", 1))
# its 3rd skill (Glimmer) is fine
self.assertEqual(collection.injection_slot_reason("Zinnia", rec, 2), "")
self.assertTrue(collection.inject_skill(0, "Zinnia", 2))
class FertilizerRewardTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._orig = collection._DATA_FILE
fd, cls._path = tempfile.mkstemp(suffix=".json")
os.close(fd)
collection._DATA_FILE = pathlib.Path(cls._path)
@classmethod
def tearDownClass(cls):
collection._DATA_FILE = cls._orig
if os.path.exists(cls._path):
os.unlink(cls._path)
def test_win_grants_fertilizer_not_water(self):
data = collection.load()
data["owned"] = ["Lavender", "Marigold", "Sunflower", "Zinnia"]
for n in data["owned"]:
data["progress"].setdefault(n, {"level": 1, "stage": 1, "xp": 0,
"duplicates": 0, "watered_at": 0})
data["water"] = 0
data["fertilizer"] = 0
collection.save(data)
collection.grant_xp(["Lavender"], 40, count_battle=True, fertilizer=3)
self.assertEqual(collection.available_fertilizer(), 3)
self.assertEqual(collection.available_water(), 0)
def test_win_fertilizer_scales_with_floor(self):
data = collection.load()
data["owned"] = ["Lavender", "Marigold", "Sunflower", "Zinnia"]
for n in data["owned"]:
data["progress"].setdefault(n, {"level": 1, "stage": 1, "xp": 0,
"duplicates": 0, "watered_at": 0})
data["fertilizer"] = 0
collection.save(data)
# floor 1 -> 1 fertilizer, floor 5 -> 5
collection.grant_xp(["Lavender"], 40, count_battle=True, fertilizer=1)
collection.grant_xp(["Lavender"], 40, count_battle=True, fertilizer=5)
self.assertEqual(collection.available_fertilizer(), 6)
def test_water_still_levels_plants(self):
data = collection.load()
data["owned"] = ["Lavender", "Marigold", "Sunflower", "Zinnia"]
for n in data["owned"]:
data["progress"].setdefault(n, {"level": 1, "stage": 1, "xp": 0,
"duplicates": 0, "watered_at": 0})
data["water"] = 3
collection.save(data)
collection.water("Lavender")
self.assertEqual(collection.get_progress("Lavender")["level"], 2)
self.assertEqual(collection.available_water(), 2)
def test_smart_water_candidate(self):
data = collection.load()
data["owned"] = ["Lavender", "Marigold", "Sunflower", "Zinnia"]
for n in data["owned"]:
data["progress"].setdefault(n, {"level": 1, "stage": 1, "xp": 0,
"duplicates": 0, "watered_at": 0})
data["progress"]["Marigold"]["duplicates"] = 5 # >= 2 needed for stage 2
collection.save(data)
self.assertTrue(collection.smart_water_candidate("Marigold"))
data = collection.load()
data["progress"]["Marigold"]["level"] = 10 # already at the milestone
collection.save(data)
self.assertFalse(collection.smart_water_candidate("Marigold"))
class StarterPackTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._orig = collection._DATA_FILE
fd, cls._path = tempfile.mkstemp(suffix=".json")
os.close(fd)
collection._DATA_FILE = pathlib.Path(cls._path)
@classmethod
def tearDownClass(cls):
collection._DATA_FILE = cls._orig
if os.path.exists(cls._path):
os.unlink(cls._path)
def setUp(self):
if collection._DATA_FILE.exists():
collection._DATA_FILE.unlink()
def test_init_starter_pinwheel(self):
self.assertFalse(collection.save_exists())
self.assertFalse(collection.init_starter_pinwheel("nope"))
self.assertTrue(collection.init_starter_pinwheel("radiant"))
self.assertTrue(collection.save_exists())
data = collection.load()
self.assertEqual(set(data["owned"]), {"Pinwheel"})
self.assertEqual(data["progress"]["Pinwheel"]["type"], "radiant")
self.assertEqual(data["progress"]["Pinwheel"]["level"], 1)
self.assertEqual(data["progress"]["Pinwheel"]["stage"], 1)
self.assertEqual(data["progress"]["Pinwheel"]["duplicates"], 0)
def test_every_type_can_start(self):
from engine.types import ALL_TYPES
for pt in ALL_TYPES:
if collection._DATA_FILE.exists():
collection._DATA_FILE.unlink()
self.assertTrue(collection.init_starter_pinwheel(pt))
self.assertEqual(collection.load()["progress"]["Pinwheel"]["type"], pt)
if __name__ == "__main__":
unittest.main()