tomitankChess - New JavaScript engine

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

User avatar
Graham Banks
Posts: 41433
Joined: Sun Feb 26, 2006 10:52 am
Location: Auckland, NZ

Re: tomitankChess - New JavaScript engine

Post by Graham Banks »

Graham Banks wrote:
tomitank wrote:Thanks your help!
Does Tomitank have a version number (like 1.0 for example)?
Tomitank 1.4 64-bit. :)
gbanksnz at gmail.com
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: tomitankChess - New JavaScript engine

Post by tomitank »

tomitankChess 1.4 (case sensitive) :D

This run on 32 and 64 bit.
Jamal Bubker
Posts: 326
Joined: Mon May 24, 2010 4:32 pm

Re: tomitankChess - New JavaScript engine

Post by Jamal Bubker »

Thanks Tamás 8-)
User avatar
hgm
Posts: 27796
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: tomitankChess - New JavaScript engine

Post by hgm »

I am relatively new to JavaScript, and it is my goal to also write a JavaScript engine, to power my 'interactive diagrams'. As my knowledge of JavaScript is at such a low level that I was not even sure whether recursion was possible, it seemed a good idea to have a look at the source code of tomitankChess.

But the whole program is just a single line, which makes it look totally unmaintainable. Did you use some compaction program on it? I guess not, because the variable names are mostly very long, and using shorter names might have saved ten times more space than deleting linefeeds and indentation.

Most variable names also seem automatically generated, like _0xff55x7c. Did you originally write it in another language, and then decompile the executable to JavaScript?

E.g. after some global replacements to create linefeeds, I get code looking like this:

Code: Select all

function Quiescence(_0xff55x7c,_0xff55x80,_0xff55x82){if((nodes& 2047)== 0){CheckUp()};
nodes++;
if(IsRepetition()){return 0};
if(boardPly> maxDepth- 1){return Evaluation()};
if(_0xff55x82== UNKNOWN_CHECK){_0xff55x82= isCheck(currentPlayer)};
var _0xff55x87=_0xff55x82?-INFINITE:Evaluation();
if(!_0xff55x82&& _0xff55x87>= _0xff55x80){return _0xff55x87};
if(!_0xff55x82&& _0xff55x87> _0xff55x7c){_0xff55x7c= _0xff55x87};
var _0xff55x88=-INFINITE;
var _0xff55x7f=NOMOVE;
var _0xff55x89=NOMOVE;
var _0xff55x9e=currentPlayer^ 8;
var _0xff55x81=_0xff55x87+ 200;
if(!_0xff55x82){GenerateAllMoves(true,false)}else {GenerateAllMoves(false,true)};
for(var _0xff55xa0=brd_moveStart[boardPly];
_0xff55xa0< brd_moveStart&#91;boardPly+ 1&#93;;
++_0xff55xa0&#41;&#123;PickNextMove&#40;_0xff55xa0&#41;;
_0xff55x89= brd_moveList&#91;_0xff55xa0&#93;;
_0xff55x7f= CHESS_BOARD&#91;TOSQ&#40;_0xff55x89&#41;&#93;;
if&#40;!_0xff55x82&& !PROMOTED&#40;_0xff55x89&#41; && &#40;brd_pieceCount&#91;_0xff55x9e| ROOK&#93;+ brd_pieceCount&#91;_0xff55x9e| QUEEN&#93;+ brd_pieceCount&#91;_0xff55x9e| KNIGHT&#93;+ brd_pieceCount&#91;_0xff55x9e| BISHOP&#93;)> 1&#41;&#123;var _0xff55xa1=_0xff55x81;
if&#40;_0xff55x7f== 0&#41;&#123;_0xff55xa1+= PieceValue&#91;PAWN&#93;&#125;else &#123;_0xff55xa1+= PieceValue&#91;_0xff55x7f&#93;&#125;;
if&#40;_0xff55xa1< _0xff55x7c&#41;&#123;if&#40;_0xff55xa1> _0xff55x87&#41;&#123;_0xff55x87= _0xff55xa1&#125;;
continue&#125;&#125;;
if&#40;!_0xff55x82&& !See&#40;_0xff55x89&#41;)&#123;continue&#125;;
if&#40;!makeMove&#40;_0xff55x89&#41;)&#123;continue&#125;;
_0xff55x88= -Quiescence&#40;-_0xff55x80,-_0xff55x7c,UNKNOWN_CHECK&#41;;
unMakeMove&#40;);
if&#40;timeStop== 1&#41;&#123;return 0&#125;;
if&#40;_0xff55x88> _0xff55x87&#41;&#123;_0xff55x87= _0xff55x88;
if&#40;_0xff55x88> _0xff55x7c&#41;&#123;if&#40;_0xff55x88>= _0xff55x80&#41;&#123;return _0xff55x88&#125;;
_0xff55x7c= _0xff55x88&#125;&#125;&#125;;
if&#40;_0xff55x82&& _0xff55x88== -INFINITE&#41;&#123;return -INFINITE+ boardPly&#125;;
return _0xff55x87&#125;
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: tomitankChess - New JavaScript engine

Post by tomitank »

hgm wrote:Did you use some compaction program on it?

Most variable names also seem automatically generated, like _0xff55x7c. Did you originally write it in another language, and then decompile the executable to JavaScript?
No.
I'm use this site:
http://www.javascriptobfuscator.com/Jav ... cator.aspx

I just wanted to share a game, not the source code, but your work is incredible :)
(I know the "github" is not for this.)
First, i would like tune some search parameter.
I think this will be the strongest JavaScript chess engine in the world. (without Enscripten and V8)
Maybe already so. (I hope.)
This will work in my mobile application.
I will share the next version with source code.
User avatar
hgm
Posts: 27796
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: tomitankChess - New JavaScript engine

Post by hgm »

OK, I see. It doesn't do a very good job, because it leaves the routine names unobfuscated. (Perhaps it must, to keep it possible to call them from another file.) When one knows that the routine I lifted out is a Quiescence Search, it becomes quite trivial to guess the fuction of all the local variables, especially when you can see which are assigned things like Evaluation(), currentPlayer^8, isCheck()... But as it was not your intetion to publish the code, I won't show the completely de-obfuscated version of Quiescece() I made in about 2 minutes.

I was not so much interested in how exactly your code worked, as whether one could use things like recursion, local variables, global arrays... So I have already seen enough to conclude that JavaScript is almost exactly the same as C, with just a few tiny differeces to the syntax. So that means JavaScript doesn't pose any new problems, which is good news for me.
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: tomitankChess - New JavaScript engine

Post by tomitank »

But as it was not your intetion to publish the code
I did not even assume.I was just kidding : )

