2024-07-26 20:49:10 +05:00

128 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Diagnostics;
using SoulstormReplayReader.Core.Extensions;
using SoulstormReplayReader.Core.Domain.Player;
namespace SoulstormReplayReader.Core.Utils;
// TODO: Посмотреть что происходит с наблюдателями
internal sealed class PlayersRandomizer
{
private readonly NativeDowRandom _rand = new();
public uint Seed
{
get => _rand.Seed;
set => _rand.SetSeed(value);
}
public PlayersRandomizer(uint seed = 0)
{
Seed = seed;
Debug.WriteLine($"The seed is: {Seed}");
}
public List<PlayerModel> Randomize(List<PlayerModel> players, int mapPlayersCount)
{
var isFfa = GetIsFfa(players);
Debug.WriteLine(isFfa ? "FFA" : "SET TEAMS");
Debug.WriteLine("RANDOMIZING TEAMS");
var newPlayers = RandomizeTeams(players, isFfa);
Debug.WriteLine("RANDOMIZING HOLES");
RandomizeHoles(newPlayers, mapPlayersCount);
if (!isFfa)
{
Debug.WriteLine("RANDOMIZING PLAYERS IN TEAMS");
RandomizePlayersInTeams(newPlayers);
}
return newPlayers;
}
private static bool GetIsFfa(List<PlayerModel> players)
{
var lastTeam = 0;
foreach (var player in players.OrderBy(static p => p.Team))
{
if (player.Team - lastTeam > 1)
return true;
lastTeam = player.Team;
}
return false;
}
private List<PlayerModel> RandomizeTeams(List<PlayerModel> players, bool isFfa)
{
if (isFfa)
{
var nPlayers = players.ToList();
var activePlayersCount = players.Count(static p => p.IsActive);
for (var i = 1; i < 8 && activePlayersCount > 1; i++)
{
if (nPlayers[i].IsActive) activePlayersCount--;
nPlayers.Swap(i, _rand.GetMax(i + 1));
}
return nPlayers.Where(static p => p.IsActive).ToList();
}
var teams = players
.Where(static p => p.IsActive)
.OrderBy(static p => p.Team)
.GroupBy(static pl => pl.Team)
.Select(static team => team.ToList()).ToList();
for (var i = 1; i < teams.Count; i++)
teams.Swap(i, _rand.GetMax(i + 1));
return teams.SelectMany(static p => p).ToList();
}
private void RandomizeHoles(List<PlayerModel> players, int mapPlayersCount)
{
var holesCount = mapPlayersCount - players.Count;
for (var i = 1; i < players.Count && holesCount != 0; i++)
{
var playerHolesCount = _rand.GetMax(holesCount + 1);
if (playerHolesCount == 0) continue;
holesCount -= playerHolesCount;
for (var j = 0; j < playerHolesCount; j++)
{
players.Insert(i, PlayerModel.Empty);
i++;
}
}
if (holesCount == 0) return;
Debug.WriteLine($"{holesCount + 1} {holesCount}");
while (holesCount-- != 0)
players.Add(PlayerModel.Empty);
}
private void RandomizePlayersInTeams(List<PlayerModel> players)
{
var indexTeams = players
.Select(static (p, i) => new KeyValuePair<int, int>(p.Team, i))
.Where(static kv => kv.Key != 0)
.GroupBy(static kv => kv.Key)
.Select(static teamIndexes => teamIndexes.ToList())
.ToList();
foreach (var indexTeam in indexTeams)
for (var i = 1; i < indexTeam.Count; i++)
{
var n = _rand.GetMax(i + 1);
indexTeam.Swap(i, n);
players.Swap(indexTeam[i].Value, indexTeam[n].Value);
}
}
}