SebLague/Chess-Coding-Adventure

WebGL build doesn't work

Mustafa-Agha opened this issue · 3 comments

if you changed Zobrist to the following : -

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

namespace Chess {
	public static class Zobrist {
		const int seed = 2361912;
		const string randomNumbersFileName = "RandomNumbers.txt";

		/// piece type, colour, square index
		public static readonly ulong[, , ] piecesArray = new ulong[8, 2, 64];
		public static readonly ulong[] castlingRights = new ulong[16];
		/// ep file (0 = no ep).
		public static readonly ulong[] enPassantFile = new ulong[9]; // no need for rank info as side to move is included in key
		public static readonly ulong sideToMove;

		static System.Random prng = new System.Random (seed);

		private static string _randomNumberString = "";
		
		static void WriteRandomNumbers () {
			prng = new System.Random (seed);
			string randomNumberString = "";
			int numRandomNumbers = 64 * 8 * 2 + castlingRights.Length + 9 + 1;

			for (int i = 0; i < numRandomNumbers; i++) {
				randomNumberString += RandomUnsigned64BitNumber ();
				if (i != numRandomNumbers - 1) {
					randomNumberString += ',';
				}
			}

			_randomNumberString = randomNumberString;
			// var writer = new StreamWriter (randomNumbersPath);
			// writer.Write (randomNumberString);
			// writer.Close ();
		}

		static Queue<ulong> ReadRandomNumbers () {
			// if (!File.Exists (randomNumbersPath)) {
			// 	Debug.Log ("Create");
			// 	WriteRandomNumbers ();
			// }
			if (string.IsNullOrEmpty(_randomNumberString)) {
				Debug.Log ("Create");
				WriteRandomNumbers ();
			}
			Queue<ulong> randomNumbers = new Queue<ulong> ();
			
			// var reader = new StreamReader (randomNumbersPath);
			// string numbersString = reader.ReadToEnd ();
			// reader.Close ();

			string numbersString = _randomNumberString;
			
			string[] numberStrings = numbersString.Split (',');
			for (int i = 0; i < numberStrings.Length; i++) {
				ulong number = ulong.Parse (numberStrings[i]);
				randomNumbers.Enqueue (number);
			}
			return randomNumbers;
		}
		
		static Zobrist ()
		{
			var randomNumbers = ReadRandomNumbers ();

			for (int squareIndex = 0; squareIndex < 64; squareIndex++) {
				for (int pieceIndex = 0; pieceIndex < 8; pieceIndex++) {
					piecesArray[pieceIndex, Board.WhiteIndex, squareIndex] = randomNumbers.Dequeue ();
					piecesArray[pieceIndex, Board.BlackIndex, squareIndex] = randomNumbers.Dequeue ();
				}
			}

			for (int i = 0; i < 16; i++) {
				castlingRights[i] = randomNumbers.Dequeue ();
			}

			for (int i = 0; i < enPassantFile.Length; i++) {
				enPassantFile[i] = randomNumbers.Dequeue ();
			}

			sideToMove = randomNumbers.Dequeue ();
		}

		/// Calculate zobrist key from current board position. This should only be used after setting board from fen; during search the key should be updated incrementally.
		public static ulong CalculateZobristKey (Board board) {
			ulong zobristKey = 0;

			for (int squareIndex = 0; squareIndex < 64; squareIndex++) {
				if (board.Square[squareIndex] != 0) {
					int pieceType = Piece.PieceType (board.Square[squareIndex]);
					int pieceColour = Piece.Colour (board.Square[squareIndex]);

					zobristKey ^= piecesArray[pieceType, (pieceColour == Piece.White) ? Board.WhiteIndex : Board.BlackIndex, squareIndex];
				}
			}

			int epIndex = (int) (board.currentGameState >> 4) & 15;
			if (epIndex != -1) {
				zobristKey ^= enPassantFile[epIndex];
			}

			if (board.ColourToMove == Piece.Black) {
				zobristKey ^= sideToMove;
			}

			zobristKey ^= castlingRights[board.currentGameState & 0b1111];

			return zobristKey;
		}

		static string randomNumbersPath {
			get
			{
				return Path.Combine (Application.streamingAssetsPath, randomNumbersFileName);
			}
		}

		static ulong RandomUnsigned64BitNumber () {
			byte[] buffer = new byte[8];
			prng.NextBytes (buffer);
			return BitConverter.ToUInt64 (buffer, 0);
		}
	}
}`
```

It still works on windows/linux/android/ios but not on webgl

any idea how to solve this problem?
mchccn commented

What do you mean "it doesn't work on WebGL"?

@kelsny

Unity WEBGL doesn't support multithreading so when disabling it and enabling use fixed depth.

The game works fine, but the max depth is only 7 or the game will freez in the search because of single threaded limitation to Javascript.

Also the above code is to avoid the problem if trying to get streamingAsset/RandomNumbers.txt file.
And this works fine in other platforms but not WEBGL, you need to use UnityWebRequest and get the url instead.

And in Android, you can't write streamingAsset, this will cause a problem. But we can ignore it because there is always a file there.

So my question is : -

1- how can I solve the multithreading issue, because max depth 5 is very easy for difficulty level.
2- how to use UnityWebRequest in a class where there is no MonoBehaviour.StartCoroutine, and I think we can't use async/await in this situation

mchccn commented

@Mustafa-Agha Not to throw any shade onto Sebastian, but have you also considered using another (better) chess engine? I don't know if he released the source for the 2nd video but you could also try that when it comes out. Using a faster engine could alleviate some of the problems. Other than that, I'm afraid I have no more answers since I use TypeScript primarily.

One last thing you could do is spin up web workers and run the engine in the background... but I don't know if that works with Unity's "export as WebGL" option.