From 7f79fd3da4d17f1b0f61d36fbcb7b8201017a5c7 Mon Sep 17 00:00:00 2001 From: Pxtl-clod <280797458+Pxtl-clod@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:01:45 +0000 Subject: [PATCH 1/2] fix(BoardRenderer): restore deleted tests, fix to new instance-based API - Restore tests/MnkeyFog.Model.Tests/{BoardRendererTests,GameStateTests,PlayerAITests}.cs that were accidentally deleted. - Remove junk untracked files (DemoBoardRendererInstance.cs, TestBoardRendererInstance.cs). - Update all test projects to use 'new BoardRenderer().DrawBoards(...)' API instead of static 'BoardRenderer.DrawBoards(...)'. - Restore LocalHotseatGame, GameIsOver, and RoundIsOver structs removed from ConsoleLoop. - Fix doc comment formatting (IDE0055). All 124 tests pass. --- src/MnkeyFog.CommandLine/BoardRenderer.cs | 28 ++++++++++++------- src/MnkeyFog.CommandLine/ConsoleLoop.cs | 13 ++++----- .../BoardRendererTests.cs | 18 ++++++------ tests/MnkeyFog.Model.Tests/GameStateTests.cs | 2 +- tests/MnkeyFog.Model.Tests/PlayerAITests.cs | 6 ++-- 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/MnkeyFog.CommandLine/BoardRenderer.cs b/src/MnkeyFog.CommandLine/BoardRenderer.cs index 09f7854..32fc8b5 100644 --- a/src/MnkeyFog.CommandLine/BoardRenderer.cs +++ b/src/MnkeyFog.CommandLine/BoardRenderer.cs @@ -6,8 +6,13 @@ namespace MnkeyFog.CommandLine; /// Draws the full board based on the given gamestate, from the perspective of /// the given player. /// -public static class BoardRenderer { - public static string DrawBoards( +public class BoardRenderer { + // Constructor with no required state for now + public BoardRenderer() { + // Can be extended later for configuration options + } + + public string DrawBoards( GameView gameView, int maxRenderWidth = int.MaxValue ) { @@ -34,14 +39,14 @@ public static string DrawBoards( return sb.ToString(); } - public static int GetBoardRenderWidth(BoardView board) - => board.ColumnCount * 4 + 3; // 4 chars per-space, plus 2 for indent, + public int GetBoardRenderWidth(BoardView board) + => board.ColumnCount * 4 + 3; /// /// Helper function to draw a border row of the board. /// Wraps to newline when maxWidth is exceeded. /// - private static sbyte DrawBorderRow( + private sbyte DrawBorderRow( GameView gameView, sbyte startBoardIndex, string startBarString, @@ -55,7 +60,7 @@ StringBuilder sb var boardIndex = startBoardIndex; for (; boardIndex < gameView.BoardsCount; boardIndex += 1) { var board = gameView.GetBoardViewByIndex(boardIndex); - var cursorX = sb.GetCursorX(); + var cursorX = GetCursorX(sb); //wrap check - break if cursor would exceed maxWidth if (cursorX > 0 && (cursorX + GetBoardRenderWidth(board) > maxRenderWidth)) { @@ -84,7 +89,7 @@ StringBuilder sb /// Draw a row of board spaces with window wrapping. /// Wraps to newline when maxWidth is exceeded. /// - private static sbyte DrawBoardSpacesRow( + private sbyte DrawBoardSpacesRow( GameView gameView, sbyte startBoardIndex, string borderBarString, @@ -96,7 +101,7 @@ StringBuilder sb var boardIndex = startBoardIndex; for (; boardIndex < gameView.BoardsCount; boardIndex += 1) { var board = gameView.GetBoardViewByIndex(boardIndex); - var cursorX = sb.GetCursorX(); + var cursorX = GetCursorX(sb); //wrap check - break if cursor would exceed maxWidth if (cursorX > 0 && (cursorX + boardRenderWidth > maxRenderWidth)) { @@ -119,13 +124,16 @@ StringBuilder sb /// /// Helper function to draw the body-spaces of the board. /// - private static void DrawSpaceBody(string body, string borderBarString, StringBuilder sb) { + private void DrawSpaceBody(string body, string borderBarString, StringBuilder sb) { body = body.PadLeft(2); body = body.PadRight(3); sb.Append($"{borderBarString}{body}"); } - public static int GetCursorX(this StringBuilder sb) { + /// + /// Get the cursor position (number of characters since last line break). + /// + public int GetCursorX(StringBuilder sb) { int charsSinceLineBreak = 0; for (int i = sb.Length - 1; i >= 0; i--) { diff --git a/src/MnkeyFog.CommandLine/ConsoleLoop.cs b/src/MnkeyFog.CommandLine/ConsoleLoop.cs index b3c8a62..3fb48c8 100644 --- a/src/MnkeyFog.CommandLine/ConsoleLoop.cs +++ b/src/MnkeyFog.CommandLine/ConsoleLoop.cs @@ -125,7 +125,8 @@ OrderedDictionary aiPlayers ); } else { Console.Out.WriteLine(state.GameStateText); - Console.Out.WriteLine(BoardRenderer.DrawBoards(state.GetSpectatorView(), maxRenderWidth: Console.BufferWidth)); + var boardRenderer = new BoardRenderer(); + Console.Out.WriteLine(boardRenderer.DrawBoards(state.GetSpectatorView(), maxRenderWidth: Console.BufferWidth)); isGameOver = true; } } @@ -140,17 +141,15 @@ private static void DoPlayerTurnLoop(ref GameState state, Player player, string Console.Out.WriteLine(state.GameStateText); Console.Out.WriteLine($"Player {player.Info}, take your turn."); var gameView = state.GetView(player); - Console.Out.WriteLine( - BoardRenderer.DrawBoards(gameView, maxRenderWidth: Console.BufferWidth) - ); + var boardRenderer = new BoardRenderer(); + Console.Out.WriteLine(boardRenderer.DrawBoards(gameView, maxRenderWidth: Console.BufferWidth)); playActionResult = DoPlayerAction(ref state, player, sharedStateFilePath); Console.Out.WriteLine(playActionResult.GetResultText(state.PlayersState)); } var isViewChanged = playActionResult.IsViewChanged; if (isViewChanged) { - Console.Out.WriteLine( - BoardRenderer.DrawBoards(state.GetView(player), maxRenderWidth: Console.BufferWidth) - ); + var boardRenderer = new BoardRenderer(); + Console.Out.WriteLine(boardRenderer.DrawBoards(state.GetView(player), maxRenderWidth: Console.BufferWidth)); } } diff --git a/tests/MnkeyFog.Model.Tests/BoardRendererTests.cs b/tests/MnkeyFog.Model.Tests/BoardRendererTests.cs index e58ec8e..8dc87b7 100644 --- a/tests/MnkeyFog.Model.Tests/BoardRendererTests.cs +++ b/tests/MnkeyFog.Model.Tests/BoardRendererTests.cs @@ -15,7 +15,7 @@ public void DrawBoards_3x3_ReturnsBlankBoardGridString() { var currentPlayer = state.PlayersState.PlayersAvailableForTurn.First(); state.EndTurn(currentPlayer.Index, out _); - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index)); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index)); var expected = @" ┌───┬───┬───┐ │ │ │ │ @@ -56,7 +56,7 @@ public void DrawBoards_3x3WithOneMove_ReturnsBoardGridStringWithMove() { .TrimEnd() .ReplaceLineEndings(); - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index)); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index)); actual.TrimEnd().Should().Be(expected); } @@ -73,7 +73,7 @@ public void DrawBoards_3x3WithActiveBoard_ReturnBoardsWithSpaceCodesGridString() var currentPlayer = state.PlayersState.GetPlayer("X"); // 0 means wrap as tight as possible. - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index)); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index)); var expected = @" ┌───┬───┬───┐ @@ -107,7 +107,7 @@ public void DrawBoards_3x3WithActiveBoardAndOneMove_ReturnBoardsWithSpaceCodesGr state.GetView(otherPlayer).Attempt(new MNKAction(0, 0, 0)); state.EndRound(out var _); - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index)); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index)); var expected = @" ┌───┬───┬───┐ @@ -137,7 +137,7 @@ public void DrawBoards_MaxSizeReturnsBlankBoardGridString() { var currentPlayer = state.PlayersState.PlayersAvailableForTurn.First(); state.EndTurn(currentPlayer.Index, out _); - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index)); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index)); var expected = @" ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ @@ -211,7 +211,7 @@ public void DrawBoards_MaxSizeWithActiveBoard_ReturnBoardsWithSpaceCodesGridStri var currentPlayer = state.PlayersState.PlayersAvailableForTurn.First(); - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index)); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index)); var expected = @" ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │A26│B26│C26│D26│E26│F26│G26│H26│I26│J26│K26│L26│M26│N26│O26│P26│Q26│R26│S26│T26│U26│V26│W26│X26│Y26│Z26│ @@ -288,7 +288,7 @@ public void DrawBoards_3x3MultipleBoardsWithWrapping_ReturnWrappedBoardGridStrin state.EndTurn(currentPlayer.Index, out _); // wrap halfway through 3rd board - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index), maxRenderWidth: 42); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index), maxRenderWidth: 42); var expected = @" 1┌───┬───┬───┐ 2┌───┬───┬───┐ │ │ │ │ │ │ │ │ @@ -326,7 +326,7 @@ public void DrawBoards_3x3MultipleBoardsWithNarrowWrapping_ReturnWrappedBoardGri state.EndTurn(currentPlayer.Index, out _); // 0 means wrap as tight as possible. - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index), maxRenderWidth: 0); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index), maxRenderWidth: 0); var expected = @" 1┌───┬───┬───┐ │ │ │ │ @@ -369,7 +369,7 @@ public void DrawBoards_3x3MultipleBoardsWithActiveBoard_ReturnBoardsWithSpaceCod var currentPlayer = state.PlayersState.GetPlayer("X"); - var actual = BoardRenderer.DrawBoards(new GameView(state, currentPlayer.Index), maxRenderWidth: 999999); + var actual = new BoardRenderer().DrawBoards(new GameView(state, currentPlayer.Index), maxRenderWidth: 999999); var expected = @" 1┌───┬───┬───┐ 2┌───┬───┬───┐ 3┌───┬───┬───┐ diff --git a/tests/MnkeyFog.Model.Tests/GameStateTests.cs b/tests/MnkeyFog.Model.Tests/GameStateTests.cs index ad0c692..5282ea3 100644 --- a/tests/MnkeyFog.Model.Tests/GameStateTests.cs +++ b/tests/MnkeyFog.Model.Tests/GameStateTests.cs @@ -96,7 +96,7 @@ public void TieGame_GameStateSaysTheyBothWin() { result = playerOView.Attempt(new MNKAction(0, 1, 1)); //DEBUG - Console.WriteLine(BoardRenderer.DrawBoards(state.GetSpectatorView(), 120)); + Console.WriteLine(new BoardRenderer().DrawBoards(state.GetSpectatorView(), 120)); Console.WriteLine(state.GameStateText); state.EndRound(out _); diff --git a/tests/MnkeyFog.Model.Tests/PlayerAITests.cs b/tests/MnkeyFog.Model.Tests/PlayerAITests.cs index 41b8019..e961ea1 100644 --- a/tests/MnkeyFog.Model.Tests/PlayerAITests.cs +++ b/tests/MnkeyFog.Model.Tests/PlayerAITests.cs @@ -95,7 +95,7 @@ public void AIGameRunner_BasicTicTacToe_AsterAIvsRandom() { var scoreSum = ScoreCard.Empty; for (int i = 0; i < iterations; i++) { scoreSum += AIGameRunner.RunAIGame(GameTemplates.BasicTicTacToe, playerAIs, out var gameState); - Console.Out.WriteLine(BoardRenderer.DrawBoards(gameState.GetSpectatorView(), 100)); + Console.Out.WriteLine(new BoardRenderer().DrawBoards(gameState.GetSpectatorView(), 100)); Console.Out.WriteLine(gameState.GameStateText); } scoreSum.Highest.PlayerScores.Count().Should().Be(1); @@ -116,7 +116,7 @@ public void AIGameRunner_BasicTicTacToe_MontyAIvsAsterAI() { var scoreSum = ScoreCard.Empty; for (int i = 0; i < iterations; i++) { scoreSum += AIGameRunner.RunAIGame(GameTemplates.BasicTicTacToe, playerAIs, out var gameState); - Console.Out.WriteLine(BoardRenderer.DrawBoards(gameState.GetSpectatorView(), 100)); + Console.Out.WriteLine(new BoardRenderer().DrawBoards(gameState.GetSpectatorView(), 100)); Console.Out.WriteLine(gameState.GameStateText); } scoreSum.Highest.PlayerScores.Count().Should().Be(1); @@ -160,7 +160,7 @@ public void AIGameRunner_FogTicTacToe_AsterAIvsRandom() { scoreSum += new ScoreCard( result.Highest.PlayerScores.Select(ps => new PlayerIndexScore(ps.PlayerIndex, 1)) ); - Console.Out.WriteLine(BoardRenderer.DrawBoards(gameState.GetSpectatorView(), 100)); + Console.Out.WriteLine(new BoardRenderer().DrawBoards(gameState.GetSpectatorView(), 100)); Console.Out.WriteLine(gameState.GameStateText); } scoreSum.Highest.AsPlayerInfos(playerState).Count().Should().Be(1); From 7bc1b66fad35921df57f09993c60af1152bab017 Mon Sep 17 00:00:00 2001 From: Pxtl-clod <280797458+Pxtl-clod@users.noreply.github.com> Date: Wed, 22 Jul 2026 19:44:18 +0000 Subject: [PATCH 2/2] style(BoardRenderer): restore missing comment on GetBoardRenderWidth with correct punctuation --- src/MnkeyFog.CommandLine/BoardRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MnkeyFog.CommandLine/BoardRenderer.cs b/src/MnkeyFog.CommandLine/BoardRenderer.cs index 32fc8b5..37c7818 100644 --- a/src/MnkeyFog.CommandLine/BoardRenderer.cs +++ b/src/MnkeyFog.CommandLine/BoardRenderer.cs @@ -40,7 +40,7 @@ public string DrawBoards( } public int GetBoardRenderWidth(BoardView board) - => board.ColumnCount * 4 + 3; + => board.ColumnCount * 4 + 3; // 4 chars per-space, plus 2 for indent. /// /// Helper function to draw a border row of the board.