Quiescence Failure For Chess Varient

Discussion of chess software programming and technical issues.

Moderator: Ras

jdm64
Posts: 41
Joined: Thu May 27, 2010 11:32 pm

Quiescence Failure For Chess Varient

Post by jdm64 »

I'm designing a program to play a chess variant called Genesis Chess. Unfortunately, it seams the search functions are returning horrible results (like moves that result in immediate captures). I've tried several modifications to the Quiesence function (which I think the bug resides), but they have made little improvements. My evaluation function uses only material balance (and check).

So my questions are:
1) Is it impossible to get correct results using only material balance?
2) Are my Negascout & Quiescence functions implemented correctly?
3) Is there a way to make sure that the search functions are working?
4) Are there any other forums or resources that would help me solve this problem?

Code: Select all

int ComputerPlayer::Quiescence(MovesPly *&ptr, int alpha, int beta, int depth)
{
	int score;

	if (!ptr)
		ptr = board->getMovesList(board->currentPlayer());
	if (!ptr->size)
		return -(INT_MAX - 2);
	score = board->CalcScore();
	if (tactical[depth])
		score -= Board::pieceValues[15];
	if (score >= beta || depth >= maxQs)
		return score;
	alpha = max(score, alpha);

	sort(ptr->list.begin(), ptr->list.begin() + ptr->size, cmpHiLow);
	getKillerMoves(ptr, depth);

	if (!tactical[depth]) {
		for (int n = 0; n < ptr->size; n++) {
			if (ptr->list[n].move.xindex == NONE && !ptr->list[n].check)
					return alpha;
			tactical[depth + 1] = ptr->list[n].check;
			board->doMove(ptr->list[n].move);
			score = -Quiescence(ptr->list[n].next, -beta, -alpha, depth + 1);
			board->undo(ptr->list[n].move);

			delete ptr->list[n].next;
			ptr->list[n].next = NULL;
			if (score >= beta) {
				setKillerMoves(ptr->list[n].move, depth);
				return score;
			}
			alpha = max(alpha, score);
		}
	} else {
		for (int n = 0; n < ptr->size; n++) {
			tactical[depth + 1] = ptr->list[n].check;
			board->doMove(ptr->list[n].move);
			score = -Quiescence(ptr->list[n].next, -beta, -alpha, depth + 1);
			board->undo(ptr->list[n].move);

			delete ptr->list[n].next;
			ptr->list[n].next = NULL;
			if (score >= beta) {
				setKillerMoves(ptr->list[n].move, depth);
				return score;
			}
			alpha = max(alpha, score);
		}
	}
	return alpha;
}
int ComputerPlayer::NegaScout(MovesPly *&ptr, int alpha, int beta, int depth, int limit)
{
	int b = beta;

	if (!ptr)
		ptr = board->getMovesList(board->currentPlayer());
	if (!ptr->size)
		return -(INT_MAX - 2);
	if (depth >= limit)
		return Quiescence(ptr, alpha, beta, depth);
	sort(ptr->list.begin(), ptr->list.begin() + ptr->size, cmpHiLow);
	if (depth)
		getKillerMoves(ptr, depth);

	for (int n = 0; n < ptr->size; n++) {
		tactical[depth + 1] = ptr->list[n].check;
		board->doMove(ptr->list[n].move);
		ptr->list[n].score = -NegaScout(ptr->list[n].next, -b, -alpha, depth + 1, limit);

		if (ptr->list[n].score > alpha && ptr->list[n].score < beta && n > 0)
			ptr->list[n].score = -NegaScout(ptr->list[n].next, -beta, -alpha, depth + 1, limit);
		board->undo(ptr->list[n].move);

		delete ptr->list[n].next;
		ptr->list[n].next = NULL;

		alpha = max(ptr->list[n].score, alpha);
		if (alpha >= beta) {
 			setKillerMoves(ptr->list[n].move, depth);
			return alpha;
		}
		b = alpha + 1;
	}
	return alpha;
}
void ComputerPlayer::think()
{
	srand(time(NULL));
	tactical[0] = board->inCheck(board->currentPlayer());
	for (int depth = 0; depth <= maxNg; depth++)
		NegaScout(curr, -INT_MAX, INT_MAX, 0, depth);
	pickMove(curr);

	assert(board->doMove(curr->list[0].move, color) == VALID_MOVE);
	cout << board->printMove(curr->list[0].move) << endl;
	delete curr;
	curr = NULL;
}
If full source code would help, I can post it on request.
User avatar
Greg Strong
Posts: 388
Joined: Sun Dec 21, 2008 6:57 pm
Location: Washington, DC

Re: Quiescence Failure For Chess Varient

Post by Greg Strong »

This variant will be very, very difficult to implement in a way that plays intelligently.

