/// <summary> /// Causes a player to join a battle immediately. /// </summary> /// <param name="session">Session of the player.</param> public async Task <BattleResult?> InvokeBattle(Session session) { // WaitHandle would probably have been very useful here... if (await GetPlayer(session) is not Player player) { return(null); } if (player.Deck.Count != 4) { return(null); } // only two taks may run simultaneously await _invokeBattleLimiter.WaitAsync().ConfigureAwait(false); // restrict to serialized execution await _invokeBattleExclusive.WaitAsync(); BattleResult result; if (_firstBattlingPlayer is null) // first player connects { _firstBattlingPlayer = player; _invokeBattleExclusive.Release(); // second player may now join System.Diagnostics.Debug.Assert(_invokeBattleHang.CurrentCount == 0); await _invokeBattleHang.WaitAsync(); // wait until unlocked by second player // invoked after second player finished var resultCopy = _btlResult; _firstBattlingPlayer = null; _btlResult = null; // let others continue _invokeBattleExclusive.Release(); _invokeBattleLimiter.Release(2); // finish first player return(resultCopy); } // cancel battle if against yourself if (_firstBattlingPlayer.Id == player.Id) { result = _btlResult = new BattleResult.Cancelled("The player started a battle against themself."); _invokeBattleHang.Release(); return(result); } System.Diagnostics.Debug.Assert(_invokeBattleExclusive.CurrentCount == 0); // finish second player result = _btlResult = _btl.RunBattle(player, _firstBattlingPlayer); // let other player's task continue _invokeBattleHang.Release(); return(result); }
public void TestWinner() { ICard[] // decks limited to one card to avoid possible infinite loops cards1 = { new NormalSpell { Damage = 10 } }, cards2 = { new NormalSpell { Damage = 1 } }; Player player1 = new Player(Guid.Empty, "Player 1", Array.Empty <byte>(), String.Empty, String.Empty, 0, Array.Empty <ICard>(), cards1, 1000, 0, 0), player2 = new Player(Guid.Empty, "Player 2", Array.Empty <byte>(), String.Empty, String.Empty, 0, Array.Empty <ICard>(), cards2, 1000, 0, 0); var result = _handler.RunBattle(player1, player2); Assert.NotNull(result); Assert.IsInstanceOf <BattleResult.Winner>(result); var win = (BattleResult.Winner)result; Assert.AreEqual(player1, win.WinningPlayer); Assert.AreEqual(player2, win.LosingPlayer); }