ported from perforce

This commit is contained in:
2026-04-19 00:43:27 +02:00
commit 6c0c33f5d4
700 changed files with 19735 additions and 0 deletions

View 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();
}