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,34 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record AluminumHat() : PatchCard(ECard.AluminumHat, Balancing.Instance.AluminumHatCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Uncommon)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
var tape = coreLoop.GetTapeCards();
var index = tape.IndexOf(this);
if (index < 0)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.NotFound, this, avatarCell));
return;
}
for (int i = index + 1; i < tape.Count; ++i)
{
intents.Add(new ImmunizeCard(this, tape[i], EModifierId.Unreliable, EModifierDuration.ShortTerm));
}
}
public override string ToolTip => "Instructions on tape become #Immune to the effects of unreliable";
public override Modifier[] TooltipModifiers => [new UnreliableCardModifier(EModifierDuration.Temporary)];
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record AtomicClock() : PatchCard(ECard.AtomicClock, Balancing.Instance.AtomicClockCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Uncommon)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
var tape = coreLoop.GetTapeCards();
var index = tape.IndexOf(this);
if (index < 0)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.NotFound, this, avatarCell));
return;
}
for (int i = index + 1; i < tape.Count; ++i)
{
intents.Add(new ImmunizeCard(this, tape[i], EModifierId.RaceCondition, EModifierDuration.ShortTerm));
}
}
public override string ToolTip => "Instructions on tape become #Immune to the effects of race condition";
public override Modifier[] TooltipModifiers => [new RaceConditionModifier(EModifierDuration.Temporary)];
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record DetoxiumPrime() : PatchCard(ECard.DetoxiumPrime, Balancing.Instance.DetoxiumPrimeCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Uncommon)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.DetoxiumPrime(avatarCell, this, avatar.Direction));
}
public override string Name => "Detoxium Prime";
public override string ToolTip => "Heals the cell in front";
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record EMField() : PatchCard(ECard.EMField, Balancing.Instance.EMFieldCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Uncommon)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
var tape = coreLoop.GetTapeCards();
var index = tape.IndexOf(this);
if (index < 0)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.NotFound, this, avatarCell));
return;
}
for (int i = index + 1; i < tape.Count; ++i)
{
intents.Add(new ImmunizeCard(this, tape[i], EModifierId.Corrupt, EModifierDuration.Temporary));
}
}
public override string ToolTip => "Instructions on tape become #Immune to the effects of corrupt";
public override Modifier[] TooltipModifiers => [new CorruptCardModifier(EModifierDuration.Temporary)];
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record FlyingDisk() : PatchCard(ECard.FlyingDisk, Balancing.Instance.FlyingDiskCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Uncommon)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.Move(avatarCell, this, avatar.Direction, true, 1));
}
public override string ToolTip => "Fly forward 1 cell, ignoring blocked areas";
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Interact() : PatchCard(ECard.Interact, Balancing.Instance.InteractCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Common)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.Interact(avatarCell, this, avatar.Direction));
}
public override string ToolTip => "Interact with the forward cell";
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Jump() : PatchCard(ECard.Jump, Balancing.Instance.JumpCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Legendary)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.Move(avatarCell, this, avatar.Direction, true, 2));
}
public override string ToolTip => "Move forward 2 cells, ignoring obstacles";
}

View File

@@ -0,0 +1,35 @@
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public abstract record ModifyCardBase(ECard Id, int ShopCost, int PlayCost, ERarity Rarity, EModifierId Modifier) : PatchCard(Id, ShopCost, PlayCost, Rarity)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
var tape = coreLoop.GetTapeCards();
var tapeIndex = tape.IndexOf(this);
if (tapeIndex < 0)
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.NotFound, this, null));
else
{
var corrupt = Modifiers.Any(m => m is CorruptModifierBase { DebuffSources.Count: 0 });
for (var i = tapeIndex + 1; i < tape.Count; ++i)
{
var victim = tape[i];
if (corrupt)
intents.Add(new ImmunizeCard(this, victim, Modifier, EModifierDuration.Temporary, false));
else
intents.Add(new ModifyCard(victim, Modifier, EModifierDuration.Temporary, ECardLocation.Tape));
}
}
}
public override string ToolTip => $"All following instructions in tape become {Modifier} temporarily";
public override Modifier[] TooltipModifiers => [ModifyCard.Create(Modifier, EModifierDuration.Temporary)];
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Move() : PatchCard(ECard.Move, Balancing.Instance.MoveCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Common)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.Move(avatarCell, this, avatar.Direction, false, 1));
}
public override string ToolTip => "Move one cell forward if it's free";
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record NoOp() : PatchCard(ECard.NoOp, Balancing.Instance.InteractCost, 0, ERarity.Common)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.Rest(avatarCell, Balancing.Instance.CardNoOpEnergyReplenish));
}
public override string ToolTip => $"Take a break, do nothing. Restore {Balancing.Instance.CardNoOpEnergyReplenish} energy.";
}

View File

