using System.Text.Json; using GameCli; // Deterministic PRNG for start-pose randomization on reset. // Seeded fresh on each reset if the caller supplies a seed. var rng = new Random(); // Current world state and step counter. Reset on {"cmd":"reset"}. var ship = ShipState.AtCenter(); int stepCount = 0; int lastAction = 0; // --- Startup handshake --------------------------------------------------- var init = new InitMessage { Init = new InitPayload { World = new[] { 1f, 1f }, Dt = Physics.Dt, ObsDim = Observation.Dim, NActions = 4, }, }; Console.WriteLine(JsonSerializer.Serialize(init, ProtocolJsonContext.Default.InitMessage)); Console.Out.Flush(); // --- Read-line loop ------------------------------------------------------ string? line; while ((line = Console.In.ReadLine()) is not null) { if (line.Length == 0) continue; StepInput? input; try { input = JsonSerializer.Deserialize(line, ProtocolJsonContext.Default.StepInput); } catch (JsonException ex) { Console.Error.WriteLine($"invalid json: {ex.Message}"); continue; } if (input is null) continue; // Reset command. if (input.Cmd == "reset") { if (input.Seed is int seed) rng = new Random(seed); ship = RandomStartPose(rng); stepCount = 0; lastAction = 0; WriteObservation((0.5f, 0.5f), reward: 0f, done: false); continue; } // Step command. int action = input.Action ?? 0; var target = (input.Target is { Length: >= 2 }) ? (input.Target[0], input.Target[1]) : (0.5f, 0.5f); ship = Physics.Step(ship, action); lastAction = action; stepCount++; float reward = Reward.Compute(ship, target, action); WriteObservation(target, reward, done: false); } // --- Helpers ------------------------------------------------------------- void WriteObservation((float X, float Y) target, float reward, bool done) { var output = new StepOutput { Obs = Observation.Build(ship, target), State = new ShipStateDto { X = ship.X, Y = ship.Y, Angle = ship.Angle, Engine = lastAction, }, Reward = reward, Done = done, Step = stepCount, }; Console.WriteLine(JsonSerializer.Serialize(output, ProtocolJsonContext.Default.StepOutput)); Console.Out.Flush(); } static ShipState RandomStartPose(Random rng) { // Random position in a comfortable box; zero velocity, near-upright. float x = 0.2f + (float)rng.NextDouble() * 0.6f; float y = 0.2f + (float)rng.NextDouble() * 0.4f; float angle = ((float)rng.NextDouble() - 0.5f) * 0.4f; // ±0.2 rad return new ShipState(x, y, 0f, 0f, angle, 0f); }