Files
tiny_tackle_heroes/Assets/_Project/Tests/PlayMode/Defense25DPersonalMissionPlayModeTests.cs
T
2026-09-28 11:07:17 +09:00

203 lines
9.6 KiB
C#

using System.Collections.Generic;
using System.Linq;
using BumpCombat.Defense;
using BumpCombat.Defense.Comparison;
using NUnit.Framework;
namespace BumpCombat.PlayModeTests
{
public sealed class Defense25DPersonalMissionPlayModeTests
{
private readonly List<int> openPortalIds = new();
private readonly List<Defense25DPersonalMissionSpawnRequest> spawnedRequests = new();
private readonly List<string> queuedRewardTokens = new();
private Defense25DPersonalMissions missions;
private bool runCanAcceptMissions;
private bool allowRewardQueue;
private int nextSpawnId;
[SetUp]
public void SetUp()
{
openPortalIds.Clear();
spawnedRequests.Clear();
queuedRewardTokens.Clear();
runCanAcceptMissions = true;
allowRewardQueue = true;
nextSpawnId = 100;
missions = new Defense25DPersonalMissions();
missions.Bind(
new[] { 3, 6, 3 },
() => runCanAcceptMissions,
() => openPortalIds,
SpawnTargets,
QueueReward);
missions.Reset(7, 12345);
}
[Test]
public void StartRequiresEnoughOpenPortalsAndRejectsConcurrentMission()
{
openPortalIds.AddRange(new[] { 2, 0, 2 });
Assert.That(missions.CanStart(1, out string reason), Is.False);
Assert.That(reason, Does.Contain("3"));
Assert.That(missions.TryStart(1), Is.False);
Assert.That(spawnedRequests, Is.Empty);
openPortalIds.AddRange(new[] { 1, 3 });
Assert.That(missions.TryStart(1), Is.True);
Assert.That(spawnedRequests, Has.Count.EqualTo(3));
Assert.That(spawnedRequests.Select(request => request.PortalId).Distinct().Count(), Is.EqualTo(3));
Assert.That(spawnedRequests.All(request =>
request.RunGeneration == 7
&& request.MissionId == 1
&& request.MissionInstanceId == 1
&& request.Source == Defense25DSpawnSource.PersonalMission), Is.True);
Assert.That(missions.TryStart(2), Is.False);
}
[Test]
public void MissionTargetsAreThreeSixAndThreeAndOnlyDeathsQueueOneReward()
{
for (int missionId = 1; missionId <= 3; missionId++)
{
openPortalIds.Clear();
for (int portalId = 0; portalId < 6; portalId++)
openPortalIds.Add(portalId);
int firstSpawnIndex = spawnedRequests.Count;
Assert.That(missions.TryStart(missionId), Is.True);
int targetCount = new[] { 3, 6, 3 }[missionId - 1];
IReadOnlyList<int> targetIds = missions.States[missionId - 1].TargetSpawnIds;
Assert.That(targetIds, Has.Count.EqualTo(targetCount));
for (int i = 0; i < targetIds.Count - 1; i++)
{
Assert.That(missions.ResolveTarget(7, targetIds[i], Defense25DSpawnSource.PersonalMission,
missionId, missions.States[missionId - 1].MissionInstanceId, DefenseEnemyResolution.Death), Is.True);
Assert.That(missions.States[missionId - 1].Status, Is.EqualTo(Defense25DPersonalMissionStatus.Active));
}
Assert.That(missions.ResolveTarget(7, targetIds[targetIds.Count - 1],
Defense25DSpawnSource.PersonalMission, missionId,
missions.States[missionId - 1].MissionInstanceId, DefenseEnemyResolution.Death), Is.True);
Assert.That(missions.States[missionId - 1].Status, Is.EqualTo(Defense25DPersonalMissionStatus.RewardPending));
Assert.That(missions.ResolveTarget(7, targetIds[0], DefenseEnemyResolution.Death), Is.False);
Assert.That(queuedRewardTokens, Has.Count.EqualTo(missionId));
Assert.That(queuedRewardTokens[missionId - 1], Is.EqualTo($"personal-mission:7:{missionId}"));
if (missionId < 3)
Assert.That(missions.TryStart(missionId + 1), Is.False);
Assert.That(missions.TryCompleteReward(7, missions.States[missionId - 1].MissionInstanceId), Is.True);
Assert.That(missions.States[missionId - 1].Status, Is.EqualTo(Defense25DPersonalMissionStatus.Completed));
Assert.That(missions.TryCompleteReward(7, missions.States[missionId - 1].MissionInstanceId), Is.False);
Assert.That(spawnedRequests.Skip(firstSpawnIndex).Take(targetCount)
.Select(request => request.PortalId).Distinct().Count(), Is.EqualTo(targetCount));
}
}
[Test]
public void RewardQueueFailureStaysPendingUntilQueuedAndChoiceIsConfirmed()
{
openPortalIds.AddRange(Enumerable.Range(0, 3));
Assert.That(missions.TryStart(1), Is.True);
Defense25DPersonalMissionState mission = missions.States[0];
allowRewardQueue = false;
foreach (int spawnId in mission.TargetSpawnIds)
Assert.That(missions.ResolveTarget(7, spawnId, DefenseEnemyResolution.Death), Is.True);
Assert.That(mission.Status, Is.EqualTo(Defense25DPersonalMissionStatus.RewardPending));
Assert.That(mission.RewardQueued, Is.False);
Assert.That(queuedRewardTokens, Is.Empty);
Assert.That(missions.TryCompleteReward(7, mission.MissionInstanceId), Is.False);
allowRewardQueue = true;
Assert.That(missions.TryQueuePendingReward(7, mission.MissionInstanceId), Is.True);
Assert.That(queuedRewardTokens, Has.Count.EqualTo(1));
Assert.That(missions.TryQueuePendingReward(7, mission.MissionInstanceId), Is.False);
Assert.That(mission.Status, Is.EqualTo(Defense25DPersonalMissionStatus.RewardPending));
Assert.That(missions.TryStart(2), Is.False);
Assert.That(missions.TryCompleteReward(7, mission.MissionInstanceId), Is.True);
Assert.That(mission.Status, Is.EqualTo(Defense25DPersonalMissionStatus.Completed));
}
[Test]
public void ArrivalFailsImmediatelyAndDoesNotResolveRemainingEnemiesOrReward()
{
openPortalIds.AddRange(Enumerable.Range(0, 3));
Assert.That(missions.TryStart(1), Is.True);
IReadOnlyList<int> targets = missions.States[0].TargetSpawnIds;
Assert.That(missions.ResolveTarget(7, targets[0], DefenseEnemyResolution.Arrival), Is.True);
Assert.That(missions.States[0].Status, Is.EqualTo(Defense25DPersonalMissionStatus.Failed));
Assert.That(missions.States[0].RemainingTargetCount, Is.EqualTo(2));
Assert.That(missions.ResolveTarget(7, targets[1], DefenseEnemyResolution.Death), Is.True);
Assert.That(missions.States[0].RemainingTargetCount, Is.EqualTo(1));
Assert.That(queuedRewardTokens, Is.Empty);
}
[Test]
public void UnownedGlobalEliteAndBossSummonIdsCannotCountAsMissionTargets()
{
openPortalIds.AddRange(Enumerable.Range(0, 3));
Assert.That(missions.TryStart(1), Is.True);
Defense25DPersonalMissionState mission = missions.States[0];
int globalEliteId = mission.TargetSpawnIds[0];
int bossSummonId = mission.TargetSpawnIds[1];
Assert.That(missions.ResolveTarget(7, globalEliteId, Defense25DSpawnSource.GlobalElite,
1, mission.MissionInstanceId, DefenseEnemyResolution.Death), Is.False);
Assert.That(missions.ResolveTarget(7, bossSummonId, Defense25DSpawnSource.BossSummon,
1, mission.MissionInstanceId, DefenseEnemyResolution.Death), Is.False);
Assert.That(missions.States[0].RemainingTargetCount, Is.EqualTo(3));
Assert.That(queuedRewardTokens, Is.Empty);
Assert.That(spawnedRequests.All(request => request.Source == Defense25DSpawnSource.PersonalMission), Is.True);
}
[Test]
public void ResetClearsMissionOwnershipAndRejectsStaleGenerationCallbacks()
{
openPortalIds.AddRange(Enumerable.Range(0, 3));
Assert.That(missions.TryStart(1), Is.True);
int staleSpawnId = missions.States[0].TargetSpawnIds[0];
missions.Reset(8, 54321);
Assert.That(missions.Generation, Is.EqualTo(8));
Assert.That(missions.States.All(state => state.Status == Defense25DPersonalMissionStatus.Available), Is.True);
Assert.That(missions.ResolveTarget(7, staleSpawnId, DefenseEnemyResolution.Death), Is.False);
Assert.That(missions.TryCompleteReward(7, 1), Is.False);
Assert.That(queuedRewardTokens, Is.Empty);
Assert.That(missions.TryStart(1), Is.True);
Assert.That(missions.States[0].MissionInstanceId, Is.EqualTo(1));
Assert.That(missions.States[0].TargetSpawnIds[0], Is.Not.EqualTo(staleSpawnId));
}
private bool SpawnTargets(
IReadOnlyList<Defense25DPersonalMissionSpawnRequest> requests,
out IReadOnlyList<int> spawnIds)
{
var ids = new List<int>(requests.Count);
foreach (Defense25DPersonalMissionSpawnRequest request in requests)
{
spawnedRequests.Add(request);
ids.Add(nextSpawnId++);
}
spawnIds = ids;
return true;
}
private bool QueueReward(string token)
{
if (!allowRewardQueue)
return false;
queuedRewardTokens.Add(token);
return true;
}
}
}