/**
         * 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);
        }
Esempio n. 3
0
 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);
        }
Esempio n. 7
0
        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());
                    }
                }
            }
        }