diff --git a/Chess-Challenge/src/Framework/Application/Core/ChallengeController.cs b/Chess-Challenge/src/Framework/Application/Core/ChallengeController.cs index 5fb1138..4fc60b3 100644 --- a/Chess-Challenge/src/Framework/Application/Core/ChallengeController.cs +++ b/Chess-Challenge/src/Framework/Application/Core/ChallengeController.cs @@ -23,7 +23,7 @@ namespace ChessChallenge.Application } // Game state - Random rng; + readonly Random rng; int gameID; bool isPlaying; Board board; @@ -53,12 +53,13 @@ namespace ChessChallenge.Application readonly BoardUI boardUI; readonly MoveGenerator moveGenerator; readonly int tokenCount; + readonly int debugTokenCount; readonly StringBuilder pgns; public ChallengeController() { Log($"Launching Chess-Challenge version {Settings.Version}"); - tokenCount = GetTokenCount(); + (tokenCount, debugTokenCount) = GetTokenCount(); Warmer.Warm(); rng = new Random(); @@ -213,7 +214,7 @@ namespace ChessChallenge.Application }; } - static int GetTokenCount() + static (int totalTokenCount, int debugTokenCount) GetTokenCount() { string path = Path.Combine(Directory.GetCurrentDirectory(), "src", "My Bot", "MyBot.cs"); @@ -384,9 +385,10 @@ namespace ChessChallenge.Application string nameB = GetPlayerName(PlayerBlack); boardUI.DrawPlayerNames(nameW, nameB, PlayerWhite.TimeRemainingMs, PlayerBlack.TimeRemainingMs, isPlaying); } + public void DrawOverlay() { - BotBrainCapacityUI.Draw(tokenCount, MaxTokenCount); + BotBrainCapacityUI.Draw(tokenCount, debugTokenCount, MaxTokenCount); MenuUI.DrawButtons(this); MatchStatsUI.DrawMatchStats(this); } diff --git a/Chess-Challenge/src/Framework/Application/Helpers/Token Counter/TokenCounter.cs b/Chess-Challenge/src/Framework/Application/Helpers/Token Counter/TokenCounter.cs index c79b36d..2e1fa82 100644 --- a/Chess-Challenge/src/Framework/Application/Helpers/Token Counter/TokenCounter.cs +++ b/Chess-Challenge/src/Framework/Application/Helpers/Token Counter/TokenCounter.cs @@ -1,11 +1,17 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; +using System.Linq; +using System; namespace ChessChallenge.Application { public static class TokenCounter { + // Including this in a comment will cause all tokens on the same line to be excluded from the count. + // Note: these tokens will still be counted in your final submission. + const string ignoreString = "#DEBUG"; static readonly HashSet tokensToIgnore = new(new SyntaxKind[] { @@ -20,40 +26,61 @@ namespace ChessChallenge.Application SyntaxKind.CloseParenToken }); - public static int CountTokens(string code) + public static (int totalCount, int debugCount) CountTokens(string code) { SyntaxTree tree = CSharpSyntaxTree.ParseText(code); SyntaxNode root = tree.GetRoot(); - return CountTokens(root); + TextLineCollection lines = tree.GetText().Lines; + IEnumerable allTokens = root.DescendantTokens(); + + // Total token count + int totalTokenCount = CountTokens(allTokens); + + // Debug token count (tokens explicitly excluded by user for testing purposes) + var ignoreInstructions = root.DescendantTrivia().Where(t => IsIgnoreTokenInstruction(t)); + int debugTokenCount = 0; + foreach(var ignore in ignoreInstructions) + { + int lineNumber = lines.GetLineFromPosition(ignore.SpanStart).LineNumber; + var debugTokens = allTokens.Where(t => lines.GetLineFromPosition(t.SpanStart).LineNumber == lineNumber); + debugTokenCount += CountTokens(debugTokens); + } + + return (totalTokenCount, debugTokenCount); } - static int CountTokens(SyntaxNodeOrToken syntaxNode) + static int CountTokens(IEnumerable tokens) { - SyntaxKind kind = syntaxNode.Kind(); - int numTokensInChildren = 0; - - - foreach (var child in syntaxNode.ChildNodesAndTokens()) + int tokenCount = 0; + foreach (var token in tokens) { - numTokensInChildren += CountTokens(child); + tokenCount += GetTokenCountValue(token); } - - if (syntaxNode.IsToken && !tokensToIgnore.Contains(kind)) - { - //Console.WriteLine(kind + " " + syntaxNode.ToString()); - - // String literals count for as many chars as are in the string - if (kind is SyntaxKind.StringLiteralToken or SyntaxKind.InterpolatedStringTextToken) - { - return syntaxNode.ToString().Length; - } - - // Regular tokens count as just one token - return 1; - } - - return numTokensInChildren; + return tokenCount; } + static int GetTokenCountValue(SyntaxToken token) + { + SyntaxKind kind = token.Kind(); + if (tokensToIgnore.Contains(kind)) + { + return 0; + } + + // String literals count for as many chars as are in the string + if (kind is SyntaxKind.StringLiteralToken or SyntaxKind.InterpolatedStringTextToken) + { + return token.ToString().Length; + } + + // Regular tokens count as just one token + return 1; + } + + static bool IsIgnoreTokenInstruction(SyntaxTrivia trivia) + { + var compareType = StringComparison.InvariantCultureIgnoreCase; + return trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) && trivia.ToString().Contains(ignoreString, compareType); + } } } \ No newline at end of file diff --git a/Chess-Challenge/src/Framework/Application/UI/BotBrainCapacityUI.cs b/Chess-Challenge/src/Framework/Application/UI/BotBrainCapacityUI.cs index c72deaa..50f25af 100644 --- a/Chess-Challenge/src/Framework/Application/UI/BotBrainCapacityUI.cs +++ b/Chess-Challenge/src/Framework/Application/UI/BotBrainCapacityUI.cs @@ -10,8 +10,9 @@ namespace ChessChallenge.Application static readonly Color red = new(219, 9, 9, 255); static readonly Color background = new Color(40, 40, 40, 255); - public static void Draw(int numTokens, int tokenLimit) + public static void Draw(int totalTokenCount, int debugTokenCount, int tokenLimit) { + int activeTokenCount = totalTokenCount - debugTokenCount; int screenWidth = Raylib.GetScreenWidth(); int screenHeight = Raylib.GetScreenHeight(); @@ -20,7 +21,7 @@ namespace ChessChallenge.Application // Bg Raylib.DrawRectangle(0, screenHeight - height, screenWidth, height, background); // Bar - double t = (double)numTokens / tokenLimit; + double t = (double)activeTokenCount / tokenLimit; Color col; if (t <= 0.7) @@ -34,11 +35,15 @@ namespace ChessChallenge.Application Raylib.DrawRectangle(0, screenHeight - height, (int)(screenWidth * t), height, col); var textPos = new System.Numerics.Vector2(screenWidth / 2, screenHeight - height / 2); - string text = $"Bot Brain Capacity: {numTokens}/{tokenLimit}"; - if (numTokens > tokenLimit) + string text = $"Bot Brain Capacity: {activeTokenCount}/{tokenLimit}"; + if (activeTokenCount > tokenLimit) { text += " [LIMIT EXCEEDED]"; } + else if (debugTokenCount != 0) + { + text += $" ({totalTokenCount} with Debugs included)"; + } UIHelper.DrawText(text, textPos, fontSize, 1, Color.WHITE, UIHelper.AlignH.Centre); } }