230 lines
9.7 KiB
Python
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() |