@@ -0,0 +1,5 @@
using RobotAndDonkey.Game.Data;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Optimize() : ModifyCardBase(ECard.Optimize, Balancing.Instance.OptimizeCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Magic, EModifierId.Optimized);

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record PatchCard(ECard Id, int ShopCost, int PlayCost, ERarity Rarity) : Card(Id, ECardType.Patch, Rarity, ShopCost, PlayCost)
{
public override void CreateIntents(Cell? avatarCell, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
if (avatarCell?.Poi is not Avatar avatar)
return;
base.CreateIntents(avatarCell, coreLoop, requestId, intents, results);
CreateIntents(avatarCell, avatar, coreLoop, requestId, intents, results);
}
protected virtual void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
}
}

View File

@@ -0,0 +1,5 @@
using RobotAndDonkey.Game.Data;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Persist() : ModifyCardBase(ECard.Persist, Balancing.Instance.PersistCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Magic, EModifierId.Persistent);

View File

@@ -0,0 +1,5 @@
using RobotAndDonkey.Game.Data;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Potentiate() : ModifyCardBase(ECard.Potentiate, Balancing.Instance.PotentiateCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Magic, EModifierId.Effective);

View File

@@ -0,0 +1,18 @@
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Reason() : PatchCard(ECard.Reason, Balancing.Instance.ReasonCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Rare)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new ModifyCurrency(new(0, 0, 0, 0, 0, HandSize: 1), true));
}
public override string ToolTip => "Adds hand size, permanently.";
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Remember() : PatchCard(ECard.Remember, Balancing.Instance.RememberCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Rare)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new ModifyCurrency(new(0, 0, 0, 0, TapeLength: 1, 0), true));
}
public override string ToolTip => "Increases tape length, permanently.";
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
using RobotAndDonkey.Game.Utils;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Repeat() : PatchCard(ECard.Repeat, Balancing.Instance.RepeatCost, 0, ERarity.Legendary)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
var tape = coreLoop.GetTapeCards();
var index = tape.IndexOf(this);
if (index < 0)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.NotFound, this, avatarCell));
return;
}
var targetIndex = CardExtensions.NextIndexConsideringCorruption(index, coreLoop);
if (targetIndex < 0 || targetIndex >= tape.Count)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.OutOfBounds, this, avatarCell));
return;
}
var targetCard = tape[targetIndex];
if (!m_RepeatedCards.Add(targetCard))
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.AlreadyExecuted, this, avatarCell));
return;
}
targetCard.CreateIntents(avatarCell, coreLoop, requestId, intents, results);
m_RepeatedCards.Remove(targetCard);
}
public override string ToolTip => "Behaves exactly like the next instruction.";
private readonly HashSet<Card> m_RepeatedCards = [];
}

View File

@@ -0,0 +1,18 @@
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Rest() : PatchCard(ECard.Rest, Balancing.Instance.RestCost, 0, ERarity.Legendary)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Intents.Rest(avatarCell, Balancing.Instance.CardRestEnergyReplenish));
}
public override string ToolTip => $"Reboot the system and restore {Balancing.Instance.CardRestEnergyReplenish} energy.";
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Modifiers;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Stabilize() : PatchCard(ECard.Stabilize, Balancing.Instance.StabilizeCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Legendary)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
var tape = coreLoop.GetTapeCards();
var index = tape.IndexOf(this);
if (index < 0)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.NotFound, this, avatarCell));
return;
}
var targetIndex = index + 1;
if (targetIndex >= tape.Count)
{
results.Add(new InvalidInstructionResult(requestId, EInvalidReason.OutOfBounds, this, avatarCell));
return;
}
intents.Add(new ImmunizeCard(this, tape[targetIndex], EModifierId._Invalid, EModifierDuration.ShortTerm));
}
public override string ToolTip => "Temporarily nullifies all modifiers of the next card.";
}

View File

@@ -0,0 +1,5 @@
using RobotAndDonkey.Game.Data;
namespace RobotAndDonkey.Game.Cards.Patches;
public record Streamline() : ModifyCardBase(ECard.Streamline, Balancing.Instance.StreamlineCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Magic, EModifierId.Efficient);

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record TurnLeft() : PatchCard(ECard.TurnLeft, Balancing.Instance.TurnLeftCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Common)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Turn(avatarCell, 1));
}
public override string ToolTip => "Change the orientation by 60 degrees counter-clockwise";
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using RobotAndDonkey.Game.Board;
using RobotAndDonkey.Game.Data;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Intents;
using RobotAndDonkey.Game.Pois;
namespace RobotAndDonkey.Game.Cards.Patches;
public record TurnRight() : PatchCard(ECard.TurnRight, Balancing.Instance.TurnRightCost, Balancing.Instance.CardPlayEnergyCost, ERarity.Common)
{
protected override void CreateIntents(Cell avatarCell, Avatar avatar, CoreLoop coreLoop, Guid requestId, List<Intent> intents, List<Result> results)
{
intents.Add(new Turn(avatarCell, -1));
}
public override string ToolTip => "Change the orientation by 60 degrees clockwise";
}