concerns on negamax material implementation

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: concerns on negamax material implementation

Post by Fguy64 »

diep wrote:
Fguy64 wrote:
diep wrote:
Fguy64 wrote:Greetings.

I am trying to implement a little minimax (negamax?) material evaluation into my engine, and I am not sure how to interpret the results. At this point I don't care if my strategy is good or bad, only that the results are to be expected given what I have done. There is as yet no alpha beta pruning, and no quiescense, which might be my problem. As you can no doubt tell, I'm kind of new at actually doing this stuff.

- Ok, I have a recursive algorithm that is currently set at 5 ply, but the actual number shouldn't matter.
- For each move at each ply, the engine generates a list of legal moves, this part is working fine.
- At the final ply (ply 1) we don't look for replies, just calculate the material balance. Material balance is only calculated at the final ply. The material calculation works fine.
- When the ply is an even number, a move eval is the maximum of all the reply evals. When the ply is an odd number, the move eval is the minimum eval of all the replies. Thus at the very first ply, the eval for each possible engine move is the minimum value of all the possible replies. The engine will then choose the move with the maximum eval.
- My material calc uses the following: P=10, N=25, B=30, R=50, Q=90.

As an example, consider the move 1.a4 The algorithm assigns the reply 1...b5 a value of 20 in white's favor. This surprises me somewhat, I would have expected that given a correct minimax implementation, the value would be 10 ( 1 pawn ) given correct subsequent play on a material basis.

Another example is every reply to 1.b3 evaluating to 10 in favor of white.


The question is whether this is all because of no quiescense, or some serious flaw in my logic that I can't see. If needed, I can post some code, it's in pretty good shape.

Thanks.
Negamax = search
material considerations = evaluation

I see those as 2 different entities actually.

minimax material evaluation, what do you mean by that,
that the root of it should give a good static material evaluation?

Or do you mean you want to build a fast searcher with just material evaluation at first?

Whatever you do in that case, you can't escape using a qsearch.
Ok, it seems I use the terminology improperly. That doesn't surprise me. Anyways, This post you quoted is kind of old, I just posted an algorithm in my previous post, I'm more interested in that now. I am hoping the pseudo code will speak for itself.
You're forgetting to make moves in your evaluation, which actually is the search. The call to the function to count material (or you could do it incremental) is what we call evaluation normally spoken.

So you keep evaluating the same position, position never changes. Also you're doing the compare at depth==1 instead of depth <= 0

adding making moves and unmaking moves fixes all this.

Vincent
ok I can see where you might have got that impression. but...

evaluate( fen1, ply ) { // evaluate is recursive function.

this is not a function call, it is the function header I suppose that was sloppy on my part, I will try to edit the post
Last edited by Fguy64 on Sun Aug 02, 2009 4:38 am, edited 1 time in total.
Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: concerns on negamax material implementation

Post by Fguy64 »

OK, it's a couple days later, and this stuff is making my head spin. I thought I'd write down my algorithm is pseudo code and post it here. It seems right to me, but I guess I'll see about that.

OK this represents an arbitrary ply n, negamax algorithm, pruning is not yet represented, I'll make sure I have this part correct. first.

Note that details about quiscense are buried in the material evaluation function.

how does it look so far? Thanks.

Code: Select all

makeMove&#40;) &#123;
	ply = n;
	fen = arbitrary starting position and game state;

	list1 = possiblesMoves&#40;fen&#41;;	// possibleMoves is non recursive.
	max = -10,000;					// initial value is lower than any possible eval

	for each move m in list1 &#123;
		fen1 = position after m;
		m.eval = evaluate&#40;fen1, ply&#41;;        /// small correction here
		if&#40; m.eval > max ) max = m.eval;
	&#125;

	return random selection from moves where eval = max.
&#125;

int evaluate&#40; fen1, ply ) &#123;  // function header

	if&#40; ply == 1&#41; return material eval of fen1, including quiescence.
	
	max = -10,000;

	list2 = possibleMoves&#40; fen1 );
	for each move m in list2 &#123;
		fen2 = posn after m;
		m.eval = evaluate&#40; fen2, ply-1 );		// recursion step.
		if&#40; m.eval > max ) max = m.eval;
	&#125;
	
	return -max;								// why we call it negamax ?
&#125;
note the revision, the function header is more clearly denoted