119 lines
4.3 KiB
C#
119 lines
4.3 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Static.Libraries;
|
|
|
|
/// <summary>
|
|
/// All data related to types and their effectiveness.
|
|
/// </summary>
|
|
public interface IReadOnlyTypeLibrary
|
|
{
|
|
/// <summary>
|
|
/// Gets the type identifier for a type with a name.
|
|
/// </summary>
|
|
bool TryGetTypeIdentifier(StringKey key, out TypeIdentifier typeIdentifier);
|
|
|
|
/// <summary>
|
|
/// Gets the type identifier for a type with an index.
|
|
/// </summary>
|
|
bool TryGetTypeIdentifierFromIndex(byte index, [MaybeNullWhen(false)] out TypeIdentifier typeIdentifier);
|
|
|
|
/// <summary>
|
|
/// Gets the effectiveness for a single attacking type against a single defending type.
|
|
/// </summary>
|
|
float GetSingleEffectiveness(TypeIdentifier attacking, TypeIdentifier defending);
|
|
|
|
/// <summary>
|
|
/// Gets the effectiveness for a single attacking type against an amount of defending types.
|
|
/// This is equivalent to running get_single_effectiveness on each defending type, and multiplying the results with each other.
|
|
/// </summary>
|
|
float GetEffectiveness(TypeIdentifier attacking, IEnumerable<TypeIdentifier> defending);
|
|
|
|
IEnumerable<(TypeIdentifier type, float effectiveness)> GetAllEffectivenessFromAttacking(TypeIdentifier attacking);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public class TypeLibrary : IReadOnlyTypeLibrary
|
|
{
|
|
private readonly List<TypeIdentifier> _types = new();
|
|
private readonly List<List<float>> _effectiveness = new();
|
|
|
|
/// <inheritdoc />
|
|
public bool TryGetTypeIdentifier(StringKey key, out TypeIdentifier type)
|
|
{
|
|
var found = _types.FirstOrDefault(t => t.Name.Equals(key));
|
|
if (found.Value is not 0)
|
|
{
|
|
type = found;
|
|
return true;
|
|
}
|
|
type = default;
|
|
return false;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public bool TryGetTypeIdentifierFromIndex(byte index, out TypeIdentifier typeIdentifier)
|
|
{
|
|
if (index < 1 || index > _types.Count)
|
|
{
|
|
typeIdentifier = default;
|
|
return false;
|
|
}
|
|
typeIdentifier = _types[index - 1];
|
|
return true;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public float GetSingleEffectiveness(TypeIdentifier attacking, TypeIdentifier defending)
|
|
{
|
|
if (attacking.Value < 1 || attacking.Value > _effectiveness.Count)
|
|
throw new ArgumentOutOfRangeException(nameof(attacking));
|
|
if (defending.Value < 1 || defending.Value > _effectiveness.Count)
|
|
throw new ArgumentOutOfRangeException(nameof(defending));
|
|
return _effectiveness[attacking.Value - 1][defending.Value - 1];
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public float GetEffectiveness(TypeIdentifier attacking, IEnumerable<TypeIdentifier> defending) =>
|
|
defending.Aggregate<TypeIdentifier, float>(1,
|
|
(current, type) => current * GetSingleEffectiveness(attacking, type));
|
|
|
|
/// <inheritdoc />
|
|
public IEnumerable<(TypeIdentifier, float)> GetAllEffectivenessFromAttacking(TypeIdentifier attacking)
|
|
{
|
|
if (attacking.Value < 1 || attacking.Value > _effectiveness.Count)
|
|
throw new ArgumentOutOfRangeException(nameof(attacking));
|
|
for (var i = 0; i < _effectiveness.Count; i++)
|
|
{
|
|
var type = _types[i];
|
|
yield return (type, _effectiveness[attacking.Value - 1][i]);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Registers a new type in the library.
|
|
/// </summary>
|
|
public TypeIdentifier RegisterType(StringKey name)
|
|
{
|
|
var id = new TypeIdentifier((byte)(_types.Count + 1), name);
|
|
_types.Add(id);
|
|
_effectiveness.Add(Enumerable.Repeat(1.0f, _effectiveness.Count).ToList());
|
|
foreach (var list in _effectiveness)
|
|
{
|
|
list.Add(1);
|
|
}
|
|
return id;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the effectiveness for an attacking type against a defending type.
|
|
/// </summary>
|
|
public void SetEffectiveness(TypeIdentifier attacking, TypeIdentifier defending, float effectiveness)
|
|
{
|
|
if (attacking.Value < 1 || attacking.Value > _effectiveness.Count)
|
|
throw new ArgumentOutOfRangeException(nameof(attacking));
|
|
if (defending.Value < 1 || defending.Value > _effectiveness.Count)
|
|
throw new ArgumentOutOfRangeException(nameof(defending));
|
|
_effectiveness[attacking.Value - 1][defending.Value - 1] = effectiveness;
|
|
}
|
|
} |