Skip to content

Commit

Permalink
finished v2-2
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrunaugh committed Feb 8, 2024
1 parent 632ad36 commit 902d457
Show file tree
Hide file tree
Showing 18 changed files with 749 additions and 201 deletions.
16 changes: 16 additions & 0 deletions ChessNotationConverter/Models/Evaluation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ChessNotationConverter.Models
{
internal class Evaluation
{
internal Position Position { get; private set; }
internal float Score { get; private set; }
internal int Hash { get; }
internal Evaluation(Position position, float score)
{
Position = position;
Score = score;
Hash = position.Matrix.GetHashCode();
}

}
}
14 changes: 0 additions & 14 deletions ChessNotationConverter/Models/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,5 @@ public Game(string gameText)
//Console.Clear();
//Console.WriteLine("Finished parsing game.");
}

internal double GetOutcomeForPositionIndex(int index)
{
if(Outcome == 0)
{
return 0.0;
}

var absoluteVal = (double)index / (double)MoveCount;

return Outcome == 1
? absoluteVal
: -absoluteVal;
}
}
}
11 changes: 11 additions & 0 deletions ChessNotationConverter/Models/Position.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,16 @@ private void Print()

return newBoard;
}

internal string Serialize(bool trailingComma = true)
{
var sb = new StringBuilder();
foreach (var pieceVal in Matrix)
{
sb.Append(pieceVal + ",");
}

return trailingComma ? sb.ToString() : sb.ToString().TrimEnd(',');
}
}
}
29 changes: 29 additions & 0 deletions ChessNotationConverter/PositionEvaluator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using ChessNotationConverter.Models;

namespace ChessNotationConverter
{
public static class PositionEvaluator
{
internal static Evaluation EvaluatePosition(Game game, int positionIndex)
{
float result;

// this assumes white won
// using logarithmic function to avoid late-middle game confusion
result = 1 - (float)Math.Log(game.MoveCount + 1 - positionIndex) / (float)Math.Log(game.MoveCount + 1);

if(game.Outcome == -1)
{
// negate for black
result = -result;
}
else if (game.Outcome == 0)
{
// always 0 for draw - assume no difference in eval for white/black
result = 0f;
}

return new Evaluation(game.Positions[positionIndex], result);
}
}
}
78 changes: 43 additions & 35 deletions ChessNotationConverter/Program.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
// See https://aka.ms/new-console-template for more information
// https://www.chess.com/analysis?tab=analysis

using ChessNotationConverter;
using ChessNotationConverter.Models;
using System.Text;

const string filePath = "C:\\Users\\bruna\\Downloads\\all_with_filtered_anotations_since1998.txt\\all_with_filtered_anotations_since1998.txt";
const string outputFilePath = "../../../../train_data.csv";
string line;
int lineNumber = 0;
var games = new List<Game>();
var evaluations = new List<Evaluation>();
var discardHashes = new List<int>();
int gameCount = 0;
int positionCount = 0;
int whiteWins = 0;
int draws = 0;
int blackWins = 0;
int uniquePositions = 0;
int duplicatePositions = 0;

using (StreamReader file = new StreamReader(filePath))
using (var file = new StreamReader(filePath))
{
while ((line = file.ReadLine()) != null)
{
Expand All @@ -37,48 +38,55 @@
games.Add(game);
}

if (games.Count >= 100)
if (games.Count >= 200)
{
gameCount += 100;
positionCount += games.Sum(g => g.Positions.Count);
whiteWins += games.Where(g => g.Outcome == 1).Count();
draws += games.Where(g => g.Outcome == 0).Count();
blackWins += games.Where(g => g.Outcome == -1).Count();
gameCount += 200;

Console.WriteLine($"Counts: {gameCount} games with {positionCount} positions written. {whiteWins} white wins - {draws} draws - {blackWins} black wins.");

var outputFilePath = Environment.CurrentDirectory + "../../../../train_data.csv";

using (StreamWriter sw = new StreamWriter(outputFilePath, true))
// loop through 1000 games
foreach (var game in games)
{
// loop through 100 games
foreach (var game in games)
if (game.WhiteElo < 2000 && game.BlackElo < 2000)
{
if (game.WhiteElo < 2000 && game.BlackElo < 2000)
{
continue;
}
gameCount--;
continue;
}

// loop through all positions
for (var i = 1; i < game.Positions.Count; i++)
// loop through all positions
for (var i = 1; i < game.Positions.Count; i++)
{
var evaluation = PositionEvaluator.EvaluatePosition(game, i);
// if no duplicates in current batch and no matches in known duplicates
if (!evaluations.Any(e => e.Hash == evaluation.Hash) && !discardHashes.Any(x => x == evaluation.Hash))
{
var sb = new StringBuilder();
foreach (var pieceInt in game.Positions[i].Matrix)
{
sb.Append(pieceInt.ToString() + ",");
}
sb.Append(game.GetOutcomeForPositionIndex(i).ToString() + "\n");

sw.WriteLine(sb.ToString());
uniquePositions++;
evaluations.Add(evaluation);
} else
{
duplicatePositions++;
gameCount--;
}

}
}

games.Clear();

using (var sw = new StreamWriter(outputFilePath, true))
{
foreach(var evaluation in evaluations)
{
var outputStr = evaluation.Position.Serialize(true) + evaluation.Score;
sw.WriteLine(outputStr);
}
}

Console.WriteLine($"Counts: {gameCount} games with {uniquePositions} unique positions written. Discarded {duplicatePositions} duplicate positions.");
evaluations.Clear();
}

if (gameCount >= 1000000)
break;
}
}

Console.WriteLine($"finished parsing games");
Console.WriteLine($"Finished converting and evaluating games.");
Console.ReadLine();
71 changes: 71 additions & 0 deletions DecisionEngine/src/Helpers/KingHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using DecisionEngine.Models;

namespace DecisionEngine.Helpers
{
public static class KingHelper
{
private static readonly int[][] offsets = [
[1, -1],
[1, 0],
[1, 1],
[0, -1],
[0, 1],
[-1, -1],
[-1, 0],
[-1, 1]
];

public static List<int[,]> FindAllLegalMoves(int[,] board, Player player)
{
var result = new List<int[,]>();

var kingValue = player == Player.White ? 9 : -9;

for (var i = 0; i < 8; i++)
{
for (var j = 0; j < 8; j++)
{
if (board[i, j] != kingValue)
continue;

var potentialSquares = GetPotentialMoveSquares(board, new Square(i, j));

foreach (var square in potentialSquares)
{
var playerCondition = player == Player.White
? BoardHelper.IntValueAt(board, (int)square.Row, (int)square.Column) <= 0
: BoardHelper.IntValueAt(board, (int)square.Row, (int)square.Column) >= 0;

if (playerCondition)
{
var newBoard = BoardHelper.DeepCopy(board);
newBoard[i, j] = 0;
newBoard[(int)square.Row, (int)square.Column] = kingValue;
result.Add(newBoard);
}
}
}
}

return result;
}

private static List<Square> GetPotentialMoveSquares(int[,] board, Square square)
{
var result = new List<Square>();

foreach (var offset in offsets)
{
var proposedRow = (int)square.Row + offset[0];
var proposedColumn = (int)square.Column + offset[1];

if(BoardHelper.AreValidCoords(proposedRow, proposedColumn))
{
result.Add(new Square(proposedRow, proposedColumn));
}
}

return result;
}
}
}
Loading

0 comments on commit 902d457

Please sign in to comment.