generating algorithms

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
hgm
Posts: 27789
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: generating algorithms

Post by hgm »

If you want to do it automatically, the problem is that computers are usually very poor at answering questions like: "what does the following set ofpositions have in common". The easiest way would probably be to have it generate random boolean expressions from position characteristics that are likely to be useful. E.g. in KPK you would have:

* side to move
* pawn on edge file
* promotion square
* pawn on Nth rank (N=2, 6, 7)
* distances between pieces and promo square
* kings in path of pawn
* exact relative locations of pieces

You could generate random boolean expressions from those, and then determine how well they correlate with the EGT WDL score. The expression that correlates best would then be taken as the primary decision. You could then test the other expressions on the sub-sets of positions in each of the classes created by the primary decision, etc.
User avatar
cdani
Posts: 2204
Joined: Sat Jan 18, 2014 10:24 am
Location: Andorra

Re: generating algorithms

Post by cdani »

hgm wrote:If you want to do it automatically, the problem is that computers are usually very poor at answering questions like: "what does the following set ofpositions have in common". The easiest way would probably be to have it generate random boolean expressions from position characteristics that are likely to be useful. E.g. in KPK you would have:

* side to move
* pawn on edge file
* promotion square
* pawn on Nth rank (N=2, 6, 7)
* distances between pieces and promo square
* kings in path of pawn
* exact relative locations of pieces

You could generate random boolean expressions from those, and then determine how well they correlate with the EGT WDL score. The expression that correlates best would then be taken as the primary decision. You could then test the other expressions on the sub-sets of positions in each of the classes created by the primary decision, etc.
Is exactly what I thought! Is what I tried to explain here in the first post, but seems that I was not very successful :-):

"To generate this I think one can iterate trough all the possible positions having tablebase access and find which "Ifs" are true always; first find one-condition if's that are always true; then find two condition if's that are always true; and so on until all the cases or most of them are covered. Of course the if's that cover most positions will be first in the resulting algorithm. "
User avatar
hgm
Posts: 27789
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: generating algorithms

Post by hgm »

But the problem is how to generate useful conditions.
Michel
Posts: 2272
Joined: Mon Sep 29, 2008 1:50 am

Re: generating algorithms

Post by Michel »

hgm wrote:But the problem is how to generate useful conditions.
Has anyone tried the C5 algorithm

https://en.wikipedia.org/wiki/C4.5_algorithm ?

I don't know nothing about it, but it appears to be a standard algorithm.
Ideas=science. Simplification=engineering.
Without ideas there is nothing to simplify.
Xann
Posts: 127
Joined: Sat Jan 22, 2011 7:14 pm
Location: Lille, France

Re: generating algorithms

Post by Xann »

Michel wrote:Has anyone tried the C5 algorithm

https://en.wikipedia.org/wiki/C4.5_algorithm ?

I don't know nothing about it, but it appears to be a standard algorithm.
C5 is a good ML algorithm. But more is needed here: feature construction.

One can start with Utgoff's papers although he had evaluation in mind, not EGTB compression:
http://chessprogramming.wikispaces.com/Paul+E.+Utgoff

An alternative is Inductive Logic Programming (ILP), which builds features in a Prolog-like language.

Make no mistake though, feature construction is a difficult problem. Selection is much easier.
User avatar
Look
Posts: 364
Joined: Thu Jun 05, 2014 2:14 pm
Location: Iran
Full name: Mehdi Amini

Re: generating algorithms

Post by Look »

[...]
Xann wrote:An alternative is Inductive Logic Programming (ILP), which builds features in a Prolog-like language.
[...]

If you are interested in Prolog, some chapters in the book "Prolog_Programming_for_Artificial_Intelligence" by lvan Bratko discuss worthwhile topics.
Farewell.
User avatar
cdani
Posts: 2204
Joined: Sat Jan 18, 2014 10:24 am
Location: Andorra

Re: generating algorithms

Post by cdani »

Anyone has a working Stockfish version with tablebase support for Visual Studio? I made it work, but modifying some things, and now the tablebases always returns draw :-)

