Intercept also works when the vanguard is attacked
Removed the rear-guard-only restriction. Interceptor resolution now runs before the vanguard damage branch, so a successful intercept retires the interceptor and the vanguard takes no damage. The attacked rear-guard still cannot intercept itself. Two tests.
This commit is contained in:
parent
fdc21c8a26
commit
4dd96e6f02
|
|
@ -12,8 +12,9 @@ namespace Vanguard.Rules.Engine;
|
||||||
/// * поддержка работает как отдельная способность: карты 0 и 1 ранга могут передать
|
/// * поддержка работает как отдельная способность: карты 0 и 1 ранга могут передать
|
||||||
/// свою силу атакующему Арьергарду из той же колонны, сила действует только в этом бою;
|
/// свою силу атакующему Арьергарду из той же колонны, сила действует только в этом бою;
|
||||||
/// * перехват — отдельная способность карт 2 ранга: карта из переднего ряда выходит
|
/// * перехват — отдельная способность карт 2 ранга: карта из переднего ряда выходит
|
||||||
/// в круг защиты, и сила атаки сравнивается с ней; из заднего ряда —
|
/// в круг защиты и при атаке по Авангарду, и при атаке по Арьергарду;
|
||||||
/// только если эффект разрешил (InterceptFromBackRow);
|
/// атакованный Арьергард не может перехватить атаку на самого себя;
|
||||||
|
/// из заднего ряда — только если эффект разрешил (InterceptFromBackRow);
|
||||||
/// * триггер требует выбора целей через ResolveTriggerCommand:
|
/// * триггер требует выбора целей через ResolveTriggerCommand:
|
||||||
/// +5000 любой карте в кругах Авангарда или Арьергарда, затем второй эффект;
|
/// +5000 любой карте в кругах Авангарда или Арьергарда, затем второй эффект;
|
||||||
/// правило одинаково для drive check и damage check;
|
/// правило одинаково для drive check и damage check;
|
||||||
|
|
@ -373,9 +374,6 @@ public sealed class GameEngine
|
||||||
if (State.ActivePlayer != defenderIndex)
|
if (State.ActivePlayer != defenderIndex)
|
||||||
return CommandResult.Reject("Перехватывает только обороняющийся.");
|
return CommandResult.Reject("Перехватывает только обороняющийся.");
|
||||||
|
|
||||||
if (battle.TargetSlot < 0)
|
|
||||||
return CommandResult.Reject("Перехват возможен только при атаке по Арьергарду.");
|
|
||||||
|
|
||||||
if (battle.Interceptor is not null)
|
if (battle.Interceptor is not null)
|
||||||
return CommandResult.Reject("Перехват уже объявлен.");
|
return CommandResult.Reject("Перехват уже объявлен.");
|
||||||
|
|
||||||
|
|
@ -647,16 +645,17 @@ public sealed class GameEngine
|
||||||
|
|
||||||
if (hit)
|
if (hit)
|
||||||
{
|
{
|
||||||
if (battle.TargetSlot < 0)
|
if (battle.Interceptor is not null)
|
||||||
|
{
|
||||||
|
// перехватчик уже вышел из круга и уйдёт в сброс при закрытии боя,
|
||||||
|
// первоначальная цель (Авангард или Арьергард) не страдает
|
||||||
|
_events.Add(new InterceptorRetiredEvent(defenderIndex, battle.Interceptor.PrintingId));
|
||||||
|
}
|
||||||
|
else if (battle.TargetSlot < 0)
|
||||||
{
|
{
|
||||||
var damage = attackerDef.Critical + attacker.TemporaryCritical;
|
var damage = attackerDef.Critical + attacker.TemporaryCritical;
|
||||||
DealDamage(defenderIndex, damage);
|
DealDamage(defenderIndex, damage);
|
||||||
}
|
}
|
||||||
else if (battle.Interceptor is not null)
|
|
||||||
{
|
|
||||||
// перехватчик уже вышел из круга и уйдёт в сброс при закрытии боя
|
|
||||||
_events.Add(new InterceptorRetiredEvent(defenderIndex, battle.Interceptor.PrintingId));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
State.Players[defenderIndex].RearGuards[battle.TargetSlot] = null;
|
State.Players[defenderIndex].RearGuards[battle.TargetSlot] = null;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ public class GameEngineTests
|
||||||
private const string Govannon = "BT01/045EN"; // Draw
|
private const string Govannon = "BT01/045EN"; // Draw
|
||||||
private const string Iseult = "BT01/011EN"; // Sentinel, Royal Paladin
|
private const string Iseult = "BT01/011EN"; // Sentinel, Royal Paladin
|
||||||
private const string Nehalem = "BT01/022EN"; // Kagero
|
private const string Nehalem = "BT01/022EN"; // Kagero
|
||||||
|
private const string Overlord = "BT01/004EN"; // Kagero, 11000
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Start_Places_Starting_Vanguard_And_Draws_Five()
|
public void Start_Places_Starting_Vanguard_And_Draws_Five()
|
||||||
|
|
@ -382,6 +383,37 @@ public class GameEngineTests
|
||||||
Assert.True(engine.Execute(new InterceptCommand(1)).Accepted);
|
Assert.True(engine.Execute(new InterceptCommand(1)).Accepted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Intercept_Works_Against_Vanguard_Attack()
|
||||||
|
{
|
||||||
|
var engine = StartedEngine();
|
||||||
|
engine.Execute(new SkipRideCommand());
|
||||||
|
SetVanguard(engine, 0, Overlord);
|
||||||
|
StackDeck(engine.State.Players[0], Gallatin, Gallatin);
|
||||||
|
engine.Execute(new EnterBattleCommand());
|
||||||
|
|
||||||
|
var defender = engine.State.Players[1];
|
||||||
|
defender.RearGuards[3] = TakeFromDeck(defender, Gallatin);
|
||||||
|
|
||||||
|
Assert.True(engine.Execute(new AttackCommand(-1, -1)).Accepted);
|
||||||
|
Assert.True(engine.Execute(new InterceptCommand(3)).Accepted);
|
||||||
|
Assert.True(engine.Execute(new PassGuardCommand()).Accepted);
|
||||||
|
|
||||||
|
Assert.Empty(defender.Damage);
|
||||||
|
Assert.NotNull(defender.Vanguard);
|
||||||
|
Assert.Contains(defender.Drop, c => c.PrintingId == Gallatin);
|
||||||
|
Assert.Contains(engine.Events, e => e is InterceptorRetiredEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Attacked_RearGuard_Cannot_Intercept_Itself()
|
||||||
|
{
|
||||||
|
var engine = ReadyToAttackRearGuard();
|
||||||
|
|
||||||
|
Assert.True(engine.Execute(new AttackCommand(3, 0)).Accepted);
|
||||||
|
Assert.False(engine.Execute(new InterceptCommand(0)).Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ResolveTrigger_Rejects_When_Nothing_Is_Pending()
|
public void ResolveTrigger_Rejects_When_Nothing_Is_Pending()
|
||||||
{
|
{
|
||||||
|
|
@ -493,7 +525,7 @@ public class GameEngineTests
|
||||||
|
|
||||||
private List<string> BuildDeck()
|
private List<string> BuildDeck()
|
||||||
{
|
{
|
||||||
var mustInclude = new[] { Barcgal, Marron, Gallatin, Alfred, Nike, Flogal, Govannon, Iseult, Nehalem };
|
var mustInclude = new[] { Barcgal, Marron, Gallatin, Alfred, Nike, Flogal, Govannon, Iseult, Nehalem, Overlord };
|
||||||
var names = mustInclude
|
var names = mustInclude
|
||||||
.Select(_catalog.CardOf)
|
.Select(_catalog.CardOf)
|
||||||
.Select(c => c.NameId)
|
.Select(c => c.NameId)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue