179 lines
7.0 KiB
C#
179 lines
7.0 KiB
C#
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();
|
|
}
|