private void StartBattle(PrepareBattle prepareBattle) { uint id = GetBattleId(); Battle battle = new Battle(); battle.Create(prepareBattle, rnd.Next(0, Int32.MaxValue)); battles.Add(id, battle); BattleData data = battle.GetData(); for (int i = 0; i < data.users.Count; i++) { Data.t.netMsg.Add(new MsgServerCreateBattle(data.users[i].userid, battle.GetSeed(), battle.GetSize())); Data.t.netMsg.Add(new MsgServerBattleData(data.users[i].userid, data)); User user = GetUser(data.users[i].userid); if (user != null) { user.isBattle = true; user.battleId = id; Unit unit = user.GetSelectUnit(); unit.RestoreUnitBattle(); unit.pos = battle.GetFreeStartPos(rnd); battle.GetMap().SetUnitPos(unit.pos); unit.dir = rnd.Next(0, 4); Data.t.netMsg.Add(new MsgServerGameAction(user.id, new GameActionVisible(unit, true))); } } }
public void AddUserPrepareBattle(User user, EBattleMode mode) { PrepareBattle prepareBattle = GetPrepareBattle(mode); if (prepareBattle == null) { uint id = CreatePrepareBattle(user, mode); Data.t.netMsg.Add(new MsgServerPrepareBattle(user.id, prepareBattles[id])); return; } Data.t.netMsg.Add(new MsgServerPrepareBattle(user.id, prepareBattle)); }
public uint CreatePrepareBattle(User user, EBattleMode mode) { uint id = GetPrepareBattleId(); PrepareBattle battle = new PrepareBattle() { id = id, time = 10, mode = mode }; battle.users.Add(new PrepareBattleItem(user.id, user.name)); prepareBattles.Add(battle.id, battle); return(id); }
public async Task Run(GameContext context, BaseWorkerWindow vm, Action <string> statusUpdater, CancellationToken cancellationToken) { using (NDC.Push("Arena Worker")) { await Task.CompletedTask; var lobby = new ArenaLobby(context); var matcher = new ArenaMatcher(context); var prepareBattle = new PrepareBattle(context); var lastScore = 0L; var lastCombatScore = 0L; Opponent lastOpponent = null; var combatResults = new List <CombatLogItem>(); var strategies = new List <IArenaStrategy>(); if (!string.IsNullOrEmpty(WorstEnemy)) { strategies.Add(new WorstEnemyArenaStrategy(WorstEnemy, WorstEnemyOnly, WorstEnemyMaxDist)); } if (UseHistory) { strategies.Add(new HistoryArenaStrategy()); } if (UseScore) { strategies.Add(new PowerArenaStrategy()); strategies.Add(new ScoreFallbackArenaStrategy()); } if (strategies.Any()) { strategies.Add(new PowerArenaStrategy()); } var clog = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "logs", "combat.jlog"); if (!Directory.Exists(Path.GetDirectoryName(clog))) { Directory.CreateDirectory(Path.GetDirectoryName(clog)); } if (File.Exists(clog)) { try { combatResults.AddRange(JsonConvert.DeserializeObject <CombatLogItem[]>(File.ReadAllText(clog))); } catch { } } Logger.Info("Created screens, entering main loop."); while (true) { cancellationToken.ThrowIfCancellationRequested(); if (!lobby.IsScreenActive()) { Logger.Fatal("Lobby screen not detected! Bailing out."); throw new InvalidOperationException("Not on the arena lobby screen"); } if (lobby.CurrentScore > MaxScore) { Logger.InfoFormat("Score limit reached (current {0} > max {1}). Bailing out.", lobby.CurrentScore, MaxScore); return; } lastCombatScore = lobby.CurrentScore - lastScore; if (lastScore != 0 && lobby.CurrentScore != 0 && lastOpponent != null) { combatResults.Add( new CombatLogItem { Date = DateTime.UtcNow, Name = lastOpponent.Name, Power = lastOpponent.Power, ScoreChange = lastCombatScore } ); File.WriteAllText(clog, JsonConvert.SerializeObject(combatResults, Formatting.Indented)); } var combatLookup = combatResults.ToLookup(x => x.Name); lastScore = lobby.CurrentScore; cancellationToken.ThrowIfCancellationRequested(); Logger.Info("Switching to matcher screen."); while (true) { do { await lobby.PressBattleButton(cancellationToken); } while (lobby.IsScreenActive()); var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); try { await matcher.Activation(CancellationTokenSource.CreateLinkedTokenSource(cts.Token, cancellationToken).Token); break; } catch (TaskCanceledException) { if (lobby.IsScreenActive()) { continue; } throw; } } if (matcher.TicketsLeft == 0) { await Task.Delay(500, cancellationToken); Logger.Info("Recapture matcher screen due to possible erratic tickets reading."); matcher.IsScreenActive(); } if (matcher.TicketsLeft <= MinTickets) { Logger.InfoFormat("Tickets limit reached (current {0} < min {1}). Bailing out.", matcher.TicketsLeft, MinTickets); return; } Logger.Info("Enabling fast battle."); statusUpdater($"My power {matcher.MyPower.Pretty()}, score {lobby.CurrentScore}. {matcher.TicketsLeft} tickets left."); while (!cancellationToken.IsCancellationRequested) { cancellationToken.ThrowIfCancellationRequested(); Logger.InfoFormat("Matcher screen found opponents {0}; {1}; {2}.", matcher.Opponents[0], matcher.Opponents[1], matcher.Opponents[2]); var opponentsWithHistory = matcher.Opponents.Select( x => { var logs = combatLookup[x.Name].Where(l => Math.Abs(1.0 - (double)l.Power / x.Power) < .1).ToArray(); return(new OpponentWithHistory(x, logs.Length > 0 ? logs.Average(l => l.ScoreChange) : 0)); } ).ToArray(); var engaged = false; foreach (var strategy in strategies) { var result = strategy.SelectOpponent(opponentsWithHistory, matcher.MyPower, lobby.CurrentScore); if (result.Item1 != null) { lastOpponent = result.Item1; matcher.Refresh(); await matcher.ToggleFastBattle(true, cancellationToken); await matcher.EngageOpponent(result.Item1, cancellationToken); engaged = true; break; } if (!result.Item2) { break; } } if (engaged) { break; } Logger.Info("Refreshing matcher as no valid opponents found."); cancellationToken.ThrowIfCancellationRequested(); await matcher.GetNewOpponents(cancellationToken); //await Task.Delay(100, cancellationToken); if (!matcher.IsScreenActive()) { Logger.Fatal("Matcher screen not detected after refresh! Bailing out."); throw new InvalidOperationException("Not on the arena matcher screen"); } } cancellationToken.ThrowIfCancellationRequested(); if (!prepareBattle.IsScreenActive()) { Logger.Fatal("Prepare for battle screen not detected! Bailing out."); throw new InvalidOperationException("Not on the prepare battle screen"); } cancellationToken.ThrowIfCancellationRequested(); Logger.Info("Into the battle!"); await prepareBattle.Engage(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); var ts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); try { await matcher.Activation(CancellationTokenSource.CreateLinkedTokenSource(ts.Token, cancellationToken).Token); } catch (TaskCanceledException) { if (lobby.IsScreenActive()) { continue; } } Logger.Info("Trying to close matcher."); while (true) { cancellationToken.ThrowIfCancellationRequested(); if (matcher.IsScreenActive()) { await matcher.Close(cancellationToken); if (lobby.IsScreenActive()) { Logger.Info("Ok, we're back to lobby."); break; } await Task.Delay(200, cancellationToken); } else if (lobby.IsScreenActive()) { continue; } else { Logger.Fatal("Matcher screen not detected while trying to close it! Bailing out."); throw new InvalidOperationException("Not on the arena matcher screen"); } } await Task.Delay(300, cancellationToken); } } }
void Awake() { instance = this; }