For starters, take evaluation ... You say you are using material balance only. Ok, so do pieces "in hand" (that is, not on the board) count? They should because they're still your pieces. In fact, in some ways they are better... They have the ultimate in mobility because you can place them almost anywhere. But if you give a bonus for pieces in hand, then the engine will not want to drop them on the board and the kings will just move around aimlessly. So at the very least, you need your evaluation function to encourage dropping of pieces, but possibly also some holding of pieces in reserve. In particular, the pawns seem like excellent paratroopers and having at least one in hand requires the opponent to be careful. My super-quick two-cent analysis is to encourage dropping of heavy pieces in a way that establishes control of the center and encourage holding of some light pieces (e.g., Knights and Pawns,) probably on a sliding scale - that is, encourage dropping of the first pawns but as you have fewer and fewer in hand, give a bigger bonus for holding onto them.

Then there's the question of quiescence ... This is tough. You can only really evaluate quiescent ("quiet") positions. But what's really quiet when you have pieces in hand? Any position where you have a piece in hand that can be dropped in such a way that it forks two enemy pieces is not quiescent.

Not to discourage you, but you're biting into a pretty tough apple. My chess variant engine ChessV plays over 50 variants pretty well, but it doesn't support any variants with drops because these are so difficult to get right.

The universal engine Zillions-of-Games can be made to play this game without too much difficulty, and it will play at least somewhat competantly. Unfortunately, it considers pieces in hand to have little or no value, so as long as there is not a capture to be made, it's just going to keep dropping all its pieces in an attempt to dominate the center and not make a specific attempt to hold anything in reserve.
jdm64
Posts: 41
Joined: Thu May 27, 2010 11:32 pm

Re: Quiescence Failure For Chess Varient

Post by jdm64 »

Greg Strong wrote:This variant will be very, very difficult to implement in a way that plays intelligently.
Well, I'd be satisfied with any play that isn't seemingly committing suicide. Actually, I originally designed the rules with the explicit goal of being hard for a computer to play -- I guess I succeeded. In the opening moves the number of legal moves per turn can be as high as 320.
Greg Strong wrote:For starters, take evaluation ... You say you are using material balance only. Ok, so do pieces "in hand" (that is, not on the board) count? They should because they're still your pieces. In fact, in some ways they are better... They have the ultimate in mobility because you can place them almost anywhere. But if you give a bonus for pieces in hand, then the engine will not want to drop them on the board and the kings will just move around aimlessly. So at the very least, you need your evaluation function to encourage dropping of pieces, but possibly also some holding of pieces in reserve. In particular, the pawns seem like excellent paratroopers and having at least one in hand requires the opponent to be careful. My super-quick two-cent analysis is to encourage dropping of heavy pieces in a way that establishes control of the center and encourage holding of some light pieces (e.g., Knights and Pawns,) probably on a sliding scale - that is, encourage dropping of the first pawns but as you have fewer and fewer in hand, give a bigger bonus for holding onto them.
The current evaluation function gives equal weight to pieces in hand or on the board -- because I realize the double benefit. I do think that your "sliding scale" would be required for efficient evaluation, but my current primary concern is correctly implementing the search functions. Later, I'd add material score based probably on the difference in score for pieces on the board between the two players.
Greg Strong wrote:Then there's the question of quiescence ... This is tough. You can only really evaluate quiescent ("quiet") positions. But what's really quiet when you have pieces in hand? Any position where you have a piece in hand that can be dropped in such a way that it forks two enemy pieces is not quiescent.
Hmm. Actually, I never thought that piece placement would mess up the quiescence search. It makes sense. Would you recommend that quiescence be eliminated altogether? As it would be extremely hard to get to a quiet board state? Or would checking the placement moves be enough? Or adding just the "fork" placements?
Greg Strong wrote:The universal engine Zillions-of-Games can be made to play this game without too much difficulty, and it will play at least somewhat competently. Unfortunately, it considers pieces in hand to have little or no value, so as long as there is not a capture to be made, it's just going to keep dropping all its pieces in an attempt to dominate the center and not make a specific attempt to hold anything in reserve.
Well, dropping pieces like crazy isn't really a bad strategy -- as long as the piece is protected on placement. Actually, I'd be fairly satisfied if I could get the search functions to even return those moves as high valued. Currently, something must be wrong because the values that are propagating to the root result in all nearly identical values -- even for moves that would result in an instant capture for the opponent.
User avatar
smrf
Posts: 484
Joined: Mon Mar 13, 2006 11:08 am
Location: Klein-Gerau, Germany

Re: Quiescence Failure For Chess Varient

Post by smrf »

Some notation questions to your variant:

a) placement of a piece?
b) adapted FEN of a game position?
c) no promotions, as I presume?
User avatar
Greg Strong
Posts: 388
Joined: Sun Dec 21, 2008 6:57 pm
Location: Washington, DC

Re: Quiescence Failure For Chess Varient

Post by Greg Strong »

smrf wrote:Some notation questions to your variant:

a) placement of a piece?
b) adapted FEN of a game position?
c) no promotions, as I presume?
There are no promotions, double-space pawn moves, en passant, or castling.

Regarding notation of piece placement, if no decision has been made, I'd recommend "P*e4" for dropping a white pawn on e4. This is the notation usually used for Shogi.
User avatar
smrf
Posts: 484
Joined: Mon Mar 13, 2006 11:08 am
Location: Klein-Gerau, Germany

Re: Quiescence Failure For Chess Varient

