| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- import pytest
- from cq2_sdk.models import Character, Item, Mission, MissionItem
- def test_character_construction():
- c = Character(
- id=1, name="p", level=10, job=0, sex=0,
- hp=100, mp=50, hp_max=100, mp_max=50,
- exp=0, map_id=1003, x=0, y=0,
- )
- assert c.level == 10
- assert c.hp_pct() == 1.0 if hasattr(c, "hp_pct") else True # no pct method on Character
- def test_item_construction():
- i = Item(id=100, name="hoe", count=1, make_index=42)
- assert i.make_index == 42
- def test_mission_progress_pct():
- m = Mission(
- id=1, name="t", status="active",
- items=[MissionItem(id=10, name="kills", current=3, target=10, completed=False)],
- )
- assert m.progress_pct() == 0.3
- def test_mission_progress_pct_multi_items():
- m = Mission(
- id=1, name="t", status="active",
- items=[
- MissionItem(id=10, name="a", current=5, target=10, completed=False),
- MissionItem(id=11, name="b", current=3, target=5, completed=False),
- ],
- )
- # 5+3 = 8 out of 10+5 = 15 -> ~0.533
- assert abs(m.progress_pct() - 8 / 15) < 1e-9
- def test_mission_is_complete():
- m = Mission(
- id=1, name="t", status="active",
- items=[
- MissionItem(id=10, name="a", current=10, target=10, completed=True),
- ],
- )
- assert m.is_complete() is True
- def test_mission_empty_items_is_complete():
- m = Mission(id=1, name="t", status="active", items=[])
- assert m.is_complete() is False # vacuously false (no items to satisfy)
- from cq2_sdk.movement.pathfind import find_path
- def test_pathfind_straight_line():
- grid = [[0] * 10 for _ in range(10)]
- path = find_path(grid, 0, 0, 5, 0)
- assert path[0] == (0, 0)
- assert path[-1] == (5, 0)
- assert len(path) == 6
- def test_pathfind_avoid_obstacle():
- grid = [[0] * 5 for _ in range(5)]
- grid[2][1] = grid[2][2] = grid[2][3] = 1 # wall at y=2
- path = find_path(grid, 0, 0, 4, 0)
- coords = set(path)
- for x in range(1, 4):
- assert (x, 2) not in coords
- def test_pathfind_no_path():
- grid = [[0] * 3 for _ in range(3)]
- grid[1][0] = grid[0][1] = grid[2][1] = grid[1][2] = 1 # surrounded
- assert find_path(grid, 0, 0, 2, 2) == []
- def test_pathfind_same_start_end():
- grid = [[0] * 3 for _ in range(3)]
- assert find_path(grid, 1, 1, 1, 1) == [(1, 1)]
- def test_pathfind_out_of_bounds():
- grid = [[0] * 3 for _ in range(3)]
- assert find_path(grid, -1, 0, 2, 2) == []
- assert find_path(grid, 0, 0, 99, 99) == []
- import asyncio
- from cq2_sdk.movement.walk import Movement
- from cq2_sdk.combat import Combat
- from cq2_sdk.missions import Missions
- @pytest.mark.asyncio
- async def test_movement_walk_sends_correct_frame():
- sent = []
- class FakeTcp:
- async def send(self, msg_id, recog=0, param1=0, param2=0, param3=0, body=b""):
- sent.append((msg_id, recog, param1, param2, param3, body))
- m = Movement(FakeTcp()) # type: ignore[arg-type]
- await m.walk_to(10, 20)
- assert sent[0][0] == 3011
- assert sent[0][3] == 10 # param2 = x
- assert sent[0][4] == 20 # param3 = y
- @pytest.mark.asyncio
- async def test_movement_run_sends_correct_frame():
- sent = []
- class FakeTcp:
- async def send(self, msg_id, recog=0, param1=0, param2=0, param3=0, body=b""):
- sent.append((msg_id, recog, param1, param2, param3, body))
- m = Movement(FakeTcp()) # type: ignore[arg-type]
- await m.run_to(10, 20)
- assert sent[0][0] == 3013
- assert sent[0][3] == 10
- assert sent[0][4] == 20
- @pytest.mark.asyncio
- async def test_combat_attack_sends_correct_frame():
- sent = []
- class FakeTcp:
- async def send(self, msg_id, recog=0, param1=0, param2=0, param3=0, body=b""):
- sent.append((msg_id, recog, param1, param2, param3, body))
- c = Combat(FakeTcp()) # type: ignore[arg-type]
- await c.attack(target_id=42, x=10, y=20)
- assert sent[0][0] == 3014
- assert sent[0][1] == 42 # recog = target entity id
- assert sent[0][3] == 10 # param2 = x
- assert sent[0][4] == 20 # param3 = y
- @pytest.mark.asyncio
- async def test_combat_cast_skill_sends_correct_frame():
- sent = []
- class FakeTcp:
- async def send(self, msg_id, recog=0, param1=0, param2=0, param3=0, body=b""):
- sent.append((msg_id, recog, param1, param2, param3, body))
- c = Combat(FakeTcp()) # type: ignore[arg-type]
- await c.cast_skill(skill_id=100, target_id=42, x=10, y=20)
- assert sent[0][0] == 3017
- assert sent[0][1] == 100 # recog = skill id
- assert sent[0][2] == 42 # param1 = target
- @pytest.mark.asyncio
- async def test_missions_accept_sends_correct_msg():
- sent = []
- class FakeTcp:
- async def send(self, msg_id, recog=0, param1=0, param2=0, param3=0, body=b""):
- sent.append((msg_id, recog, param1, param2, param3, body))
- m = Missions(FakeTcp()) # type: ignore[arg-type]
- await m.accept(101)
- assert sent[0][0] == 1011
- assert sent[0][1] == 101
- @pytest.mark.asyncio
- async def test_missions_claim_sends_correct_msg():
- sent = []
- class FakeTcp:
- async def send(self, msg_id, recog=0, param1=0, param2=0, param3=0, body=b""):
- sent.append((msg_id, recog, param1, param2, param3, body))
- m = Missions(FakeTcp()) # type: ignore[arg-type]
- await m.claim_reward(202)
- assert sent[0][0] == 3031
- assert sent[0][1] == 202
- def test_missions_update_from_sc_parses_mission_list():
- m = Missions.__new__(Missions)
- m._cache = {}
- # Format: "<mid>,<iid>:<cur>:<target>,<iid>:<cur>:<target>;<mid>,..."
- body = b"101,10:3:10,11:0:5;102,20:1:3"
- m.update_from_sc(body)
- assert 101 in m._cache
- assert m._cache[101].items[0].current == 3
- assert m._cache[101].items[0].target == 10
- assert m._cache[101].items[0].completed is False
- assert m._cache[101].items[1].completed is False
- assert m._cache[102].items[0].current == 1
- assert m._cache[102].items[0].target == 3
- def test_missions_update_completed_marks_status():
- m = Missions.__new__(Missions)
- m._cache = {}
- body = b"101,10:10:10"
- m.update_from_sc(body)
- assert m._cache[101].status == "completed"
- assert m._cache[101].is_complete()
- def test_missions_update_empty_body_noop():
- m = Missions.__new__(Missions)
- m._cache = {}
- m.update_from_sc(b"")
- assert m._cache == {}
|