ported from perforce
This commit is contained in:
178
RobotAndDonkey.Game/Intents/RunProgram.cs
Normal file
178
RobotAndDonkey.Game/Intents/RunProgram.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using RobotAndDonkey.Game.Board;
|
||||
using RobotAndDonkey.Game.Cards;
|
||||
using RobotAndDonkey.Game.Data;
|
||||
using RobotAndDonkey.Game.Execution;
|
||||
using RobotAndDonkey.Game.Execution.Results;
|
||||
using RobotAndDonkey.Game.GameState;
|
||||
using RobotAndDonkey.Game.Modifiers;
|
||||
using RobotAndDonkey.Game.Pois;
|
||||
using RobotAndDonkey.Game.Robots;
|
||||
using RobotAndDonkey.Game.Utils;
|
||||
|
||||
namespace RobotAndDonkey.Game.Intents;
|
||||
|
||||
public class RunProgram : Intent
|
||||
{
|
||||
public static IEnumerable<(Entity Entity, ECardLocation Location)> CollectEntities(CoreLoop coreLoop)
|
||||
{
|
||||
yield return (coreLoop.Robot, ECardLocation.Robot);
|
||||
|
||||
foreach (var card in coreLoop.PatchDeck)
|
||||
yield return (card, ECardLocation.Deck);
|
||||
|
||||
foreach (var card in coreLoop.Hand)
|
||||
yield return (card, ECardLocation.Hand);
|
||||
|
||||
foreach (var card in coreLoop.Tape)
|
||||
yield return (card, ECardLocation.Tape);
|
||||
|
||||
foreach (var card in coreLoop.Discard)
|
||||
yield return (card, ECardLocation.Discard);
|
||||
|
||||
foreach (var card in coreLoop.Board.Cells)
|
||||
yield return (card, ECardLocation.Board);
|
||||
}
|
||||
|
||||
public override void Run(Guid requestId, CoreLoop coreLoop, List<Intent> newIntents, List<Result> results)
|
||||
{
|
||||
var board = coreLoop.Board;
|
||||
|
||||
coreLoop.ProgramsExecuted += 1;
|
||||
results.Add(new ProgramResult(requestId, coreLoop.ProgramsExecuted));
|
||||
|
||||
var modifierStack = new ModifierStack();
|
||||
modifierStack.Push(coreLoop.Robot);
|
||||
|
||||
var tapeCards = coreLoop.GetTapeCards();
|
||||
var minCount = Math.Min(tapeCards.Count, coreLoop.Currency.TapeLength);
|
||||
|
||||
for (var i = 0; i < minCount; i++)
|
||||
{
|
||||
var card = tapeCards[i];
|
||||
if (!card.Modifiers.Any(m => m is { Id: EModifierId.RaceCondition, DebuffSources.Count: 0 }))
|
||||
continue;
|
||||
|
||||
if (coreLoop.Random.NextSingle() > Balancing.Instance.RaceConditionChance)
|
||||
continue;
|
||||
|
||||
var targetIndex = CardExtensions.NextIndexConsideringCorruption(i, coreLoop);
|
||||
if (targetIndex >= 0 && targetIndex < tapeCards.Count)
|
||||
{
|
||||
results.Add(new ModifyCardResult(requestId, tapeCards[targetIndex].DeepClone(), EModifierId.RaceCondition, ECardLocation.Tape));
|
||||
if (coreLoop.SwapTapeCards(i, targetIndex))
|
||||
{
|
||||
(tapeCards[i], tapeCards[targetIndex]) = (tapeCards[targetIndex], tapeCards[i]);
|
||||
results.Add(new ProgramRowResult(requestId, coreLoop.ProgramRow.ToArray(), coreLoop.TapeCardIds));
|
||||
results.Add(new TapeResult(requestId, tapeCards.ToArray()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tapeCards = coreLoop.GetTapeCards();
|
||||
minCount = Math.Min(tapeCards.Count, coreLoop.Currency.TapeLength);
|
||||
|
||||
for (var i = 0; i < minCount; i++)
|
||||
{
|
||||
var card = tapeCards[i];
|
||||
var avatarCell = board.Cells.Single(c => c.Poi is Avatar);
|
||||
modifierStack.Push(avatarCell);
|
||||
modifierStack.Push(card);
|
||||
|
||||
results.Add(new RunCardResult(requestId, card));
|
||||
var intents = new List<Intent>();
|
||||
card.CreateIntents(avatarCell, coreLoop, requestId, intents, results);
|
||||
modifierStack.Execute(requestId, coreLoop, intents, results, false, true);
|
||||
coreLoop.InstructionsUsed += 1;
|
||||
|
||||
modifierStack.Pop();
|
||||
modifierStack.Pop();
|
||||
}
|
||||
|
||||
modifierStack.Pop();
|
||||
|
||||
static IEnumerable<(Entity Owner, Modifier Modifier, ECardLocation Location)> CollectModifiers(CoreLoop coreLoop, EModifierDuration duration)
|
||||
{
|
||||
foreach (var (entity, location) in CollectEntities(coreLoop))
|
||||
{
|
||||
foreach (var modifier in entity.Modifiers)
|
||||
{
|
||||
if (modifier.Duration == duration)
|
||||
yield return (entity, modifier, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveModifier(Entity entity, Modifier modifier, ECardLocation location)
|
||||
{
|
||||
entity.RemoveModifier(modifier, newIntents);
|
||||
if (entity is Cell cell)
|
||||
results.Add(new ModifyCellResult(requestId, new(coreLoop.Board), modifier.Id, cell.Hex));
|
||||
if (entity is Card card)
|
||||
results.Add(new ModifyCardResult(requestId, card.DeepClone(), modifier.Id, location));
|
||||
if (entity is Robot)
|
||||
results.Add(new ModifyRobotResult(requestId));
|
||||
}
|
||||
|
||||
foreach (var (entity, modifier, location) in CollectModifiers(coreLoop, EModifierDuration.ShortTerm).ToArray())
|
||||
RemoveModifier(entity, modifier, location);
|
||||
|
||||
tapeCards = coreLoop.GetTapeCards();
|
||||
foreach (var card in tapeCards)
|
||||
{
|
||||
var isPersistent = card.Modifiers.Any(m => m is PersistentModifier && m.DebuffSources.Count == 0);
|
||||
|
||||
if (!isPersistent)
|
||||
{
|
||||
coreLoop.Discard.Add(card);
|
||||
coreLoop.RemoveProgramCard(card);
|
||||
}
|
||||
}
|
||||
coreLoop.ClearTapeSelection();
|
||||
coreLoop.ProgramCount -= 1;
|
||||
|
||||
results.Add(new ProgramRowResult(requestId, coreLoop.ProgramRow.ToArray(), coreLoop.TapeCardIds));
|
||||
results.Add(new CurrencyResult(requestId, coreLoop.Currency));
|
||||
results.Add(new HandResult(requestId, coreLoop.Hand.ToArray()));
|
||||
results.Add(new DiscardResult(requestId, coreLoop.Discard.ToArray()));
|
||||
results.Add(new ProgramResult(requestId, coreLoop.ProgramCount));
|
||||
results.Add(new TapeResult(requestId, coreLoop.Tape.ToArray()));
|
||||
results.Add(new DeckResult(requestId, coreLoop.PatchDeck.ToArray()));
|
||||
|
||||
var victory = coreLoop.Board.Cells.Select(c => c.Poi as Shed).Where(s => s != null).Sum(s => s!.Remaining) == 0;
|
||||
if (coreLoop.ProgramCount == 0 || coreLoop.PatchDeck.Count == 0 || coreLoop.Currency.Energy <= 0 || victory)
|
||||
{
|
||||
coreLoop.Currency.Energy += Balancing.Instance.EndOfProgramEnergyReplenish;
|
||||
coreLoop.RunPhase = ERunPhase.Scoring;
|
||||
|
||||
foreach (var (entity, modifier, location) in CollectModifiers(coreLoop, EModifierDuration.Temporary).ToArray())
|
||||
{
|
||||
RemoveModifier(entity, modifier, location);
|
||||
}
|
||||
|
||||
results.Add(new HandResult(requestId, coreLoop.Hand.ToArray()));
|
||||
results.Add(new DiscardResult(requestId, coreLoop.Discard.ToArray()));
|
||||
results.Add(new TapeResult(requestId, coreLoop.Tape.ToArray()));
|
||||
results.Add(new DeckResult(requestId, coreLoop.PatchDeck.ToArray()));
|
||||
|
||||
results.Add(new RunPhaseResult(requestId, coreLoop.RunPhase));
|
||||
}
|
||||
else
|
||||
{
|
||||
coreLoop.DrawHand();
|
||||
}
|
||||
|
||||
base.Run(requestId, coreLoop, newIntents, results);
|
||||
}
|
||||
|
||||
public override bool IsValid(CoreLoop coreLoop)
|
||||
{
|
||||
if (!base.IsValid(coreLoop))
|
||||
return false;
|
||||
|
||||
return coreLoop.RunPhase == ERunPhase.ExecuteProgram;
|
||||
}
|
||||
|
||||
public override bool Immune => true;
|
||||
|
||||
public override string ToString() => "Run program, " + base.ToString();
|
||||
}
|
||||
Reference in New Issue
Block a user