champions-of-luneraria/tools/dotnet/Luneraria.Balance/Program.cs
Martin Stickelbroeck 60992f1091 H1A Sylvara: Kernregeln, Ultimate-Auslöser, Netz, Bot-Profil, Prüfsuite
Sylvara (held_sylvara) als vierter Held nach der Referenz: Mondsprung,
Sichelwurf, Mondsicheltanz mit in der Planung gewählter Auslöseregel,
Mondschleier-Schild, Talente Mondsilber/Sichelsturm und Neumond/Vollmond.
Befehl ultimate_rule, HeroState.Ultimate und UnitDef.UltimateRule im Netz,
Sprung-/Ultimate-Zähler in den Flag-Bits des Kampf-Frames. Bot-Profil
assassine außerhalb der Seed-Rotation. Golden 0 Abweichungen, h1 35/35.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:12:02 +02:00

72 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Luneraria.Core;
/// <summary>
/// H1 balance runs. Every hero gets the same probe bot (shares of "ausgewogen", same items,
/// first talent choices, recruited in round 3) on slot 0 or slot 3; the other five slots are
/// fixed reference profiles with Ringborke's probe on the opposite seat. Reports the win rate
/// of the probe seat per hero over many seeds and both sides, plus how often Sylvara leaps and
/// releases her ultimate. Usage: dotnet run -c Release --project tools/dotnet/Luneraria.Balance [seeds]
/// </summary>
public static class Program
{
static readonly string[] Heroes = { "held_ringborke", "held_quellgeflecht", "held_funkenlanze", "held_sylvara" };
public static int Main(string[] args)
{
int seeds = args.Length > 0 ? int.Parse(args[0], CultureInfo.InvariantCulture) : 40;
BotProfile reference = ContentData.BotProfiles["ausgewogen"];
foreach (string hero in Heroes)
{
ContentData.ExtraBotProfiles["probe_" + hero] = new BotProfile
{
Name = "probe_" + hero, Front = reference.Front, Melee = reference.Melee, Ranged = reference.Ranged, Splash = reference.Splash,
Support = reference.Support, UpgradeFrom = reference.UpgradeFrom, SupportLane = 0.0, Hero = hero, HeroRound = 3,
Items = new[] { "glutklinge", "basaltschild", "funkenfokus" }, TalentChoices = new[] { 0, 0 }, Champion = "",
};
}
Console.WriteLine("hero; seat wins; losses; draws; open; win rate; mean rounds; leaps/combat; ultimates/combat");
foreach (string hero in Heroes)
{
int wins = 0, losses = 0, draws = 0, open = 0, rounds = 0, combats = 0, leaps = 0, ults = 0;
for (int seed = 1; seed <= seeds; seed++)
{
for (int side = 0; side < 2; side++)
{
var profiles = new List<string> { "probe_held_ringborke", "druck", "fernkampf", "probe_held_ringborke", "druck", "fernkampf" };
profiles[side * 3] = "probe_" + hero;
var match = new LuneMatch();
match.Setup(new MatchOptions { Seed = seed, HumanSlot = -1, Profiles = profiles });
while (match.Phase != Phase.Over && match.RoundNumber <= 80)
{
for (int slot = 0; slot < 6; slot++)
LuneBot.Plan(match, slot);
match.BeginCombat();
match.FinishCombat();
combats++;
foreach (LuneUnit unit in match.Combat.Units)
{
if (unit.Kind == "hero" && unit.OwnerSlot == side * 3)
{
leaps += unit.LeapSerial;
ults += unit.UltimateSerial;
}
}
}
rounds += match.RoundNumber;
if (match.Phase != Phase.Over) open++;
else if (match.Winner == side) wins++;
else if (match.Winner == LuneMatch.Draw) draws++;
else losses++;
}
}
int games = seeds * 2;
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}; {1}; {2}; {3}; {4}; {5:P0}; {6:F1}; {7:F2}; {8:F2}",
hero, wins, losses, draws, open, (double)wins / Math.Max(1, wins + losses + draws), (double)rounds / games, (double)leaps / combats, (double)ults / combats));
}
return 0;
}
}