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>
240 lines
9.1 KiB
C#
240 lines
9.1 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace Luneraria.Core
|
|
{
|
|
public enum Phase { Planning, Combat, Over }
|
|
|
|
/// <summary>One persistent troop of a player (committed roster or planning draft).</summary>
|
|
public sealed class RosterEntry
|
|
{
|
|
/// <summary>"p{slot}-{seq}": unique per match; ownership is the slot in the uid.</summary>
|
|
public string Uid = "";
|
|
public int Seq;
|
|
public string TypeId = "";
|
|
/// <summary>top, mid, bot or grotto (one round).</summary>
|
|
public string Lane = "";
|
|
public int Invested;
|
|
/// <summary>Bought in the current planning (full refund on sale).</summary>
|
|
public bool Fresh;
|
|
|
|
public RosterEntry Clone() { return (RosterEntry)MemberwiseClone(); }
|
|
}
|
|
|
|
/// <summary>The single hero of a player.</summary>
|
|
public sealed class HeroState
|
|
{
|
|
public string Uid = "";
|
|
public int Seq;
|
|
public string HeroId = "";
|
|
public string Lane = "";
|
|
public int Xp;
|
|
public List<string> Items = new List<string>();
|
|
public List<string> Talents = new List<string>();
|
|
public int Invested;
|
|
public bool Fresh;
|
|
/// <summary>Items bought in the current planning (full refund on sale).</summary>
|
|
public List<string> FreshItems = new List<string>();
|
|
/// <summary>Trigger rule of the ultimate (H1), "" = the hero's default rule.</summary>
|
|
public string Ultimate = "";
|
|
|
|
public HeroState Clone()
|
|
{
|
|
var copy = (HeroState)MemberwiseClone();
|
|
copy.Items = new List<string>(Items);
|
|
copy.Talents = new List<string>(Talents);
|
|
copy.FreshItems = new List<string>(FreshItems);
|
|
return copy;
|
|
}
|
|
}
|
|
|
|
/// <summary>An attack champion booking: bought in round n, fights once in round n + 1.</summary>
|
|
public sealed class Booking
|
|
{
|
|
public string Uid = "";
|
|
public int Seq;
|
|
public string ChampionId = "";
|
|
public string Lane = "";
|
|
public int Cost;
|
|
/// <summary>0 while uncommitted (draft); the round it fights in once committed.</summary>
|
|
public int DeployRound;
|
|
|
|
public Booking Clone() { return (Booking)MemberwiseClone(); }
|
|
}
|
|
|
|
/// <summary>Private planning of one player; validated and committed atomically at combat start.</summary>
|
|
public sealed class Draft
|
|
{
|
|
public int Gold;
|
|
public List<RosterEntry> Roster = new List<RosterEntry>();
|
|
public int NextSeq;
|
|
public HeroState Hero;
|
|
public List<Booking> NewBookings = new List<Booking>();
|
|
/// <summary>Lane chosen by the boss chooser in this planning, "" if unchanged.</summary>
|
|
public string BossLane = "";
|
|
|
|
public Draft Clone()
|
|
{
|
|
var copy = new Draft { Gold = Gold, NextSeq = NextSeq, BossLane = BossLane, Hero = Hero != null ? Hero.Clone() : null };
|
|
foreach (RosterEntry entry in Roster)
|
|
copy.Roster.Add(entry.Clone());
|
|
foreach (Booking booking in NewBookings)
|
|
copy.NewBookings.Add(booking.Clone());
|
|
return copy;
|
|
}
|
|
}
|
|
|
|
/// <summary>One of six seats. Team = slot / 3, lane = slot % 3 (top, mid, bot).</summary>
|
|
public sealed class Player
|
|
{
|
|
public int Slot;
|
|
public int Team;
|
|
public string Lane = "";
|
|
public bool IsHuman;
|
|
public string Name = "";
|
|
public string Bund = "";
|
|
public int Gold;
|
|
public List<RosterEntry> Roster = new List<RosterEntry>();
|
|
public HeroState Hero;
|
|
public List<Booking> Bookings = new List<Booking>();
|
|
public bool Ready;
|
|
public int Earned;
|
|
public int Spent;
|
|
public int NextSeq;
|
|
public Draft Draft;
|
|
public List<Draft> Undo = new List<Draft>();
|
|
}
|
|
|
|
public sealed class BossClaim
|
|
{
|
|
public int Team;
|
|
public int WonRound;
|
|
public int DeployRound;
|
|
public int ChooserSlot;
|
|
public string Lane = "";
|
|
|
|
public BossClaim Clone() { return (BossClaim)MemberwiseClone(); }
|
|
}
|
|
|
|
/// <summary>Public boss state: the grotto opens from NextAvailableRound; Claim is null or the conquest.</summary>
|
|
public sealed class BossState
|
|
{
|
|
public int NextAvailableRound = 1;
|
|
public BossClaim Claim;
|
|
/// <summary>Round whose settlement was already applied (idempotence), 0 = none.</summary>
|
|
public int SettledRound;
|
|
}
|
|
|
|
public sealed class BossLogEntry
|
|
{
|
|
public int Round;
|
|
/// <summary>deployed, won or failed.</summary>
|
|
public string Event = "";
|
|
public int Team = -1;
|
|
public string Lane = "";
|
|
public int Chooser = -1;
|
|
}
|
|
|
|
/// <summary>Public announcement of the current round: a champion or the deployed boss.</summary>
|
|
public sealed class Announcement
|
|
{
|
|
/// <summary>champion or boss.</summary>
|
|
public string Kind = "";
|
|
public int Team;
|
|
public int Slot;
|
|
public string Lane = "";
|
|
public string ChampionId = "";
|
|
public int Bounty;
|
|
}
|
|
|
|
public sealed class Settlement
|
|
{
|
|
public int Round;
|
|
public int[] Gains = new int[6];
|
|
public int Income;
|
|
public List<string> BuildingsLost = new List<string>();
|
|
public string EndReason = "";
|
|
public double CombatTime;
|
|
public OrderedMap<string, int> LaneKills = new OrderedMap<string, int>();
|
|
public OrderedMap<string, int> Xp = new OrderedMap<string, int>();
|
|
/// <summary>none, won, failed, deployed or repeat.</summary>
|
|
public string Boss = "none";
|
|
}
|
|
|
|
public sealed class HistoryEntry
|
|
{
|
|
public int Round;
|
|
public string EndReason = "";
|
|
public double CombatTime;
|
|
public int[] Buildings = new int[2];
|
|
public int[] Gold = new int[6];
|
|
public List<string> Lost = new List<string>();
|
|
public string Boss = "";
|
|
public int[] HeroLevels = new int[6];
|
|
}
|
|
|
|
public sealed class MatchOptions
|
|
{
|
|
public int Seed = 1;
|
|
/// <summary>-1 for six bots.</summary>
|
|
public int HumanSlot = 1;
|
|
/// <summary>Six Bünde; missing entries follow the seed.</summary>
|
|
public List<string> Bunds = new List<string>();
|
|
/// <summary>Optional fixed bot profile per slot (balance runs).</summary>
|
|
public List<string> Profiles = new List<string>();
|
|
}
|
|
|
|
/// <summary>Bot-private notes per slot, derived only from its own actions and public outcomes.</summary>
|
|
public sealed class BotMemory
|
|
{
|
|
public bool HasChampionRound;
|
|
public int ChampionRound;
|
|
public bool HasBossFields;
|
|
public double Bar;
|
|
public int Sent;
|
|
}
|
|
|
|
public struct CommandResult
|
|
{
|
|
public bool Ok;
|
|
public string Message;
|
|
|
|
public CommandResult(bool ok, string message)
|
|
{
|
|
Ok = ok;
|
|
Message = message;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A player's intent during planning. Clients only ever send these; the authority applies
|
|
/// them through LuneMatch.Submit. Null fields mean "not given" (e.g. buy without lane uses
|
|
/// the player's own lane).
|
|
/// </summary>
|
|
public sealed class Command
|
|
{
|
|
public string Type = "";
|
|
public string TypeId;
|
|
public string Lane;
|
|
public string Uid;
|
|
public string HeroId;
|
|
public string ItemId;
|
|
public string ChampionId;
|
|
public int? Tier;
|
|
public int? Choice;
|
|
|
|
public static Command Buy(string typeId, string lane = null) { return new Command { Type = "buy", TypeId = typeId, Lane = lane }; }
|
|
public static Command Upgrade(string uid) { return new Command { Type = "upgrade", Uid = uid }; }
|
|
public static Command Sell(string uid) { return new Command { Type = "sell", Uid = uid }; }
|
|
public static Command Assign(string uid, string lane) { return new Command { Type = "assign", Uid = uid, Lane = lane }; }
|
|
public static Command HeroBuy(string heroId) { return new Command { Type = "hero_buy", HeroId = heroId }; }
|
|
public static Command HeroCancel() { return new Command { Type = "hero_cancel" }; }
|
|
public static Command ItemBuy(string itemId, string uid = null) { return new Command { Type = "item_buy", ItemId = itemId, Uid = uid }; }
|
|
public static Command ItemSell(string itemId) { return new Command { Type = "item_sell", ItemId = itemId }; }
|
|
public static Command Talent(int tier, int choice) { return new Command { Type = "talent", Tier = tier, Choice = choice }; }
|
|
public static Command ChampionBook(string championId, string lane = null) { return new Command { Type = "champion_book", ChampionId = championId, Lane = lane }; }
|
|
public static Command ChampionCancel(string uid) { return new Command { Type = "champion_cancel", Uid = uid }; }
|
|
public static Command BossLaneChoice(string lane) { return new Command { Type = "boss_lane", Lane = lane }; }
|
|
/// <summary>H1: trigger rule of the hero's ultimate; the rule id travels in TypeId.</summary>
|
|
public static Command UltimateRule(string rule) { return new Command { Type = "ultimate_rule", TypeId = rule }; }
|
|
}
|
|
}
|