Post by smrf »

Thank you.

So the board has no orientation. A missing of castlings might be tolerable, but not the loss of pwan directions. Why not restrict the placements of (unchanged) pawns to the board halfs of each player?

In chess the value of B/N is about 3 P. Having pawns not their traditional characteristic will increase their strength so much, that their value will become incommensurable to other pieces. Pawns as suggested here by me would increase their value to about 1.5, so exchanges will also remain calculatable, and the nature of chess is not violated that much.
jdm64
Posts: 41
Joined: Thu May 27, 2010 11:32 pm

Re: Quiescence Failure For Chess Varient

Post by jdm64 »

Greg Strong wrote:Regarding notation of piece placement, if no decision has been made, I'd recommend "P*e4" for dropping a white pawn on e4. This is the notation usually used for Shogi.
Well, my current notation used to enter piece placement for the terminal version of my program uses similar notation -- but without the "*", so just Pe4 or Qa2.
smrf wrote:b) adapted FEN of a game position?
I haven't thought about that, but I'd assume that the only alterations nessisary would be removing the Castling and En passant sections.
smrf wrote:So the board has no orientation. A missing of castlings might be tolerable, but not the loss of pwan directions. Why not restrict the placements of (unchanged) pawns to the board halfs of each player?
Actually my goal in designing the game was to have a non-orientated board setup. So having restrictions on pawn placements would go counter to that. Also if those changes were made then the game would be too similar to another chess variant that I found while looking for games similar to mine -- UnaChess. I actually think that my rules allow for a more balanced play.
smrf wrote:In chess the value of B/N is about 3 P. Having pawns not their traditional characteristic will increase their strength so much, that their value will become incommensurable to other pieces. Pawns as suggested here by me would increase their value to about 1.5, so exchanges will also remain calculatable, and the nature of chess is not violated that much.
Yes it is true that pawns become a very power piece for blocking/attacking, but I don't think it would make them incalculably powerful. From the many games I've played, most times they're played as a defensive piece. I don't see the game as unbalanced, henceforth I'm not going to change the rules (unless you could prove that the game is unfair without above alterations). My current value system is currently based on piece mobility permutations. If you think that my value system can be improved then I'm open to suggestions, but my main concern is the correctness of my search functions.
  • Pawn=11, Knight=34, Bishop=56, Rook=90, Queen=146
Anyways, I didn't post this thread to get a critique of the rules (you are welcome to do so). I'm trying to figure out if there's a flaw or technical limitation to my search algorithms. Currently, I think that my problem lies in my quiescence search. But, I don't know if I've either implemented it wrong or because of the unique nature of the rules no quiescence search could be possible.
User avatar
smrf
Posts: 484
Joined: Mon Mar 13, 2006 11:08 am
Location: Klein-Gerau, Germany

Re: Quiescence Failure For Chess Varient

Post by smrf »

There is something needed like the proposed '*' maybe '@' to distinguish placements from possible short moves' notations.

P.S. This also could be a delimiter concatenating a sorted list of still placable pieces to the end of the first FEN entry.

Chess has more chances for navigating to quiet positions because of the well matching fine commensurable value graining by pawn units compared to the bigger pieces' values. Your value estimation of non directed pawns seems to be far too low. Those incommensurable lowest piece value will make piece trades to mostly reach unbalanced material compositions, thus having the quiescence search tree nearly explode.
jdm64
Posts: 41
Joined: Thu May 27, 2010 11:32 pm

Re: Quiescence Failure For Chess Varient

Post by jdm64 »

smrf wrote:There is something needed like the proposed '*' maybe '@' to distinguish placements from possible short moves' notations.

P.S. This also could be a delimiter concatenating a sorted list of still placable pieces to the end of the first FEN entry.
Ok, then I'd rather use '@'. I've seen this used in crazyhouse notation.
smrf wrote:Chess has more chances for navigating to quiet positions because of the well matching fine commensurable value graining by pawn units compared to the bigger pieces' values. Your value estimation of non directed pawns seems to be far too low. Those incommensurable lowest piece value will make piece trades to mostly reach unbalanced material compositions, thus having the quiescence search tree nearly explode.
So, would you suggest just using negascout for the search? Or is there another function that could take the place of the quiescenc search?

If I increase the value of the pawn then the engine might more likely trade a more valuable piece for a pawn. There are more pawns than any other type of piece so the pawns are easily lost even if they have a strong playing force. The valuation should reflect this fact. So the sum of score by piece type becomes:
  • Knights=68, Pawns=88, Bishops=112, Rooks=180, Queen=146
User avatar
hgm
Posts: 28378
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Quiescence Failure For Chess Varient

Post by hgm »

This should not be any more difficult than a regular Crazyhouse engine. I see no reason why QS should not work. I think TJchess uses a normal QS (captures only, no drops). The rule that you cannot make drops that check makes this even more valid than in Crazyhouse or Shogi.

If you get non-sensical moves, my guess is that you have a search bug. By limiting the search depth to a very low value (like 1 or 2 ply), and examining the tree, it should be easy to find the variations that get a non-sensical score.