/** * Draws the board, and called drawCBM which will check our hypothesis * for board memory behavior and print out all the board memory is any hypothesis is incorrect */ private static void DrawBoard(ChessBoard board) { ChessBoardMemory cbm = board.cbm; Console.WriteLine($"Board: L{board.cbm.timeline:+#;-#;0}T{board.cbm.turn + 1}"); DrawCBM(cbm); for (int y = board.height - 1; y >= 0; y--) { for (int x = 0; x < board.width; x++) { var p = board.Pieces[x * board.width + y]; if (!p.IsEmpty) { WriteConsoleColored(p.SingleLetterNotation(), p.IsBlack ? ConsoleColor.White : ConsoleColor.Black, p.IsBlack ? ConsoleColor.Black : ConsoleColor.White); } else { WriteConsoleColored(" ", ConsoleColor.Gray, ConsoleColor.Gray); } } Console.ResetColor(); Console.WriteLine(" "); } Console.WriteLine(); }
/// <summary> /// Gets all currently available chessboards. Chessboards are ordered by their id, indicating when they were created. (<see cref="ChessBoard.Id"/>). /// </summary> /// <returns>A list of <see cref="ChessBoard"/>, each representing a single chessboard.</returns> public List <ChessBoard> GetChessBoards() { var len = this.MemLocChessArraySize.GetValue(); var bytesToRead = (uint)(len * ChessBoardMemory.structSize); var boardLoc = this.MemLocChessArrayPointer.GetValue(); var bytes = KernelMethods.ReadMemory(GetGameHandle(), boardLoc, bytesToRead, out uint bytesRead); if (bytesToRead != bytesRead) { throw new Exception("Not all bytes have been read!"); } var chunks = new List <byte[]>(); for (int i = 0; i < len; i++) { var dest = new byte[ChessBoardMemory.structSize]; Array.Copy(bytes, i * ChessBoardMemory.structSize, dest, 0, ChessBoardMemory.structSize); chunks.Add(dest); } var cbms = chunks.Select(x => ChessBoardMemory.ParseFromByteArray(x)).ToList(); var chessboardSize = GetChessBoardSize(); var cbs = cbms.Select(x => new ChessBoard(x, chessboardSize.Width, chessboardSize.Height)).ToList(); return(cbs); }
public ChessBoard(ChessBoardMemory mem, int width, int height) { this.width = width; this.height = height; this.cbm = mem; UpdatePieceArrayFromInternalData(); }
public ChessBoard(ChessBoardMemory mem, int width, int height) { this.width = width; this.height = height; this.cbm = mem; this.Pieces = new ChessPiece[width * height]; for (int x = 0; x < width; x++) { for (int y = height - 1; y >= 0; y--) { var srcIndex = (x * 8 + y) * 2; this.Pieces[x * height + y] = ChessPiece.ParseFromTwoByteNotation(mem.positionData[srcIndex], mem.positionData[srcIndex + 1]); } } }
/** * Check our hypothesis, if any are wrong then print out all the board data * otherwise just say we were correct */ private static void DrawCBM(ChessBoardMemory cbm) { if (CheckCBMHypothesis(cbm)) { Dictionary <string, int> fields = cbm.GetFieldsWithNames(); foreach (KeyValuePair <string, int> pair in fields) { Console.WriteLine($"{pair.Key} = {pair.Value}"); // Console.WriteLine("VALUE: " + pair.Value); } } else { Console.WriteLine("All Hypothesis Correct"); } }
/** * This is a function to check assumptions about how the board memory behaves * check ChessBoardMemory for more info on some of these values * some of the variable names are also a little messed up to do my own laziness * * If all the hypothesis are correct this function returns false * if any hypothesis is wrong this function returns true */ private static bool CheckCBMHypothesis(ChessBoardMemory cbm) { Dictionary <string, int> fields = cbm.GetFieldsWithNames(); bool wrong_hypothesis = false; // if a move has been made on the board... fields.TryGetValue("move type", out int moveType); if (moveType > 0) { // standard physical move if (moveType == 1) { // timeline and timeline number 2 are the same fields.TryGetValue("timeline", out int timeline1); fields.TryGetValue("move source universe", out int timeline2); if (timeline1 != timeline2) { WriteConsoleColored("timeline and timeline number 2 are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // turn and time position 2 are the same fields.TryGetValue("turn", out int time1); fields.TryGetValue("move source time", out int time2); if (time1 != time2) { WriteConsoleColored("turn and time position 2 are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // isBlacksMove and player to move are the same fields.TryGetValue("isBlacksMove", out int isBlack); fields.TryGetValue("move piece color", out int isBlack2); if (isBlack != isBlack2) { WriteConsoleColored("isBlacksMove and player to move are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } } // branching jump move if (moveType == 2) { // timeline and timeline number 2 are the same fields.TryGetValue("timeline", out int timeline1); fields.TryGetValue("move source universe", out int timeline2); if (timeline1 != timeline2) { WriteConsoleColored("timeline and timeline number 2 are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // turn and time position 2 are the same fields.TryGetValue("turn", out int time1); fields.TryGetValue("move source time", out int time2); if (time1 != time2) { WriteConsoleColored("turn and time position 2 are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // isBlacksMove and player to move are the same fields.TryGetValue("isBlacksMove", out int isBlack); fields.TryGetValue("move piece color", out int isBlack2); if (isBlack != isBlack2) { WriteConsoleColored("isBlacksMove and player to move are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } } // non-branching jump move if (moveType == 3) { // timeline and timeline number 2 are the same fields.TryGetValue("timeline", out int timeline1); fields.TryGetValue("move source universe", out int timeline2); if (timeline1 != timeline2) { WriteConsoleColored("timeline and timeline number 2 are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // turn and time position 2 are the same fields.TryGetValue("turn", out int time1); fields.TryGetValue("move source time", out int time2); if (time1 != time2) { WriteConsoleColored("turn and time position 2 are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // isBlacksMove and player to move are the same fields.TryGetValue("isBlacksMove", out int isBlack); fields.TryGetValue("move piece color", out int isBlack2); if (isBlack != isBlack2) { WriteConsoleColored("isBlacksMove and player to move are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } } // a piece arrived from another board (do to a non-branching jump move) if (moveType == 4) { // timeline and timeline number 2 are the same fields.TryGetValue("timeline", out int timeline1); fields.TryGetValue("move source universe", out int timeline2); if (timeline1 == timeline2) { WriteConsoleColored("timeline and timeline number 2 are equal when they shouldn't be!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } // isBlacksMove and player to move are the same fields.TryGetValue("isBlacksMove", out int isBlack); fields.TryGetValue("move piece color", out int isBlack2); if (isBlack != isBlack2) { WriteConsoleColored("isBlacksMove and player to move are not equal!\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } } if (moveType > 4) { WriteConsoleColored("move type is greater than 4\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } } // moveType == 0 else { fields.TryGetValue("move source universe", out int sourceUniverse); fields.TryGetValue("move source time", out int sourceTime); fields.TryGetValue("move piece color", out int movePieceColor); if (sourceUniverse != 0) { WriteConsoleColored("move source universe not zero\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } if (sourceTime != 0) { WriteConsoleColored("move source time not zero\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } if (movePieceColor != 0) { WriteConsoleColored("move piece color not zero\n", ConsoleColor.Red, ConsoleColor.Black); wrong_hypothesis = true; } } return(wrong_hypothesis); }
public void ModifyChessBoards(Func <ChessBoard, ChessBoard> lambda) { var len = this.MemLocChessArrayElementCount.GetValue(); var bytesToRead = (uint)(len * ChessBoardMemory.structSize); var boardLoc = this.MemLocChessArrayPointer.GetValue(); var bytes = KernelMethods.ReadMemory(GetGameHandle(), boardLoc, bytesToRead, out uint bytesRead); if (bytesToRead != bytesRead) { throw new Exception("Not all bytes have been read!"); } var size = GetChessBoardSize(); for (int i = 0; i < len; i++) { var dest = new byte[ChessBoardMemory.structSize]; Array.Copy(bytes, i * ChessBoardMemory.structSize, dest, 0, ChessBoardMemory.structSize); var board = ChessBoardMemory.ParseFromByteArray(dest); var modifiedBoard = lambda.Invoke(new ChessBoard(board, size.Width, size.Height)); var newBytes = ChessBoardMemory.ToByteArray(modifiedBoard.cbm); if (newBytes.Length != ChessBoardMemory.structSize) { throw new Exception("For some reason the modified ChessBaordMemory struct is smaller than the original which is not allowed"); } var updateRequired = false; for (int j = 0; j < newBytes.Length; j++) { if (newBytes[j] != bytes[i * ChessBoardMemory.structSize + j]) // if any of the bytes changed { updateRequired = true; break; } } // resolve deltas, to not overwrite potentially modified data -- experimental but seems to work, but doesnt solve the problem where an AI gets stuck // if we swap pieces while the ai is thinking if (updateRequired) { // var byteDelta = newBytes.Select((x, i) => x == bytes[i] ? (byte?)null : x).ToArray(); var lengths = new List <(int, int)>(); // tuples of start index, length int currStartIndex = -1; for (int bi = 0; bi < newBytes.Length; bi++) { var byteDiffers = bytes[bi] != newBytes[bi]; if (currStartIndex == -1) // not currently in a group { if (byteDiffers) { currStartIndex = bi; } } else { if (!byteDiffers) { lengths.Add((currStartIndex, bi - currStartIndex)); currStartIndex = -1; } } } if (currStartIndex != -1) { lengths.Add((currStartIndex, newBytes.Length - currStartIndex)); } foreach (var(startindex, length) in lengths) { KernelMethods.WriteMemory(GetGameHandle(), boardLoc + i * ChessBoardMemory.structSize + startindex, newBytes.Skip(startindex).Take(length).ToArray()); } } } }