public string Print(bool territoryOnly = false) { const string tc = "ABCDEF"; using (var writer = new StringWriter()) { writer.WriteLine($"score: {string.Join(",", players.Select(x => x.score))}"); writer.WriteLine($"territory: {string.Join(",", players.Select(x => x.territory))}"); writer.WriteLine($"nitroLeft: {string.Join(",", players.Select(x => x.nitroLeft))}"); writer.WriteLine($"slowLeft: {string.Join(",", players.Select(x => x.slowLeft))}"); writer.WriteLine($"nitrosCollected: {string.Join(",", players.Select(x => x.nitrosCollected))}"); writer.WriteLine($"slowsCollected: {string.Join(",", players.Select(x => x.slowsCollected))}"); writer.WriteLine($"sawsCollected: {string.Join(",", players.Select(x => x.sawsCollected))}"); writer.WriteLine($"opponentTerritoryCaptured: {string.Join(",", players.Select(x => x.opponentTerritoryCaptured))}"); writer.WriteLine($"lineCount: {string.Join(",", players.Select(x => x.lineCount))}"); for (var y = Env.Y_CELLS_COUNT - 1; y >= 0; y--) { for (var x = 0; x < Env.X_CELLS_COUNT; x++) { var c = (ushort)(y * Env.X_CELLS_COUNT + x); var player = -1; for (var p = 0; p < players.Length; p++) { if (players[p].status != PlayerStatus.Eliminated && (players[p].pos == c || players[p].arrivePos == c)) { player = p; break; } } var tomb = false; for (var p = 0; p < players.Length; p++) { if (players[p].status == PlayerStatus.Eliminated && (players[p].pos == c || players[p].arrivePos == c)) { tomb = true; break; } } Bonus bonus = null; for (var b = 0; b < bonusCount; b++) { if (bonuses[b].pos == c) { bonus = bonuses[b]; break; } } if (territoryOnly) { if (territory[c] == 0xFF) { writer.Write('.'); } else { writer.Write(tc[territory[c]]); } } else { if (bonus?.type == BonusType.N) { writer.Write('N'); } else if (bonus?.type == BonusType.S) { writer.Write('S'); } else if (bonus?.type == BonusType.Saw) { writer.Write('W'); } else if (player != -1) { writer.Write(player); } else if (tomb) { writer.Write('*'); } else if (lines[c] != 0) { writer.Write('x'); } else if (territory[c] == 0xFF) { writer.Write('.'); } else { writer.Write(tc[territory[c]]); } } } writer.WriteLine(); } return(writer.ToString()); } }
public void SetInput(RequestInput input, string my = "i") { if (players == null) { players = new Player[input.players.Count]; territory = new byte[Env.CELLS_COUNT]; lines = new byte[Env.Y_CELLS_COUNT * Env.X_CELLS_COUNT]; undos = new UndoPool(players.Length); } isGameOver = false; capture.Init(players.Length); time = input.tick_num; playersLeft = input.players.Count; for (var c = 0; c < Env.CELLS_COUNT; c++) { territory[c] = 0xFF; lines[c] = 0; } var keys = new[] { my }.Concat(input.players.Keys.Where(k => k != my)).ToList(); for (var i = 0; i < players.Length; i++) { var key = i < keys.Count ? keys[i] : "unknown"; if (players[i] == null) { players[i] = new Player(); } if (!input.players.TryGetValue(key, out var playerData)) { players[i].status = PlayerStatus.Eliminated; } else { var accel = 0; if (playerData.bonuses.Any(b => b.type == BonusType.N)) { accel++; } if (playerData.bonuses.Any(b => b.type == BonusType.S)) { accel--; } var speed = accel == 0 ? Env.SPEED : accel == -1 ? Env.SLOW_SPEED : accel == 1 ? Env.NITRO_SPEED : throw new InvalidOperationException(); var v = playerData.position; var arriveTime = 0; while (!v.InCellCenter()) { v += GetShift(playerData.direction ?? throw new InvalidOperationException(), speed); arriveTime++; } players[i].arrivePos = v.ToCellCoords().ToCoord(); if (arriveTime == 0) { players[i].pos = players[i].arrivePos; } else { players[i].pos = players[i].arrivePos.NextCoord((Direction)(((int)(playerData.direction ?? throw new InvalidOperationException()) + 2) % 4)); } players[i].status = playerData.direction == null && i != 0 ? PlayerStatus.Broken : PlayerStatus.Active; players[i].dir = playerData.direction; players[i].score = playerData.score; players[i].shiftTime = accel == 0 ? Env.TICKS_PER_REQUEST : accel == -1 ? Env.SLOW_TICKS_PER_REQUEST : accel == 1 ? Env.NITRO_TICKS_PER_REQUEST : throw new InvalidOperationException(); players[i].arriveTime = arriveTime; players[i].slowLeft = playerData.bonuses.FirstOrDefault(b => b.type == BonusType.S)?.ticks ?? 0; players[i].nitroLeft = playerData.bonuses.FirstOrDefault(b => b.type == BonusType.N)?.ticks ?? 0; players[i].lineCount = playerData.lines.Length; players[i].territory = playerData.territory.Length; players[i].slowsCollected = 0; players[i].nitrosCollected = 0; players[i].sawsCollected = 0; players[i].killedBy = 0; players[i].opponentTerritoryCaptured = 0; for (var k = 0; k < playerData.lines.Length; k++) { var lv = playerData.lines[k].ToCellCoords().ToCoord(); players[i].line[k] = lv; lines[lv] = (byte)(lines[lv] | (1 << i)); } for (var k = 0; k < playerData.territory.Length; k++) { var lv = playerData.territory[k].ToCellCoords().ToCoord(); territory[lv] = (byte)i; } } } if (bonuses == null || bonuses.Length < input.bonuses.Length) { bonuses = new Bonus[input.bonuses.Length]; } bonusCount = 0; for (var i = 0; i < input.bonuses.Length; i++) { bonuses[bonusCount++] = new Bonus(input.bonuses[i]); } V GetShift(Direction direction, int d) => direction == Direction.Up ? V.Get(0, d) : direction == Direction.Down ? V.Get(0, -d) : direction == Direction.Right ? V.Get(d, 0) : direction == Direction.Left ? V.Get(-d, 0) : throw new InvalidOperationException($"Unknown direction: {direction}"); }