Allow tokens to be excluded from count with // #Debug

This commit is contained in:
Sebastian Lague 2023-07-29 13:31:56 +02:00
parent 282048c796
commit 4d5ea5d7ad
3 changed files with 67 additions and 33 deletions

View file

@ -23,7 +23,7 @@ namespace ChessChallenge.Application
} }
// Game state // Game state
Random rng; readonly Random rng;
int gameID; int gameID;
bool isPlaying; bool isPlaying;
Board board; Board board;
@ -53,12 +53,13 @@ namespace ChessChallenge.Application
readonly BoardUI boardUI; readonly BoardUI boardUI;
readonly MoveGenerator moveGenerator; readonly MoveGenerator moveGenerator;
readonly int tokenCount; readonly int tokenCount;
readonly int debugTokenCount;
readonly StringBuilder pgns; readonly StringBuilder pgns;
public ChallengeController() public ChallengeController()
{ {
Log($"Launching Chess-Challenge version {Settings.Version}"); Log($"Launching Chess-Challenge version {Settings.Version}");
tokenCount = GetTokenCount(); (tokenCount, debugTokenCount) = GetTokenCount();
Warmer.Warm(); Warmer.Warm();
rng = new Random(); 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"); string path = Path.Combine(Directory.GetCurrentDirectory(), "src", "My Bot", "MyBot.cs");
@ -384,9 +385,10 @@ namespace ChessChallenge.Application
string nameB = GetPlayerName(PlayerBlack); string nameB = GetPlayerName(PlayerBlack);
boardUI.DrawPlayerNames(nameW, nameB, PlayerWhite.TimeRemainingMs, PlayerBlack.TimeRemainingMs, isPlaying); boardUI.DrawPlayerNames(nameW, nameB, PlayerWhite.TimeRemainingMs, PlayerBlack.TimeRemainingMs, isPlaying);
} }
public void DrawOverlay() public void DrawOverlay()
{ {
BotBrainCapacityUI.Draw(tokenCount, MaxTokenCount); BotBrainCapacityUI.Draw(tokenCount, debugTokenCount, MaxTokenCount);
MenuUI.DrawButtons(this); MenuUI.DrawButtons(this);
MatchStatsUI.DrawMatchStats(this); MatchStatsUI.DrawMatchStats(this);
} }

View file

@ -1,11 +1,17 @@
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System;
namespace ChessChallenge.Application namespace ChessChallenge.Application
{ {
public static class TokenCounter 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<SyntaxKind> tokensToIgnore = new(new SyntaxKind[] static readonly HashSet<SyntaxKind> tokensToIgnore = new(new SyntaxKind[]
{ {
@ -20,40 +26,61 @@ namespace ChessChallenge.Application
SyntaxKind.CloseParenToken SyntaxKind.CloseParenToken
}); });
public static int CountTokens(string code) public static (int totalCount, int debugCount) CountTokens(string code)
{ {
SyntaxTree tree = CSharpSyntaxTree.ParseText(code); SyntaxTree tree = CSharpSyntaxTree.ParseText(code);
SyntaxNode root = tree.GetRoot(); SyntaxNode root = tree.GetRoot();
return CountTokens(root); TextLineCollection lines = tree.GetText().Lines;
IEnumerable<SyntaxToken> 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);
} }
static int CountTokens(SyntaxNodeOrToken syntaxNode) return (totalTokenCount, debugTokenCount);
{
SyntaxKind kind = syntaxNode.Kind();
int numTokensInChildren = 0;
foreach (var child in syntaxNode.ChildNodesAndTokens())
{
numTokensInChildren += CountTokens(child);
} }
if (syntaxNode.IsToken && !tokensToIgnore.Contains(kind)) static int CountTokens(IEnumerable<SyntaxToken> tokens)
{ {
//Console.WriteLine(kind + " " + syntaxNode.ToString()); int tokenCount = 0;
foreach (var token in tokens)
{
tokenCount += GetTokenCountValue(token);
}
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 // String literals count for as many chars as are in the string
if (kind is SyntaxKind.StringLiteralToken or SyntaxKind.InterpolatedStringTextToken) if (kind is SyntaxKind.StringLiteralToken or SyntaxKind.InterpolatedStringTextToken)
{ {
return syntaxNode.ToString().Length; return token.ToString().Length;
} }
// Regular tokens count as just one token // Regular tokens count as just one token
return 1; return 1;
} }
return numTokensInChildren; static bool IsIgnoreTokenInstruction(SyntaxTrivia trivia)
} {
var compareType = StringComparison.InvariantCultureIgnoreCase;
return trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) && trivia.ToString().Contains(ignoreString, compareType);
}
} }
} }

View file

@ -10,8 +10,9 @@ namespace ChessChallenge.Application
static readonly Color red = new(219, 9, 9, 255); static readonly Color red = new(219, 9, 9, 255);
static readonly Color background = new Color(40, 40, 40, 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 screenWidth = Raylib.GetScreenWidth();
int screenHeight = Raylib.GetScreenHeight(); int screenHeight = Raylib.GetScreenHeight();
@ -20,7 +21,7 @@ namespace ChessChallenge.Application
// Bg // Bg
Raylib.DrawRectangle(0, screenHeight - height, screenWidth, height, background); Raylib.DrawRectangle(0, screenHeight - height, screenWidth, height, background);
// Bar // Bar
double t = (double)numTokens / tokenLimit; double t = (double)activeTokenCount / tokenLimit;
Color col; Color col;
if (t <= 0.7) if (t <= 0.7)
@ -34,11 +35,15 @@ namespace ChessChallenge.Application
Raylib.DrawRectangle(0, screenHeight - height, (int)(screenWidth * t), height, col); Raylib.DrawRectangle(0, screenHeight - height, (int)(screenWidth * t), height, col);
var textPos = new System.Numerics.Vector2(screenWidth / 2, screenHeight - height / 2); var textPos = new System.Numerics.Vector2(screenWidth / 2, screenHeight - height / 2);
string text = $"Bot Brain Capacity: {numTokens}/{tokenLimit}"; string text = $"Bot Brain Capacity: {activeTokenCount}/{tokenLimit}";
if (numTokens > tokenLimit) if (activeTokenCount > tokenLimit)
{ {
text += " [LIMIT EXCEEDED]"; text += " [LIMIT EXCEEDED]";
} }
else if (debugTokenCount != 0)
{
text += $" ({totalTokenCount} with Debugs included)";
}
UIHelper.DrawText(text, textPos, fontSize, 1, Color.WHITE, UIHelper.AlignH.Centre); UIHelper.DrawText(text, textPos, fontSize, 1, Color.WHITE, UIHelper.AlignH.Centre);
} }
} }