pk3DS/pk3DS.Core/Randomizers/MoveRandomizer.cs
2024-06-02 18:26:00 -05:00

164 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using pk3DS.Core.Structures;
using pk3DS.Core.Structures.PersonalInfo;
namespace pk3DS.Core.Randomizers;
public class MoveRandomizer : IRandomizer
{
//private readonly GameConfig Config;
//private readonly int MaxMoveID;
private readonly Move[] MoveData;
private readonly PersonalInfo[] SpeciesStat;
private readonly GenericRandomizer RandMove;
public MoveRandomizer(GameConfig config)
{
//Config = config;
var MaxMoveID = config.Info.MaxMoveID;
MoveData = config.Moves;
SpeciesStat = config.Personal.Table;
RandMove = new GenericRandomizer(Enumerable.Range(1, MaxMoveID - 1).ToArray());
}
public void Execute()
{
}
public bool rDMG = true;
public int rDMGCount = 2;
public bool rSTAB = true;
public int rSTABCount = 2;
public decimal rSTABPercent = 100;
public IList<int> BannedMoves = [];
public static readonly int[] FixedDamageMoves = [49, 82];
private int loopctr;
public int[] GetRandomLearnset(int index, int movecount) => GetRandomLearnset(SpeciesStat[index].Types, movecount);
public int[] GetRandomLearnset(int[] Types, int movecount)
{
var oldSTABCount = rSTABCount;
rSTABCount = (int)(rSTABPercent * movecount / 100);
int[] moves = GetRandomMoveset(Types, movecount);
rSTABCount = oldSTABCount;
return moves;
}
public int[] GetRandomMoveset(int index, int movecount = 4) => GetRandomMoveset(SpeciesStat[index].Types, movecount);
public int[] GetRandomMoveset(int[] Types, int movecount = 4)
{
loopctr = 0;
const int maxLoop = 666;
int[] moves;
do { moves = GetRandomMoves(Types, movecount); }
while (!IsMovesetMeetingRequirements(moves, movecount) && loopctr++ <= maxLoop);
return moves;
}
private int[] GetRandomMoves(int[] Types, int movecount = 4)
{
int i = 0;
int[] moves = new int[movecount];
if (rSTAB)
{
for (; i < rSTABCount; i++)
moves[i] = GetRandomSTABMove(Types);
}
for (; i < moves.Length; i++) // remainder of moves
moves[i] = RandMove.Next();
return moves;
}
private int GetRandomSTABMove(int[] types)
{
int move;
do { move = RandMove.Next(); }
while (!types.Contains(MoveData[move].Type));
return move;
}
private bool IsMovesetMeetingRequirements(int[] moves, int count)
{
if (rDMG && rDMGCount > moves.Count(move => MoveData[move].Category != 0))
return false;
if (moves.Any(BannedMoves.Contains))
return false;
return moves.Distinct().Count() == count;
}
public void ReorderMovesPower(IList<int> moves)
{
var data = moves.Select((Move, Index) => new { Index, Move, Data = MoveData[Move] });
var powered = data.Where(z => z.Data.Power > 1).ToList();
var indexes = powered.ConvertAll(z => z.Index);
var order = powered.OrderBy(z => z.Data.Power * Math.Max(1, (z.Data.HitMin + z.Data.HitMax) / 2m)).ToList();
for (var i = 0; i < order.Count; i++)
moves[indexes[i]] = order[i].Move;
}
private static readonly int[] firstMoves =
[
1, // Pound
40, // Poison Sting
52, // Ember
55, // Water Gun
64, // Peck
71, // Absorb
84, // Thunder Shock
98, // Quick Attack
122, // Lick
141, // Leech Life
];
private static readonly GenericRandomizer first = new(firstMoves);
public static int GetRandomFirstMoveAny()
{
first.Reset();
return first.Next();
}
public int GetRandomFirstMove(int index) => GetRandomFirstMove(SpeciesStat[index].Types);
public int GetRandomFirstMove(int[] types)
{
first.Reset();
int ctr = 0;
int move;
do
{
move = first.Next();
if (++ctr == firstMoves.Length)
return move;
} while (!types.Contains(MoveData[move].Type));
return move;
}
public bool SanitizeMovesetForBannedMoves(int[] moves, int index)
{
bool updated = false;
for (int m = 0; m < moves.Length; m++)
{
if (!BannedMoves.Contains(moves[m]))
continue;
updated = true;
moves[m] = GetRandomFirstMove(index);
}
return updated;
}
}