/// <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);
        }
Beispiel #2
0
        /// <summary>
        /// Load a JVM dll to use as java server for the java vm calls
        /// Notes :
        /// - the previous library is released if one was already launched
        /// - Alledgedly, a library previously load is prioritized
        /// https://docs.microsoft.com/fr-fr/windows/win32/dlls/dynamic-link-library-search-order?redirectedfrom=MSDN
        /// </summary>
        /// <param name="jvm_dll_path"></param>
        public static void loadAssembly(string jvm_dll_path)
        {
            if (_dllPtr != IntPtr.Zero)
            {
                KernelMethods.FreeLibrary(_dllPtr);
            }
            _dllPtr = KernelMethods.LoadLibrary(jvm_dll_path);
            // Just in case :
            // according to DLL search order, previously loaded DLL are prioritized
            // But just in case, i also set the dll search directory to ensure
            bool dllDirValid = KernelMethods.SetDllDirectory(Path.GetDirectoryName(jvm_dll_path));

            if (_dllPtr == IntPtr.Zero || !dllDirValid)
            {
                throw new Exception($"An error occured while loading {jvm_dll_path}");
            }
        }
Beispiel #3
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());
                    }
                }
            }
        }