// Single-file Kobaltmeer starter; System.Text.Json is provided by .NET itself. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; readonly record struct Point(int X,int Y); static class Program { static int N(JsonElement item,string key)=>item.GetProperty(key).GetInt32(); static Point Pos(JsonElement item)=>new(N(item,"x"),N(item,"y")); static int Distance(Point a,Point b,int size){int x=Math.Abs(a.X-b.X),y=Math.Abs(a.Y-b.Y);return Math.Min(x,size-x)+Math.Min(y,size-y);} static Point Destination(Point p,string action,int size){int x=p.X,y=p.Y;switch(action){case "N":y--;break;case "S":y++;break;case "E":x++;break;case "W":x--;break;}return new((x+size)%size,(y+size)%size);} static object Decide(JsonElement input,HashSet returning){ var rules=input.GetProperty("rules");var state=input.GetProperty("state");int player=N(input,"player"),size=N(rules,"size"),capacity=N(rules,"capacity"); var own=state.GetProperty("players")[player];var yard=new Point(own.GetProperty("yard")[0].GetInt32(),own.GetProperty("yard")[1].GetInt32()); var resource=state.GetProperty("resource");var fleet=state.GetProperty("ships").EnumerateArray().Where(s=>N(s,"owner")==player).OrderByDescending(s=>N(s,"cargo")).ThenBy(s=>N(s,"id")).ToArray(); var harbors=state.GetProperty("sites").EnumerateArray().Where(s=>N(s,"owner")==player).Select(Pos).ToArray(); var occupied=fleet.Select(Pos).ToHashSet();var reserved=new HashSet();var ships=new Dictionary();var debug=new List(); foreach(var ship in fleet){ int id=N(ship,"id"),cargo=N(ship,"cargo");var pos=Pos(ship);occupied.Remove(pos);var home=harbors.OrderBy(h=>Distance(pos,h,size)).First(); if(pos==home)returning.Remove(id); if(cargo>=capacity*3/4 || (cargo>0&&N(rules,"turns")-N(state,"turn")<=Distance(pos,home,size)+6))returning.Add(id); int value=resource[pos.Y][pos.X].GetInt32(),divisor=N(rules,"move_divisor");bool floor=rules.TryGetProperty("floor_move_cost",out var field)&&field.GetBoolean();int fuel=floor?value/divisor:(value+divisor-1)/divisor; string chosen="O";double best=double.NegativeInfinity; foreach(string action in new[]{"O","N","E","S","W"}){var target=Destination(pos,action,size);if((action!="O"&&cargobest){best=score;chosen=action;} } var destination=Destination(pos,chosen,size);reserved.Add(destination);ships[id.ToString(System.Globalization.CultureInfo.InvariantCulture)]=chosen; var goal=returning.Contains(id)?home:destination;debug.Add(new{ship=id,target=new[]{goal.X,goal.Y},reason=returning.Contains(id)?"C#: Fracht abliefern":"C#: Nachbarfeld oder Abbau"}); } bool spawn=fleet.Length<8&&N(state,"turn")*100=N(rules,"ship_cost")&&!reserved.Contains(yard); return new{type="orders",ships,spawn,debug}; } static void Send(object value){Console.WriteLine(JsonSerializer.Serialize(value));Console.Out.Flush();} static int Main(){ Console.InputEncoding=Encoding.UTF8;Console.OutputEncoding=new UTF8Encoding(false); try{string? first=Console.ReadLine();if(first is null)return 1;using var init=JsonDocument.Parse(first);var root=init.RootElement; if(root.GetProperty("type").GetString()!="init"||root.GetProperty("protocol").GetString()!="kobaltmeer-bot-v1")return 2; ulong seed=root.GetProperty("seed").GetUInt64();_ = seed; // Use this seed if you add randomness. Send(new{type="ready",name="C# Sammler"});var returning=new HashSet(); while(Console.ReadLine() is string line){using var doc=JsonDocument.Parse(line);if(doc.RootElement.GetProperty("type").GetString()=="close")break;Send(Decide(doc.RootElement,returning));} return 0; }catch(Exception error){Console.Error.WriteLine(error.Message);return 1;} } }