private async void Team_UnsafePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(Team.TeamHandler)) { if (WriteConsole) { Console.WriteLine("Handler changed. awaiting semaphore..."); } await HandlerSemaphore.WaitAsync(); if (IsGaming) { RaiseFinished(TeamHandler1, TeamHandler2); } TeamHandler1 = Team1.TeamHandler; TeamHandler2 = Team2.TeamHandler; if (IsGaming) { RaiseStarted(TeamHandler1, TeamHandler2); } HandlerSemaphore.Release(); } }
private void StartInternal(CancellationToken cancellationToken) { Field.GetCell(Team1.Agent1.Position).SetState(Teams.Team1, CellState.Occupied); Field.GetCell(Team1.Agent2.Position).SetState(Teams.Team1, CellState.Occupied); Field.GetCell(Team2.Agent1.Position).SetState(Teams.Team2, CellState.Occupied); Field.GetCell(Team2.Agent2.Position).SetState(Teams.Team2, CellState.Occupied); IsGaming = true; RaiseStarted(TeamHandler1, TeamHandler2); Started?.Invoke(this, new EventArgs()); int length = Length; bool infinite = length <= 0; if (infinite) { length = 1; if (WriteConsole) { Console.WriteLine("Game Started : Infinity Turns"); } } else if (WriteConsole) { Console.WriteLine("Game Started : " + length + " Turns"); } if (Abort(cancellationToken, TeamHandler1, TeamHandler2)) { return; } for (Turn = 1; length >= Turn; Turn++) { //TeamHandler1, 2を排他ロックします HandlerSemaphore.Wait(); if (Abort(cancellationToken, TeamHandler1, TeamHandler2)) { return; } if (WriteConsole) { Console.WriteLine("Turn " + Turn); } TurnChanged?.Invoke(this, new EventArgs()); var intents = MakeIntents(Turn, TeamHandler1, TeamHandler2); if (Abort(cancellationToken, TeamHandler1, TeamHandler2)) { return; } IntentResult[] results = new IntentResult[4]; //インテントを受け取って判断(マップの状態が正しいと仮定しています) for (int i = 0; intents.Length > i; i++) { var intent = intents[i]; bool res = intent.Intention == Intentions.Stay; GetParamsForResult(i, out var team, out var current, out var agent); var teamEnum = team == Team1 ? Teams.Team1 : Teams.Team2; var anotherEnum = (Teams.Team1 | Teams.Team2) & ~teamEnum; if (Abort(cancellationToken, TeamHandler1, TeamHandler2)) { return; } if (!res) { Point next = intent.GetNextPoint(current); if (next.X < 0 || next.Y < 0 || next.X >= Field.Width || next.Y >= Field.Height) { throw new Exception($"Invalid intent requested : {next}({intent.Intention}, {intent.Direction})"); } switch (intent.Intention) { case Intentions.Move: current = next; res = true; break; //http://www.procon.gr.jp/wp-content/uploads//2016/12/e017e38ca89f7a0d04d6ad74319ffde0-1.pdf 10ページ目の試合の進行(3).ii.③を参照 case Intentions.Remove: var cell = Field.GetCell(next); var state = cell.GetState(anotherEnum); //敵チームのセル状態が占有かどうかを判定 if (state == CellState.Occupied) { current = next; res = true; } break; } } IntentResult ir = new IntentResult() { Team = team, Agent = agent, Intent = intent, NextPosition = current, Result = res }; results[i] = ir; } if (Abort(cancellationToken, TeamHandler1, TeamHandler2)) { return; } //自分が動けるかをまず確認 foreach (var res in results) { if (res.Intent.Intention == Intentions.Move) { res.Result = this.CanMove(res.Agent, res.Intent.Direction); } else if (res.Intent.Intention == Intentions.Remove) { res.Result = Field.IsInField(res.Agent, res.Intent.Direction); } if (!res.Result) { res.NextPosition = res.Agent.Position; } } var list = results.Where(r => r.Result).ToList(); foreach (var res1 in list) { foreach (var res2 in list) { if (res1 != res2) { bool r1 = false, r2 = false; if (res1.NextPosition == res2.NextPosition) { r1 = true; r2 = true; } if (res2.NextPosition == res1.Agent.Position) { r2 = true; } if (r1) { res1.NextPosition = res1.Agent.Position; res1.Result = false; } if (r2) { res2.NextPosition = res2.Agent.Position; res2.Result = false; } } } } //実際に移動 foreach (var res in results) { if (res.Intent.Intention == Intentions.Move) { res.Agent.Position = res.NextPosition; var team = res.Team == Team1 ? Teams.Team1 : Teams.Team2; var cell = Field.GetCell(res.NextPosition); var state = cell.GetState(team); cell.SetState(team, CellState.Occupied); } } var remList = results.Where(r => r.Intent.Intention == Intentions.Remove).ToList(); var agentPos = GetAgentPositions(Team1.Agent1, Team1.Agent2, Team2.Agent1, Team2.Agent2); //削除ができるものを実際に削除 foreach (var rem in remList.Where(r => r.Result)) { //除去動作は自チームも許可されるため修正 var cell = Field.GetCell(rem.NextPosition); cell.State1 = CellState.None; cell.State2 = CellState.None; } if (Abort(cancellationToken, TeamHandler1, TeamHandler2)) { return; } int intentIndex = 0; InvokeTeams(t => t.TeamHandler.IntentResult(results[intentIndex++].Result, results[intentIndex++].Result)); Result?.Invoke(this, new IntentResultEventArgs(intents, results.Select(r => r.Result).ToArray())); if (infinite) { length++; } HandlerSemaphore.Release(); } IsGaming = false; RaiseFinished(TeamHandler1, TeamHandler2); if (WriteConsole) { Console.WriteLine("Game Finished"); } Finished?.Invoke(this, new EventArgs()); Length = 0; Turn = 0; }