I'm working on the algorithm to find algorithms, adding some functions to Stockfish, but I need this.
Thanks!
User avatar
cdani
Posts: 2204
Joined: Sat Jan 18, 2014 10:24 am
Location: Andorra

Re: generating algorithms

Post by cdani »

cdani wrote:Anyone has a working Stockfish version with tablebase support for Visual Studio? I made it work, but modifying some things, and now the tablebases always returns draw :-)

I'm working on the algorithm to find algorithms, adding some functions to Stockfish, but I need this.
Thanks!
Jose mº velasco just sent me one that works well. Thanks!
User avatar
cdani
Posts: 2204
Joined: Sat Jan 18, 2014 10:24 am
Location: Andorra

Re: generating algorithms

Post by cdani »

Finally I tried to manually generate an algorithm to solve the KPK endgame, to try to see what is supposed to be generated automatically. The result I publish here is incomplete, it solves 265222 of 331352 possible positions (from the point of view of white). I stopped developing it because I think nobody will use this for anything but as an example :-) and also of course is difficult to continue.

It's clear what HGM told that it's an impossible task for a computer, unless someone finds who knows what type of hidden relations.

It's done in Stockfish. Here I show the function I created, which generates every possible KPK position, then tries to solve it by hand generated algorithm, and compares the result to tablebase result. If a position is not correct, it shows it and exits. Also it shows the first position that it's not covered by the hand generated algorithm, if any, to give ideas over what can be the next condition to add. And finally shows the number of positions well solved by hand.

Maybe I will try to do the hand algorithm to solve the typical KBPK with rook pawn endgame , as I suppose it will be a lot easier, and can be used in most engines.

Here is the Visual Studio solution:

http://www.andscacs.com/stockfish/stockfish_syzygy.zip

This is the main function:

