Skip to content

Commit

Permalink
Added ForceAttack behavior; TacticalPhase will check whether the Forc…
Browse files Browse the repository at this point in the history
…eAttack is present on any attacker candidates; if it is, Pass is disabled as a response;

Implemented Abort respond to quit a Game failed; used it to implement KillBranch choice.
  • Loading branch information
zeroyao committed Feb 26, 2013
1 parent 336bfd0 commit 12ca091
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 34 deletions.
14 changes: 14 additions & 0 deletions trunk/TouhouSpring/Game/Behaviors/ForceAttack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TouhouSpring.Behaviors
{
public class ForceAttack : BaseBehavior<ForceAttack.ModelType>
{
[BehaviorModel(Category = "Core", Description = "Card must attack if it can.")]
public class ModelType : BehaviorModel<ForceAttack>
{ }
}
}
19 changes: 2 additions & 17 deletions trunk/TouhouSpring/Game/Behaviors/Protector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,10 @@

namespace TouhouSpring.Behaviors
{
public sealed class Protector : BaseBehavior<Protector.ModelType>,
IPrerequisiteTrigger<Commands.PlayCard>
public sealed class Protector : BaseBehavior<Protector.ModelType>
{
public CommandResult RunPrerequisite(Commands.PlayCard command)
{
if (command.CardToPlay == Host
&& Model.Unique
&& Host.Owner.CardsOnBattlefield.Any(card => card.Model == Host.Model))
{
return CommandResult.Cancel("Only one protector is allowed on battlefield.");
}

return CommandResult.Pass;
}

[BehaviorModel(Category = "Core")]
public class ModelType : BehaviorModel<Protector>
{
public bool Unique { get; set; }
}
{ }
}
}
16 changes: 11 additions & 5 deletions trunk/TouhouSpring/Game/Game.Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public bool DidRedeem
get; private set;
}

public void RunTurn()
public bool RunTurn()
{
if (m_gameFlowThread != null && System.Threading.Thread.CurrentThread != m_gameFlowThread
|| CurrentPhase != "")
Expand All @@ -51,15 +51,15 @@ public void RunTurn()
DidRedeem = false;
IssueCommandsAndFlush(new Commands.StartPhase("Main"));

RunTurnFromMainPhase();
return RunTurnFromMainPhase();
}

public void RunTurnFromMainPhase()
public bool RunTurnFromMainPhase()
{
RunTurnFromMainPhase(null);
return RunTurnFromMainPhase(null);
}

public void RunTurnFromMainPhase(Interactions.TacticalPhase.CompiledResponse compiledMainPhaseResponse)
public bool RunTurnFromMainPhase(Interactions.TacticalPhase.CompiledResponse compiledMainPhaseResponse)
{
if (m_gameFlowThread != null && System.Threading.Thread.CurrentThread != m_gameFlowThread
|| CurrentPhase != "Main")
Expand Down Expand Up @@ -135,6 +135,10 @@ public void RunTurnFromMainPhase(Interactions.TacticalPhase.CompiledResponse com
{
break;
}
else if (result.ActionType == Interactions.TacticalPhase.Action.Abort)
{
return false;
}
else
{
throw new InvalidDataException();
Expand All @@ -146,6 +150,8 @@ public void RunTurnFromMainPhase(Interactions.TacticalPhase.CompiledResponse com
new Commands.StartPhase("Cleanup"),
new Commands.EndPhase(),
new Commands.EndTurn(ActingPlayer));

return true;
}

private void GameFlowMain()
Expand Down
1 change: 1 addition & 0 deletions trunk/TouhouSpring/Game/Game.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Behaviors\ForceAttack.cs" />
<Compile Include="Commands\AddPlayerLife.cs" />
<Compile Include="Commands\AddPlayerMana.cs" />
<Compile Include="Commands\DeactivateAssist.cs" />
Expand Down
31 changes: 28 additions & 3 deletions trunk/TouhouSpring/Game/Interactions/TacticalPhase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public enum Action
Redeem, // return one card from sacrifice to hand
AttackCard, // card attacks a opponent card
AttackPlayer, // card attacks the opponent player
Pass
Pass,
Abort
}

public struct Result
Expand Down Expand Up @@ -65,6 +66,11 @@ public IIndexable<BaseCard> DefenderCandidates
get; private set;
}

public bool CanPass
{
get; private set;
}

internal TacticalPhase(Player player)
: base(player.Game)
{
Expand Down Expand Up @@ -100,6 +106,8 @@ internal TacticalPhase(Player player)
{
DefenderCandidates = Indexable.Empty<BaseCard>();
}

CanPass = !AttackerCandidates.Any(card => card.Behaviors.Has<Behaviors.ForceAttack>());
}

internal Result Run()
Expand All @@ -111,7 +119,12 @@ internal Result Run()

public void RespondPass()
{
RespondBack(new Result { ActionType = Action.Pass });
var result = new Result
{
ActionType = Action.Pass
};
Validate(result);
RespondBack(result);
}

public void RespondPlay(BaseCard selectedCard)
Expand Down Expand Up @@ -249,12 +262,21 @@ public void RespondAttackPlayer(BaseCard attacker, Player player)
RespondBack(result);
}

