mirror of
https://github.com/kwsch/pk3DS.git
synced 2026-03-22 01:44:33 -05:00
164 lines
4.5 KiB
C#
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;
|
|
}
|
|
} |