Code: Select all

	void endgame_kpk(Position& pos) {
		long long totalpositions = 0;
		long long resolvedpositions = 0;
		int unknown = 999;
		bool first_unresolved_shown = false;
		for &#40;Square bk = SQ_A1; bk <= SQ_H8; bk++) &#123;
			for &#40;Square wk = SQ_A1; wk <= SQ_H8; wk++) &#123;
				if &#40;SquareDistance&#91;bk&#93;&#91;wk&#93; <= 1&#41;
					continue;
				for &#40;Square p = SQ_A2; p <= SQ_H7; p++) &#123;
					if &#40;p == wk || p == bk /*|| p == b*/)
						continue;
					for &#40;Color c = WHITE; c <= BLACK; ++c&#41; &#123;	//turn
						pos.clear&#40;);
						pos.thisThread = Threads.main&#40;);
						pos.st->epSquare = SQ_NONE;
						pos.put_piece&#40;WHITE, PAWN, p&#41;;
						pos.put_piece&#40;WHITE, KING, wk&#41;;
						pos.put_piece&#40;BLACK, KING, bk&#41;;
						pos.sideToMove = c;
						pos.set_state&#40;pos.st&#41;;
						if &#40;pos.attackers_to&#40;pos.king_square&#40;~c&#41;) & pos.pieces&#40;c&#41;)
							continue; //illegal position
						int own = unknown, found, v = Tablebases&#58;&#58;probe_wdl&#40;pos, &found&#41;;
						if (!found&#41; &#123;
							sync_cout << "Error not found; pawn&#58; " << UCI&#58;&#58;square&#40;p&#41; << " wk&#58; " << UCI&#58;&#58;square&#40;wk&#41; << " bk&#58; " << UCI&#58;&#58;square&#40;bk&#41; << sync_endl;
							return;
						&#125;
						totalpositions++;

						// -2 &#58; loss
						//  0 &#58; draw
						//  2 &#58; win
						if &#40;rank_of&#40;bk&#41; < rank_of&#40;p&#41; && c == WHITE&#41; //pawn scapes
							own = 2; //74772

						if &#40;own == unknown && rank_of&#40;bk&#41; < rank_of&#40;p&#41; - 1 && c == BLACK&#41; //pawn scapes
							own = -2; //53440 - 128212

						if &#40;own == unknown && rank_of&#40;p&#41; == 1 && rank_of&#40;bk&#41; <= 1&#41; &#123;//pawn scapes advancing 2 squares
							if &#40;c == WHITE || &#40;rank_of&#40;bk&#41; == 0 && &#40;SquareDistance&#91;wk&#93;&#91;p&#93; == 1 || SquareDistance&#91;bk&#93;&#91;p&#93; > 1&#41;))  //white's turn or pawn defended and black cannot block it or black cannot take pawn
								own = 2; //4892
						&#125;

						//black king prevents white king to unblock the pawn, or it must leave an entry to black king
						if &#40;own == unknown && &#40;file_of&#40;p&#41; == 0 || file_of&#40;p&#41; == 7&#41; && file_of&#40;wk&#41; == file_of&#40;p&#41; &&
							rank_of&#40;wk&#41; > rank_of&#40;p&#41;) &#123;
							if &#40;abs&#40;file_of&#40;bk&#41; - file_of&#40;wk&#41;) - &#40;c == BLACK ? 1 &#58; 0&#41; <= 2
								&& (
								&#40;rank_of&#40;bk&#41; + &#40;c == BLACK ? 1 &#58; 0&#41;) >= rank_of&#40;wk&#41;  //black king will arrive to block the wking
								||
								&#40;rank_of&#40;p&#41; == 6 && file_of&#40;bk&#41; != file_of&#40;wk&#41; && &#40;rank_of&#40;bk&#41; + &#40;c == BLACK ? 1 &#58; 0&#41;) == 6&#41; //black king will arrive to c7/f7 to block the wking 
								||
								&#40;c == WHITE && SquareDistance&#91;wk&#93;&#91;p&#93; >= SquareDistance&#91;bk&#93;&#91;p&#93; && rank_of&#40;wk&#41; - rank_of&#40;bk&#41; == 1 && rank_of&#40;p&#41; != 1&#41;
								))
								own = 0;  //608 
						&#125;

						if &#40;own == unknown && rank_of&#40;bk&#41; == rank_of&#40;p&#41; && c == WHITE && SquareDistance&#91;wk&#93;&#91;p&#93; == 1 && rank_of&#40;wk&#41; >= rank_of&#40;p&#41;) //pawn scapes, maybe defended by own king
							own = 2; //928 - 132808  //this works because of the previous condition

						if &#40;own == unknown && bk - p == 8 && c == BLACK && rank_of&#40;bk&#41; < 7&#41; //black king blocks pawn to advance
							own = 0;  //2230 - 135038

						if &#40;own == unknown && bk - p == 8 && c == WHITE && rank_of&#40;bk&#41; == 7&#41; &#123;
							//white king cannot force black king to leave the blockade of pawn, as black is stalemated
							if &#40;file_of&#40;bk&#41; == 0 ||
								file_of&#40;bk&#41; == 7 ||
								&#40;rank_of&#40;wk&#41; < 4 || //pawn undefended
								&#40;file_of&#40;wk&#41; != file_of&#40;p&#41; && SquareDistance&#91;wk&#93;&#91;p&#93; == 1&#41; //wk has to go to the same file of their pawn to defend it
								))
								own = 0;	//324 - 135362				  
						&#125;

						//black king can block the pawn on 8th, but white king forces it to leave 8th row.
						if &#40;own == unknown && rank_of&#40;bk&#41; == 7 && rank_of&#40;p&#41; == 6 &&
							//c == BLACK && p - wk == 8
							(
							&#40;c == BLACK && p - wk == 8 && file_of&#40;bk&#41; != file_of&#40;p&#41;)
							||
							&#40;c == WHITE && SquareDistance&#91;wk&#93;&#91;p&#93; == 2 && rank_of&#40;wk&#41; != 7 && file_of&#40;bk&#41; == file_of&#40;p&#41;)
							||
							(&#40;c == WHITE && p - wk == 8&#41; || &#40;c == BLACK && &#40;p - wk == 7 || p - wk == 9&#41;) && file_of&#40;bk&#41; == file_of&#40;p&#41;)
							)
							&& file_of&#40;p&#41; != 0 && file_of&#40;p&#41; != 7&#41;
							own = 2; //66

						if &#40;own == unknown && SquareDistance&#91;bk&#93;&#91;p&#93; == 1 && c == BLACK && SquareDistance&#91;wk&#93;&#91;p&#93; > 1&#41;  //black captures pawn
							own = 0;  //16076 - 151438

						//white king between black king and pawn
						if &#40;own == unknown && file_of&#40;bk&#41; > file_of&#40;wk&#41; && file_of&#40;wk&#41; > file_of&#40;p&#41; && rank_of&#40;bk&#41; <= rank_of&#40;wk&#41; && SquareDistance&#91;bk&#93;&#91;p&#93; > SquareDistance&#91;wk&#93;&#91;p&#93; + &#40;c == WHITE ? 1 &#58; 0&#41; + 1&#41;
							own = 2;  //3209
						if &#40;own == unknown && file_of&#40;bk&#41; < file_of&#40;wk&#41; && file_of&#40;wk&#41; < file_of&#40;p&#41; && rank_of&#40;bk&#41; <= rank_of&#40;wk&#41; && SquareDistance&#91;bk&#93;&#91;p&#93; > SquareDistance&#91;wk&#93;&#91;p&#93; + &#40;c == WHITE ? 1 &#58; 0&#41; + 1&#41;
							own = 2;  //3209

						if &#40;own == unknown &&
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, &#40;Rank&#41;7&#41;&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; > SquareDistance&#91;p&#93;&#91;make_square&#40;file_of&#40;p&#41;, &#40;Rank&#41;7&#41;&#93;
							) //king can not stop pawn
							own = 2;  //31920

						if &#40;own == unknown &&
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, &#40;Rank&#41;7&#41;&#93; < SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41;, &#40;Rank&#41;7&#41;&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; &&
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; < SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; &&
							(
							rank_of&#40;bk&#41; > rank_of&#40;p&#41;
							||
							&#40;rank_of&#40;bk&#41; == rank_of&#40;p&#41; &&
							(
							rank_of&#40;p&#41; != 1
							||
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; == 1  //king can block the pawn immediately if in 2nd rank
							)
							)
							)
							) //king can stop pawn
							own = 0; //41262

						//king can catch and capture the pawn
						if &#40;own == unknown && rank_of&#40;bk&#41; + &#40;c == BLACK ? 1 &#58; 0&#41; >= rank_of&#40;p&#41; && rank_of&#40;p&#41; != 1 &&
							SquareDistance&#91;bk&#93;&#91;p&#93; + &#40;c == BLACK ? 1 &#58; 0&#41; < SquareDistance&#91;wk&#93;&#91;p&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; &&  //+ &#40;c == BLACK ? 1 &#58; 0&#41; seems illogical but is a way to ignore a bunch of exceptions
							abs&#40;file_of&#40;wk&#41; - file_of&#40;p&#41;) - &#40;c == WHITE ? 1 &#58; 0&#41; > abs&#40;file_of&#40;wk&#41; - file_of&#40;p&#41;) - &#40;c == BLACK ? 1 &#58; 0&#41;
							)
							own = 0; //5874

						if &#40;own == unknown &&
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; > SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; + 1 &&
							rank_of&#40;wk&#41; >= rank_of&#40;bk&#41;
							) //king can not stop pawn
							own = 2; //5810

						/*if &#40;p == SQ_C3 && wk == SQ_A5 && bk == SQ_A2 && c == BLACK&#41;
							p = p;*/

						Square antbk = bk, antwk = wk;

						for &#40;int tried = 0; tried < 5; tried++) &#123;
							//king can catch and capture the pawn from left side
							if &#40;own == unknown && file_of&#40;p&#41; > 0 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; - &#40;File&#41;1, rank_of&#40;p&#41;)&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; <= 1 &&
								SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41; - &#40;File&#41;1, rank_of&#40;p&#41;)&#93; > 1 &&
								&#40;SquareDistance&#91;wk&#93;&#91;p&#93; > 3
								|| (&#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 1 && file_of&#40;wk&#41; < file_of&#40;p&#41;) &&
								&#40;c == BLACK && &#40;file_of&#40;wk&#41; == file_of&#40;bk&#41; || &#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 2 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; - &#40;File&#41;1, rank_of&#40;p&#41;)&#93; == 1&#41;)))
								|| (&#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 1 && file_of&#40;wk&#41; >= file_of&#40;p&#41;) &&
								&#40;c == BLACK && (&#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 2 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; - &#40;File&#41;1, rank_of&#40;p&#41;)&#93; == 1&#41;)))
								)
								&& rank_of&#40;p&#41; != 1
								) &#123;
								own = 0; //2551
								break;
							&#125;

							//push kings to pawn and try again
							if &#40;file_of&#40;bk&#41; < file_of&#40;p&#41;)
								bk += &#40;Square&#41;1;
							if &#40;file_of&#40;wk&#41; < file_of&#40;p&#41;)
								wk += &#40;Square&#41;1;
							else
								if &#40;file_of&#40;wk&#41; > file_of&#40;p&#41;)
									wk -= &#40;Square&#41;1;

							if &#40;rank_of&#40;bk&#41; <= rank_of&#40;p&#41;) //'<=' necessary to remove space to white king  8/1K6/8/8/8/4P3/k7/8 b - - 0 1
								bk += &#40;Square&#41;8;
							if &#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; && SquareDistance&#91;bk&#93;&#91;wk - 8&#93; > 1&#41;
								wk -= &#40;Square&#41;8;
							if &#40;SquareDistance&#91;bk&#93;&#91;wk&#93; == 1&#41;
								break;
						&#125;
						bk = antbk;
						wk = antwk;

						for &#40;int tried = 0; tried < 5; tried++) &#123;
							//king can catch and capture the pawn from right side
							if &#40;own == unknown && file_of&#40;p&#41; < 7 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; + &#40;File&#41;1, rank_of&#40;p&#41;)&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; <= 1 &&
								SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41; + &#40;File&#41;1, rank_of&#40;p&#41;)&#93; > 1 &&
								&#40;SquareDistance&#91;wk&#93;&#91;p&#93; > 3
								|| (&#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 1 && file_of&#40;wk&#41; > file_of&#40;p&#41;) &&
								&#40;c == BLACK && &#40;file_of&#40;wk&#41; == file_of&#40;bk&#41; || &#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 2 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; + &#40;File&#41;1, rank_of&#40;p&#41;)&#93; == 1&#41;)))
								|| (&#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 1 && file_of&#40;wk&#41; <= file_of&#40;p&#41;) &&
								&#40;c == BLACK && (&#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; + 2 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; + &#40;File&#41;1, rank_of&#40;p&#41;)&#93; == 1&#41;)))
								)
								&& rank_of&#40;p&#41; != 1
								) &#123;
								own = 0; //2353
								break;
							&#125;

							//push kings to pawn and try again
							if &#40;file_of&#40;bk&#41; > file_of&#40;p&#41;)
								bk -= &#40;Square&#41;1;
							if &#40;file_of&#40;wk&#41; > file_of&#40;p&#41;)
								wk -= &#40;Square&#41;1;
							else
								if &#40;file_of&#40;wk&#41; < file_of&#40;p&#41;)
									wk += &#40;Square&#41;1;

							if &#40;rank_of&#40;bk&#41; <= rank_of&#40;p&#41;) //'<=' necessary to remove space to white king  8/1K6/8/8/8/4P3/k7/8 b - - 0 1
								bk += &#40;Square&#41;8;
							if &#40;rank_of&#40;wk&#41; > rank_of&#40;p&#41; && SquareDistance&#91;bk&#93;&#91;wk - 8&#93; > 1&#41;
								wk -= &#40;Square&#41;8;
							if &#40;SquareDistance&#91;bk&#93;&#91;wk&#93; == 1&#41;
								break;
						&#125;
						bk = antbk;
						wk = antwk;

						//black king can stop the pawn on H
						//8/8/8/8/8/7P/1k6/3K4 b - - 0 1
						if &#40;own == unknown && file_of&#40;p&#41; == 7 &&
							SquareDistance&#91;bk&#93;&#91;SQ_H8&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; < SquareDistance&#91;wk&#93;&#91;SQ_H8&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; &&
							SquareDistance&#91;bk&#93;&#91;SQ_H8&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; < SquareDistance&#91;p&#93;&#91;SQ_H8&#93; &&
							rank_of&#40;wk&#41; < rank_of&#40;bk&#41;
							)
							own = 0; //2563

						//black king can stop the pawn on A
						if &#40;own == unknown && file_of&#40;p&#41; == 0 &&
							SquareDistance&#91;bk&#93;&#91;SQ_A8&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; < SquareDistance&#91;wk&#93;&#91;SQ_A8&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; &&
							SquareDistance&#91;bk&#93;&#91;SQ_A8&#93; - &#40;c == BLACK ? 1 &#58; 0&#41; < SquareDistance&#91;p&#93;&#91;SQ_A8&#93; &&
							rank_of&#40;wk&#41; < rank_of&#40;bk&#41;
							)
							own = 0; //2563

						//white king wins oposition going to the other side of the pawn
						//8/8/8/8/8/8/k1P5/2K5 b - - 0 1
						if &#40;own == unknown && file_of&#40;p&#41; > 1 && file_of&#40;p&#41; < 7 && bk == make_square&#40;file_of&#40;p&#41; - &#40;File&#41;2, rank_of&#40;p&#41;) && SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41; + &#40;File&#41;1, rank_of&#40;p&#41;)&#93; == 1&#41;
							own = 2;  //280
						if &#40;own == unknown && file_of&#40;p&#41; < 6 && file_of&#40;p&#41; > 0 && bk == make_square&#40;file_of&#40;p&#41; + &#40;File&#41;2, rank_of&#40;p&#41;) && SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41; - &#40;File&#41;1, rank_of&#40;p&#41;)&#93; == 1&#41;
							own = 2;  //280

						if &#40;own == unknown && bk - p == 16 && &#40;rank_of&#40;bk&#41; < 7 || c == BLACK&#41;) //black king blocks pawn to advance
							own = 0;  //1166

						//stalemate
						if &#40;own == unknown && c == BLACK && bk == SQ_H8 && wk != SQ_F6 && SquareDistance&#91;wk&#93;&#91;bk&#93; == 2 &&
							(&#40;file_of&#40;wk&#41; > FILE_F && p == SQ_F7&#41; || &#40;file_of&#40;wk&#41; == FILE_F && p == SQ_G6&#41;))
							own = 0; //4
						if &#40;own == unknown && c == BLACK && bk == SQ_A8 && wk != SQ_C6 && SquareDistance&#91;wk&#93;&#91;bk&#93; == 2 &&
							(&#40;file_of&#40;wk&#41; < FILE_C && p == SQ_C7&#41; || &#40;file_of&#40;wk&#41; == FILE_C && p == SQ_B6&#41;))
							own = 0; //4


						//white king supporting advance of pawn, in front of black king, and pawn in the middle of the kings, and wk on the left of the pawn
						//if &#40;own == unknown && file_of&#40;wk&#41; + 1 == file_of&#40;p&#41; && file_of&#40;p&#41; + 1 == file_of&#40;bk&#41; && rank_of&#40;wk&#41; == rank_of&#40;bk&#41;)
						if &#40;own == unknown &&
							&#40;file_of&#40;wk&#41; + 1 == file_of&#40;p&#41; ||
							&#40;file_of&#40;wk&#41; == file_of&#40;p&#41; - 2 && c == WHITE && !&#40;p == SQ_G6 && bk == SQ_H8&#41;)) &&  //avoid stalemate
							&#40;file_of&#40;p&#41; + 1 == file_of&#40;bk&#41; || &#40;file_of&#40;p&#41; + 2 == file_of&#40;bk&#41; && c == BLACK&#41;) &&
							(
							rank_of&#40;wk&#41; == rank_of&#40;bk&#41; ||
							&#40;abs&#40;rank_of&#40;wk&#41; - rank_of&#40;bk&#41;) == 1 && c == WHITE&#41;
							)
							)
							own = 2; //894

						//white king supporting advance of pawn, in front of black king, and pawn in the middle of the kings, and wk on the right of the pawn
						//if &#40;own == unknown && file_of&#40;wk&#41; - 1 == file_of&#40;p&#41; && file_of&#40;p&#41; - 1 == file_of&#40;bk&#41; && rank_of&#40;wk&#41; == rank_of&#40;bk&#41;)
						if &#40;own == unknown &&
							&#40;file_of&#40;wk&#41; - 1 == file_of&#40;p&#41; ||
							&#40;file_of&#40;wk&#41; == file_of&#40;p&#41; + 2 && c == WHITE && !&#40;p == SQ_B6 && bk == SQ_A8&#41;)) &&  //avoid stalemate
							&#40;file_of&#40;p&#41; - 1 == file_of&#40;bk&#41; || &#40;file_of&#40;p&#41; - 2 == file_of&#40;bk&#41; && c == BLACK&#41;) &&
							(
							rank_of&#40;wk&#41; == rank_of&#40;bk&#41; ||
							&#40;abs&#40;rank_of&#40;wk&#41; - rank_of&#40;bk&#41;) == 1 && c == WHITE&#41;
							)
							)
							own = 2; //894

						//white king supporting advance of pawn in same file of the pawn, and in front of black king
						if &#40;own == unknown &&
							&#40;file_of&#40;wk&#41; == file_of&#40;p&#41; ||
							&#40;abs&#40;file_of&#40;wk&#41; - file_of&#40;p&#41;) == 1 && c == WHITE&#41;) &&
							abs&#40;file_of&#40;p&#41; - file_of&#40;bk&#41;) == 2 &&
							(
							rank_of&#40;wk&#41; == rank_of&#40;bk&#41; ||
							&#40;abs&#40;rank_of&#40;wk&#41; - rank_of&#40;bk&#41;) == 1 && c == WHITE&#41;
							) &&
							file_of&#40;p&#41; != 0 && file_of&#40;p&#41; != 7
							)
							own = 2;  //860

						//black king reaches front of pawn
						if &#40;own == unknown && rank_of&#40;bk&#41; > rank_of&#40;p&#41; &&
							&#40;file_of&#40;bk&#41; == file_of&#40;p&#41; || &#40;abs&#40;file_of&#40;bk&#41; - file_of&#40;p&#41;) == 1 && c == BLACK&#41;) &&
							abs&#40;file_of&#40;wk&#41; - file_of&#40;p&#41;) > 1 &&
							&#40;rank_of&#40;bk&#41; <= rank_of&#40;wk&#41; || &#40;rank_of&#40;bk&#41; - 1 == rank_of&#40;wk&#41; && c == BLACK&#41;)
							)
							own = 0; //2528

						//black king disables advance of white king to support the pawn, from the left side
						//8/8/8/8/8/8/k2P4/2K5 b - - 0 1
						if &#40;own == unknown && file_of&#40;p&#41; > &#40;File&#41;1 && make_square&#40;file_of&#40;wk&#41; + &#40;File&#41;1, rank_of&#40;wk&#41; + &#40;Rank&#41;1&#41; == p &&
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; - &#40;File&#41;2, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; == &#40;c == BLACK ? 1 &#58; 0&#41; &&
							rank_of&#40;p&#41; < 5
							)
							own = 0; //88

						//black king disables advance of white king to support the pawn, from the right side
						if &#40;own == unknown && file_of&#40;p&#41; < &#40;File&#41;6 && make_square&#40;file_of&#40;wk&#41; - &#40;File&#41;1, rank_of&#40;wk&#41; + &#40;Rank&#41;1&#41; == p &&
							SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41; + &#40;File&#41;2, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; == &#40;c == BLACK ? 1 &#58; 0&#41; &&
							rank_of&#40;p&#41; < 5
							)
							own = 0; //88

						//white king reaches a good square to help to advance the pawn, against a king on the left side of the pawn
						if &#40;own == unknown && file_of&#40;p&#41; < 7 && file_of&#40;bk&#41; < file_of&#40;p&#41; && file_of&#40;p&#41; - file_of&#40;bk&#41; >= 2 + &#40;c == BLACK ? 1 &#58; 0&#41; && SquareDistance&#91;wk&#93;&#91;p&#93; < 2 &&
							rank_of&#40;bk&#41; < rank_of&#40;wk&#41; + 3 + &#40;c == WHITE && rank_of&#40;wk&#41; > rank_of&#40;p&#41; ? 1 &#58; 0&#41;
							)
							own = 2; //1551

						//white king reaches a good square to help to advance the pawn, against a king on the right side of the pawn
						if &#40;own == unknown && file_of&#40;p&#41; > 0 && file_of&#40;bk&#41; > file_of&#40;p&#41; && file_of&#40;bk&#41; - file_of&#40;p&#41; >= 2 + &#40;c == BLACK ? 1 &#58; 0&#41; && SquareDistance&#91;wk&#93;&#91;p&#93; < 2 &&
							rank_of&#40;bk&#41; < rank_of&#40;wk&#41; + 3 + &#40;c == WHITE && rank_of&#40;wk&#41; > rank_of&#40;p&#41; ? 1 &#58; 0&#41;
							)
							own = 2; //1551

						/*if &#40;own == unknown && rank_of&#40;p&#41;>2 && SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;2&#41;&#93; < SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;1&#41;&#93; - &#40;c == WHITE ? 1 &#58; 0&#41;) //black king blocks pawn to advance
							own = 0; */


						/*if &#40;own == unknown && rank_of&#40;p&#41; < 6 && rank_of&#40;p&#41; != 1 && SquareDistance&#91;wk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;2&#41;&#93; - &#40;c == WHITE ? 1 &#58; 0&#41; <= SquareDistance&#91;bk&#93;&#91;make_square&#40;file_of&#40;p&#41;, rank_of&#40;p&#41; + &#40;Rank&#41;2&#41;&#93; - &#40;c == BLACK ? 1 &#58; 0&#41;)
							own = 2;*/

						if &#40;own != 999 && abs&#40;own&#41; != abs&#40;v&#41;) &#123;
							sync_cout << "Error result&#58; pawn&#58; " << UCI&#58;&#58;square&#40;p&#41; << " wk&#58; " << UCI&#58;&#58;square&#40;wk&#41; << " bk&#58; " << UCI&#58;&#58;square&#40;bk&#41; << " color&#58; " << c << " own&#58; " << own << " good&#58; " << v << sync_endl;
							return;
						&#125;

						if &#40;own != unknown&#41;
							resolvedpositions++;
						else
							if (!first_unresolved_shown&#41; &#123;
								sync_cout << "1st unresolved&#58; pawn&#58; " << UCI&#58;&#58;square&#40;p&#41; << " wk&#58; " << UCI&#58;&#58;square&#40;wk&#41; << " bk&#58; " << UCI&#58;&#58;square&#40;bk&#41; << " color&#58; " << c << " good&#58; " << v << sync_endl;
								first_unresolved_shown = true;
							&#125;
					&#125;
				&#125;
			&#125;
		&#125;
		sync_cout << "Total positions&#58; " << totalpositions << " resolved positions&#58; " << resolvedpositions << sync_endl;
	&#125;