This encrypt method is not perfect.

As I said: If everything is ready, I will publish it ; )

I really respect you! I hope you didn't misunderstand.

Yes! JavaScript is very similar, but very slow. (no 64 bit integer, no macros, no memori management etc..)
User avatar
hgm
Posts: 27796
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: tomitankChess - New JavaScript engine

Post by hgm »

I also took a peek as to how you did your hash table, so see if the entries are structs as I would do in C. But I see you are using arrays for those, and even arrays that are 'indexed' bij character strings.

Code: Select all

function HashEntry&#40;_0xff55x7c,_0xff55x80,_0xff55x82,_0xff55x87,_0xff55x88,_0xff55x7f&#41;&#123;
  this&#91;"move"&#93;= _0xff55x7c;
  this&#91;"flag"&#93;= _0xff55x82;
  this&#91;"depth"&#93;= _0xff55x87;
  this&#91;"score"&#93;= _0xff55x80;
  this&#91;"hashKeyLow"&#93;= _0xff55x88;
  this&#91;"hashKeyHigh"&#93;= _0xff55x7f
&#125;
Doesn't this cause an incredible slowdown? It must mean that every HashEntry is in fact a tiny hash table in itself, and that to store the data items it must calculate a hash key from strings like "hashKeyLow" before it can know where the data was stored. (Or worse, do a linear search.) I also wonder if this doesn't blow up the side of the HashEntry enormously, e.g. because it also stores the strings "move", "flag" etc. with each of them. Wouldn't it be much faster to just use "this[0] = ...", "this[1] = ..."?

The obfuscator seems to make this even far worse, because it puts the strings in an array, from which it has to be fetched first, so that in the code above it does not even look like a constant 'index' (which could be calculated at compile time), but becomes a unknow variable, not even known to be a string. The array _0x1b7c could be made to contain any data type, so the decision to use an array or hash table must be taken at run time for every HashEntry that is written:

