Begin work on outlining dynamic side
This commit is contained in:
6
PkmnLib.Dynamic/Models/Choices/FleeChoice.cs
Normal file
6
PkmnLib.Dynamic/Models/Choices/FleeChoice.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
public interface IFleeChoice : ITurnChoice
|
||||
{
|
||||
|
||||
}
|
||||
6
PkmnLib.Dynamic/Models/Choices/ItemChoice.cs
Normal file
6
PkmnLib.Dynamic/Models/Choices/ItemChoice.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
public interface IItemChoice : ITurnChoice
|
||||
{
|
||||
|
||||
}
|
||||
74
PkmnLib.Dynamic/Models/Choices/MoveChoice.cs
Normal file
74
PkmnLib.Dynamic/Models/Choices/MoveChoice.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using PkmnLib.Dynamic.ScriptHandling;
|
||||
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
/// <summary>
|
||||
/// The choice of a Pokémon to use a move.
|
||||
/// </summary>
|
||||
public interface IMoveChoice : ITurnChoice
|
||||
{
|
||||
/// <summary>
|
||||
/// The move that is used.
|
||||
/// </summary>
|
||||
ILearnedMove UsedMove { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The side the move is targeted at.
|
||||
/// </summary>
|
||||
byte TargetSide { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The position the move is targeted at.
|
||||
/// </summary>
|
||||
byte TargetPosition { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The priority of the move.
|
||||
/// </summary>
|
||||
sbyte Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The underlying script of the move.
|
||||
/// </summary>
|
||||
ScriptContainer Script { get; set; }
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMoveChoice"/>
|
||||
public class MoveChoice : TurnChoice, IMoveChoice
|
||||
{
|
||||
/// <inheritdoc cref="MoveChoice"/>
|
||||
public MoveChoice(IPokemon user, ILearnedMove usedMove, byte targetSide, byte targetPosition) : base(user)
|
||||
{
|
||||
UsedMove = usedMove;
|
||||
TargetSide = targetSide;
|
||||
TargetPosition = targetPosition;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ILearnedMove UsedMove { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte TargetSide { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte TargetPosition { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public sbyte Priority { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ScriptContainer Script { get; set; } = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int ScriptCount => 1 + User.ScriptCount;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts) => scripts.Add(Script);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void CollectScripts(List<IEnumerable<ScriptContainer>> scripts)
|
||||
{
|
||||
GetOwnScripts(scripts);
|
||||
User.CollectScripts(scripts);
|
||||
}
|
||||
}
|
||||
6
PkmnLib.Dynamic/Models/Choices/PassChoice.cs
Normal file
6
PkmnLib.Dynamic/Models/Choices/PassChoice.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
public interface IPassChoice : ITurnChoice
|
||||
{
|
||||
|
||||
}
|
||||
6
PkmnLib.Dynamic/Models/Choices/SwitchChoice.cs
Normal file
6
PkmnLib.Dynamic/Models/Choices/SwitchChoice.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
public interface ISwitchChoice : ITurnChoice
|
||||
{
|
||||
|
||||
}
|
||||
56
PkmnLib.Dynamic/Models/Choices/TurnChoice.cs
Normal file
56
PkmnLib.Dynamic/Models/Choices/TurnChoice.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using PkmnLib.Dynamic.ScriptHandling;
|
||||
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
public interface ITurnChoice : IScriptSource
|
||||
{
|
||||
/// <summary>
|
||||
/// The user of the turn choice
|
||||
/// </summary>
|
||||
IPokemon User { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The speed of the user at the beginning of the turn.
|
||||
/// </summary>
|
||||
uint Speed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This random value is set at the beginning of the turn. It is used for tie breaking of the
|
||||
/// turn order in a predictable way, regardless of implementation and hardware.
|
||||
/// </summary>
|
||||
uint RandomValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the choice has failed. A failed choice will stop running, and execute special
|
||||
/// fail handling during turn execution.
|
||||
/// </summary>
|
||||
bool HasFailed { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Fails the choice. This will prevent it from executing and run a specific fail handling during
|
||||
/// execution. Note that this can not be undone.
|
||||
/// </summary>
|
||||
public void Fail();
|
||||
}
|
||||
|
||||
public abstract class TurnChoice : ScriptSource, ITurnChoice
|
||||
{
|
||||
protected TurnChoice(IPokemon user)
|
||||
{
|
||||
User = user;
|
||||
}
|
||||
|
||||
public IPokemon User { get; }
|
||||
|
||||
public uint Speed { get; set; }
|
||||
|
||||
public uint RandomValue { get; set; }
|
||||
|
||||
public bool HasFailed { get; private set; }
|
||||
|
||||
public void Fail()
|
||||
{
|
||||
HasFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
83
PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs
Normal file
83
PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
namespace PkmnLib.Dynamic.Models.Choices;
|
||||
|
||||
/// <summary>
|
||||
/// Comparer for turnchoices, to determine the order in which they should be executed.
|
||||
/// </summary>
|
||||
public class TurnChoiceComparer : IComparer<ITurnChoice>
|
||||
{
|
||||
private enum CompareValues
|
||||
{
|
||||
XEqualsY = 0,
|
||||
XLessThanY = -1,
|
||||
XGreaterThanY = 1
|
||||
}
|
||||
|
||||
private CompareValues CompareForSameType(ITurnChoice x, ITurnChoice y)
|
||||
{
|
||||
// Higher speed goes first
|
||||
var speedComparison = x.Speed.CompareTo(y.Speed);
|
||||
if (speedComparison != 0)
|
||||
return (CompareValues)speedComparison;
|
||||
// If speed is equal, we use the random values we've given to each choice to tiebreak.
|
||||
// This is to ensure that the order of choices is deterministic.
|
||||
return (CompareValues)x.RandomValue.CompareTo(y.RandomValue);
|
||||
}
|
||||
|
||||
private CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y)
|
||||
{
|
||||
// Deal with possible null values
|
||||
switch (x)
|
||||
{
|
||||
case null when y is null:
|
||||
return CompareValues.XEqualsY;
|
||||
case null:
|
||||
return CompareValues.XLessThanY;
|
||||
}
|
||||
if (y is null)
|
||||
return CompareValues.XGreaterThanY;
|
||||
|
||||
switch (x)
|
||||
{
|
||||
case IMoveChoice moveX:
|
||||
// Move choices go first
|
||||
if (y is IMoveChoice moveY)
|
||||
{
|
||||
// Higher priority goes first
|
||||
var priorityComparison = moveX.Priority.CompareTo(moveY.Priority);
|
||||
if (priorityComparison != 0)
|
||||
return (CompareValues)priorityComparison;
|
||||
return CompareForSameType(moveX, moveY);
|
||||
}
|
||||
return CompareValues.XGreaterThanY;
|
||||
case IItemChoice itemX:
|
||||
// Item choices go second
|
||||
return y switch
|
||||
{
|
||||
IMoveChoice => CompareValues.XLessThanY,
|
||||
IItemChoice itemY => CompareForSameType(itemX, itemY),
|
||||
_ => CompareValues.XGreaterThanY
|
||||
};
|
||||
case ISwitchChoice switchX:
|
||||
// Switch choices go third
|
||||
return y switch
|
||||
{
|
||||
IMoveChoice or IItemChoice => CompareValues.XLessThanY,
|
||||
ISwitchChoice switchY => CompareForSameType(switchX, switchY),
|
||||
_ => CompareValues.XGreaterThanY
|
||||
};
|
||||
case IPassChoice passX:
|
||||
// Pass choices go last
|
||||
return y switch
|
||||
{
|
||||
IMoveChoice or IItemChoice or ISwitchChoice => CompareValues.XLessThanY,
|
||||
IPassChoice passY => CompareForSameType(passX, passY),
|
||||
_ => CompareValues.XGreaterThanY
|
||||
};
|
||||
}
|
||||
|
||||
return CompareValues.XLessThanY;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Compare(ITurnChoice? x, ITurnChoice? y) => (int) CompareImpl(x, y);
|
||||
}
|
||||
Reference in New Issue
Block a user