public void RespondAbort()
{
RespondBack(new Result { ActionType = Action.Abort });
}

protected void Validate(Result result)
{
switch (result.ActionType)
{
case Action.Pass:
if (result.Data != null)
if (!CanPass)
{
throw new InteractionValidationFailException("Can't pass.");
}
else if (result.Data != null)
{
throw new InteractionValidationFailException("Action Pass shall have null data.");
}
Expand Down Expand Up @@ -351,6 +373,9 @@ protected void Validate(Result result)
}
break;

case Action.Abort:
break;

default:
throw new InteractionValidationFailException("Invalid action performed.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ public void OnEnter(Interactions.BaseInteraction io)
{
m_io = (Interactions.TacticalPhase)io;
m_gameUI.RemoveAllContextButtons();
m_gameUI.AddContextButton("结束", ContextButton_OnPass);
if (m_io.CanPass)
{
m_gameUI.AddContextButton("结束", ContextButton_OnPass);
}
m_castFromCards = m_io.CastSpellCandidates.Select(spell => spell.Host).Distinct().ToArray();
}

Expand All @@ -51,7 +54,10 @@ public void OnCardClicked(UI.CardControl cardControl)
var card = SelectedCard != null ? SelectedCard.Card : null;

m_gameUI.RemoveAllContextButtons();
m_gameUI.AddContextButton("结束", ContextButton_OnPass);
if (m_io.CanPass)
{
m_gameUI.AddContextButton("结束", ContextButton_OnPass);
}

if (m_io.PlayCardCandidates.Contains(card))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ public override IEnumerable<Choice> TacticalPhase(Interactions.TacticalPhase io,
}
}

yield return new PassChoice();
if (io.CanPass)
{
yield return new PassChoice();
}
}

public override IEnumerable<Choice> SelectCards(Interactions.SelectCards io, IContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,27 @@ public Task(ParallelSandbox sandbox, PendingBranch pendingBranch)
while (m_pendingCursor < m_pendingBranches.Count)
{
m_currentBranch = m_pendingBranches[m_pendingCursor++];
bool aborted = false;

if (m_currentBranch.Root != null)
{
CurrentBranchDepth = m_currentBranch.Depth;
CurrentBranchOrder = m_currentBranch.Order;
m_currentBranch.Root.OverrideController(this);
m_currentBranch.Root.RunTurnFromMainPhase(m_currentBranch.Response);
aborted = !m_currentBranch.Root.RunTurnFromMainPhase(m_currentBranch.Response);
}
else
{
CurrentBranchDepth = 0;
CurrentBranchOrder = 0;
m_currentBranch.Root = m_sandbox.RootGame.CloneWithController(this);
m_currentBranch.Root.RunTurn();
aborted = !m_currentBranch.Root.RunTurn();
}

m_sandbox.AddResult(m_currentBranch.Root, m_currentBranch.ChoicePath);
if (!aborted)
{
m_sandbox.AddResult(m_currentBranch.Root, m_currentBranch.ChoicePath);
}
}
}

Expand All @@ -101,6 +105,11 @@ private void OnInteraction(Interactions.BaseInteraction io, IEnumerable<Choice>

foreach (var choice in choices)
{
if (mainPhase != null && choice is KillBranchChoice)
{
continue;
}

var branch = ForkBranch(choice);

if (mainPhase != null)
Expand Down Expand Up @@ -147,7 +156,7 @@ private void OnInteraction(Interactions.BaseInteraction io, IEnumerable<Choice>
mainPhase.AttackerCandidates[(choice as AttackPlayerChoice).AttackerIndex],
mainPhase.Game.Players[(choice as AttackPlayerChoice).PlayerIndex]);
}
else if (choice is PassChoice || choice is KillBranchChoice)
else if (choice is PassChoice)
{
branch.Response = mainPhase.CompiledRespondPass();
}
Expand Down Expand Up @@ -184,7 +193,9 @@ private void OnInteraction(Interactions.BaseInteraction io, IEnumerable<Choice>
}
else
{
throw new NotImplementedException();
// no choice generated
System.Diagnostics.Debug.Assert(io is Interactions.TacticalPhase);
(io as Interactions.TacticalPhase).RespondAbort();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
<Behavior Type="TouhouSpring.Behaviors.Passive_Retaliate+ModelType">
<Name>反击</Name>
</Behavior>
<Behavior Type="TouhouSpring.Behaviors.ForceAttack+ModelType">
<Name>TouhouSpring.Behaviors.ForceAttack</Name>
</Behavior>
</Behaviors>
<Category>TouhouSpring/Miko/Summonings</Category>
</Resource>
Expand Down Expand Up @@ -497,7 +500,6 @@ X等于己方场上本卡的数量
</Behavior>
<Behavior Type="TouhouSpring.Behaviors.Protector+ModelType">
<Name>Protector</Name>
<Unique>true</Unique>
</Behavior>
</Behaviors>
<Category>TouhouSpring/Miko/Warriors</Category>
Expand Down

0 comments on commit 12ca091

Please sign in to comment.