Code: Select all

function HashEntry&#40;_0xff55x7c,_0xff55x80,_0xff55x82,_0xff55x87,_0xff55x88,_0xff55x7f&#41;&#123;
  this&#91;_0x1b7c&#91;29&#93;&#93;= _0xff55x7c;
  this&#91;_0x1b7c&#91;30&#93;&#93;= _0xff55x82;
  this&#91;_0x1b7c&#91;31&#93;&#93;= _0xff55x87;
  this&#91;_0x1b7c&#91;32&#93;&#93;= _0xff55x80;
  this&#91;_0x1b7c&#91;33&#93;&#93;= _0xff55x88;
  this&#91;_0x1b7c&#91;34&#93;&#93;= _0xff55x7f
&#125;
I also wonder why you create a new HashEntry every time you do a HashStore. Why not just overwrite the data in the existing one. Does't this waste enormous amounts of memory?

Or am I completely misunderstanding how JavaScript works?
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: tomitankChess - New JavaScript engine

Post by tomitank »

I use "Always Replace" strategy.

Here is the source code:

Code: Select all

var HASHENTRIES		= &#40;28 << 20&#41; / 14; // Hashtabla merete 28 MB / 1 Hash merete &#40;14 Byte&#41;
var HASHMASK		= HASHENTRIES - 1; // Hashtabla maszk, csak ketto hatvanya lehet & MASK

Code: Select all

	function StoreHashMove&#40;move, score, flags, depth&#41; &#123;

		if &#40;score > ISMATE&#41; &#123; // Pontszam fixalasa
			score += boardPly;
		&#125; else if &#40;score < -ISMATE&#41; &#123; // Pontszam fixalasa
			score -= boardPly;
		&#125;

		brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93; = new HashEntry&#40;move, score, flags, depth, brd_hashKeyLow, brd_hashKeyHigh&#41;; // 108 bit /14 Byte/
	&#125;


	function HashEntry&#40;move, score, flags, depth, hashLow, hashHigh&#41; &#123;
		this.move			= move; // 20 bit
		this.flags			= flags; // 2 bit
		this.depth			= depth; // 7 bit
		this.score			= score; // 15 bit
		this.hashKeyLow		= hashLow; // 32 bit
		this.hashKeyHigh	= hashHigh; // 32 bit
	&#125;
I use 1 array -> it's called: brd_HashTable
The entries is Objects, not arrays, and not strings.

It could have been like this:

Code: Select all

brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93; = &#123;
	move &#58; move,
	flags &#58; flags,
	depth &#58; depth,
	score &#58; score,
	hashKeyLow &#58; brd_hashKeyLow,
	hashKeyHigh&#58; brd_hashKeyHigh
&#125;;
but in most browsers with "Object prototype" is a bit faster.
function HashEntry is my prototype.
So, this is not string, but also object in array.
(It's difficult because browser-dependent is the speed.)
I saw this method in garboChess.js

So you can refer to it:

Code: Select all

brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93;.score
brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93;.flags
brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93;.depth
In C would look like this(but this is different):

Code: Select all

brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93;->score
brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93;->flags
brd_HashTable&#91;brd_hashKeyLow & HASHMASK&#93;->depth
Very important:
so the maximal hash size is 28mb (currently).
If this is bigger, than some mobile browser crashes.
In a UCI i would like with bigger hash...
And again: JavaScript chess engine is difficult because browser-dependent is the speed.
tomitank
Posts: 276
Joined: Sat Mar 04, 2017 12:24 pm
Location: Hungary

Re: tomitankChess - New JavaScript engine

Post by tomitank »

Hi Gabor!

Javascript doesn't have 64 bit integers.
"Before a bitwise operation is performed, JavaScript converts numbers to 32 bits signed integers."

Please read this: http://talkchess.com/forum/viewtopic.php?t=65198

So this runs very similar.(slow)
This is not C..
It's hard to make a strong engine.

This will work in my mobile application. (This is a cordova project)

More on: https://cordova.apache.org/

I want to use my own engine. (Not the Stockfish-js Emscript version)

Currently run with my older engine:
https://play.google.com/store/apps/deta ... y.hu&hl=hu
https://itunes.apple.com/hu/app/sakk-in ... 54415?mt=8

In a few days, the automatic English language support comes. The "UI" is also self-made product.