Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions src/MnkeyFog.CommandLine/BoardRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ namespace MnkeyFog.CommandLine;
/// Draws the full board based on the given gamestate, from the perspective of
/// the given player.
/// </summary>
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
) {
Expand All @@ -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; // 4 chars per-space, plus 2 for indent.

/// <summary>
/// Helper function to draw a border row of the board.
/// Wraps to newline when maxWidth is exceeded.
/// </summary>
private static sbyte DrawBorderRow(
private sbyte DrawBorderRow(
GameView gameView,
sbyte startBoardIndex,
string startBarString,
Expand All @@ -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)) {
Expand Down Expand Up @@ -84,7 +89,7 @@ StringBuilder sb
/// Draw a row of board spaces with window wrapping.
/// Wraps to newline when maxWidth is exceeded.
/// </summary>
private static sbyte DrawBoardSpacesRow(
private sbyte DrawBoardSpacesRow(
GameView gameView,
sbyte startBoardIndex,
string borderBarString,
Expand All @@ -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)) {
Expand All @@ -119,13 +124,16 @@ StringBuilder sb
/// <summary>
/// Helper function to draw the body-spaces of the board.
/// </summary>
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) {
/// <summary>
/// Get the cursor position (number of characters since last line break).
/// </summary>
public int GetCursorX(StringBuilder sb) {
int charsSinceLineBreak = 0;

for (int i = sb.Length - 1; i >= 0; i--) {
Expand Down
13 changes: 6 additions & 7 deletions src/MnkeyFog.CommandLine/ConsoleLoop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ OrderedDictionary<PlayerInfo, IPlayerAI> 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;
}
}
Expand All @@ -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));
}
}

Expand Down
18 changes: 9 additions & 9 deletions tests/MnkeyFog.Model.Tests/BoardRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = @"
┌───┬───┬───┐
│ │ │ │
Expand Down Expand Up @@ -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);
}

Expand All @@ -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 = @"
┌───┬───┬───┐
Expand Down Expand Up @@ -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 = @"
┌───┬───┬───┐
Expand Down Expand Up @@ -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 = @"
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
Expand Down Expand Up @@ -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│
Expand Down Expand Up @@ -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┌───┬───┬───┐
│ │ │ │ │ │ │ │
Expand Down Expand Up @@ -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┌───┬───┬───┐
│ │ │ │
Expand Down Expand Up @@ -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┌───┬───┬───┐
Expand Down
2 changes: 1 addition & 1 deletion tests/MnkeyFog.Model.Tests/GameStateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 _);
Expand Down
6 changes: 3 additions & 3 deletions tests/MnkeyFog.Model.Tests/PlayerAITests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading