From 09e6cb34a11ca25ca848df63aef6c5c02d787a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Tr=C3=B6ster?= Date: Mon, 27 Nov 2023 02:04:20 +0100 Subject: [PATCH] apply convenience functions to game log --- Schafkopf.Lib.Tests/GameLogTest.cs | 19 +++++++++++++---- Schafkopf.Lib.Tests/GameResultTest.cs | 15 ++++++-------- Schafkopf.Lib/GameLog.cs | 30 ++++++++++++++++++++------- Schafkopf.Lib/Rules.cs | 3 +++ Schafkopf.Lib/Turn.cs | 1 + 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/Schafkopf.Lib.Tests/GameLogTest.cs b/Schafkopf.Lib.Tests/GameLogTest.cs index daeea84..bed8504 100644 --- a/Schafkopf.Lib.Tests/GameLogTest.cs +++ b/Schafkopf.Lib.Tests/GameLogTest.cs @@ -73,6 +73,7 @@ public void Test_ApplyCardToHistory_WhenTurnIsNotEmpty(int cardsAlreadyPlayed) int cardPos = cardsAlreadyPlayed; var cardToPlay = initialHands[cardPos].PickRandom(); var turnAfter = history.NextCard(cardToPlay); + if (cardsAlreadyPlayed == 3) turnAfter = history.Turns[0]; turnAfter.Should().Be(history.Turns[0]); turnAfter.CardsCount.Should().Be(turnBefore.CardsCount + 1); @@ -107,10 +108,20 @@ public void Test_HistoryFinalizes_AfterApplyingLastCardOfLastTurn() var initialHands = new Hand[4]; deck.InitialHands(call, initialHands); var history = GameLog.NewLiveGame(call, initialHands, 0); - - foreach (int i in Enumerable.Range(0, 8)) - foreach (int j in Enumerable.Range(0, 4)) - history.NextCard(initialHands[j].PickRandom()); + var rules = new GameRules(); + var cardCache = new Card[8]; + + for (int i = 0; i < 8; i++) + { + for (int j = 0; j < 4; j++) + { + int pid = history.DrawingPlayerId; + var hand = history.HandOfDrawingPlayer; + var possCards = history.CardCount >= 28 ? hand : hand.Where(c => + rules.CanPlayCard(call, c, history.CurrentTurn, hand)); + history.NextCard(possCards.PickRandom()); + } + } history.Turns.Should().Match(turns => turns.All(t => t.CardsCount == 4)); history.TurnCount.Should().Be(8); diff --git a/Schafkopf.Lib.Tests/GameResultTest.cs b/Schafkopf.Lib.Tests/GameResultTest.cs index bfed773..8d6eb90 100644 --- a/Schafkopf.Lib.Tests/GameResultTest.cs +++ b/Schafkopf.Lib.Tests/GameResultTest.cs @@ -128,16 +128,13 @@ private static GameLog playRandomValidGame(GameCall call, Hand[] hands) for (int i = 0; i < 8; i++) { - var turn = log.Turns[i]; - var playersInOrder = Enumerable.Range(0, 4) - .Select(i => (kommtRaus + i) % 4); - - foreach (int pid in playersInOrder) + for (int j = 0; j < 4; j++) { - var possCards = hands[pid].Where(c => - possCardEval.CanPlayCard(call, c, turn, hands[pid])); - possCards = log.TurnCount < 8 ? possCards : hands[pid]; - turn = log.NextCard(possCards.PickRandom()); + int pid = log.DrawingPlayerId; + var hand = log.HandOfDrawingPlayer; + var possCards = log.CardCount >= 28 ? hand : hand.Where(c => + possCardEval.CanPlayCard(call, c, log.CurrentTurn, hand)); + log.NextCard(possCards.PickRandom()); } } diff --git a/Schafkopf.Lib/GameLog.cs b/Schafkopf.Lib/GameLog.cs index 4fec764..9ce4a0c 100644 --- a/Schafkopf.Lib/GameLog.cs +++ b/Schafkopf.Lib/GameLog.cs @@ -98,11 +98,14 @@ private GameLog( InitialHands[i] = initialHands[i]; for (int i = 0; i < 8; i++) Turns[i] = history[i]; + Hands = InitialHands.Select( + h => h.CacheTrumpf(call.IsTrumpf)).ToArray(); } public GameCall Call; public Turn[] Turns; public Hand[] InitialHands; + public Hand[] Hands; public GameSessionMeta Meta; public int TurnCount => (int)Math.Ceiling((double)CardCount / 4); @@ -132,29 +135,38 @@ public int CardCount public void Kontra() => Meta.Kontra(); public void Re() => Meta.Re(); + public Turn CurrentTurn => Turns[CardCount / 4]; + public int DrawingPlayerId => CurrentTurn.DrawingPlayerId; + public Hand HandOfDrawingPlayer => Hands[DrawingPlayerId]; + public Turn NextCard(Card card) { + int p_id = DrawingPlayerId; + Hands[p_id] = Hands[p_id].Discard(card); + int t_id = CardCount / 4; Turns[t_id] = Turns[t_id].NextCard(card); - return Turns[t_id]; + if (CardCount % 4 == 0 && t_id > 0 && t_id < 7) + return Turns[t_id+1] = Turn.InitNextTurn(Turns[t_id]); + else + return Turns[t_id]; } public IEnumerable UnrollActions() { var turnCache = new Card[4]; + var action = new GameAction(); foreach (var turn in Turns) { int p_id = turn.FirstDrawingPlayerId; turn.CopyCards(turnCache); - for (int i = 0; i < 4; i++) + for (int i = 0; i < turn.CardsCount; i++) { var card = turnCache[p_id]; - var action = new GameAction() { - PlayerId = (byte)p_id, - CardPlayed = card - }; + action.PlayerId = (byte)p_id; + action.CardPlayed = card; yield return action; p_id = (p_id + 1) % 4; } @@ -163,13 +175,17 @@ public IEnumerable UnrollActions() public IEnumerable UnrollHands() { + int i = 0; var hands = InitialHands.ToArray(); foreach (var action in UnrollActions()) { + if (i++ >= CardCount) + break; yield return hands[action.PlayerId]; hands[action.PlayerId] = hands[action.PlayerId].Discard(action.CardPlayed); } - yield return hands[0]; + if (CardCount == 32) + yield return Hand.EMPTY; } public IEnumerable UnrollAugen() diff --git a/Schafkopf.Lib/Rules.cs b/Schafkopf.Lib/Rules.cs index d17e061..1ec02a8 100644 --- a/Schafkopf.Lib/Rules.cs +++ b/Schafkopf.Lib/Rules.cs @@ -2,6 +2,9 @@ namespace Schafkopf.Lib; public class GameRules { + public ReadOnlySpan PossibleCards(GameLog log, Card[] cache) + => PossibleCards(log.Call, log.CurrentTurn, log.HandOfDrawingPlayer, cache); + public ReadOnlySpan PossibleCards( GameCall call, Turn currentTurn, Hand playerHand, Card[] cache) { diff --git a/Schafkopf.Lib/Turn.cs b/Schafkopf.Lib/Turn.cs index 317075f..891b2f5 100644 --- a/Schafkopf.Lib/Turn.cs +++ b/Schafkopf.Lib/Turn.cs @@ -98,6 +98,7 @@ public Turn NextCard(Card card) public int FirstDrawingPlayerId => Meta.FirstDrawingPlayerId; public bool AlreadyGsucht => Meta.AlreadyGsucht; + public int DrawingPlayerId => (FirstDrawingPlayerId + CardsCount) % 4; public Card FirstCard => new Card( (byte)((Cards >> (Meta.FirstDrawingPlayerId * CARD_OFFSET))