The NextMove() and NextEvasions() functions in Crafty also re-appear in pre-Beta Rybka. I will give the latter completely, and for reasons of length just point out one identical element in NextMove().
Crafty uses phases 1, 4, and 10 in NextEvasion(). Here is high-level logic in pre-Beta Rybka.
0x00459c70: sub $0xc,%esp # NextEvasion() function
0x00459c75: mov 0x18(%esp),%esi
0x00459c7a: mov 0x20(%esp),%edi
0x00459c7e: lea (%edi,%edi,2),%eax
0x00459c81: lea (%esi,%eax,4),%ebx
0x00459c8b* mov %ebx,0xc(%esp)
0x00459c84: mov 0xb20(%ebx),%eax # get current phase
0x00459c8a: dec %eax # (sub 1 from it)
0x00459c8f: je 0x459ca8 # if phase was 1, then ...
0x00459c91: sub $0x6,%eax # (sub 6 more)
0x00459c94: je 0x459cea # if phase was 7, then...
0x00459c96: sub $0x3,%eax # (sub 3 more)
0x00459c99: je 0x459e9c # if phase was 10, then...
0x00459ca1: xor %eax,%eax # phase is bad, return 0
0x00459ca7: ret
Here is the first part of NextEvasion(), for the case HASH_MOVE:
int NextEvasion(TREE * RESTRICT tree, int ply, int wtm){registerint*movep, *sortv;switch(tree->next_status[ply].phase){case HASH_MOVE:
tree->last[ply]=GenerateCheckEvasions(tree, ply, wtm, tree->last[ply-1]);if(tree->hash_move[ply]){
tree->next_status[ply].phase=SORT_ALL_MOVES;
tree->current_move[ply]=tree->hash_move[ply];if(ValidMove(tree,ply,wtm,tree->current_move[ply]))return(HASH_MOVE);else Print(128,"bad move from hash table, ply=%d\n",ply);}
0x00459ca8: mov 0x137c(%esi,%edi,4),%ecx # ptr to tree->last[ply-1]
0x00459caf: mov 0x24(%esp),%edx
0x00459cb3: push %ecx, %edx, %edi, %esi
0x00459cb7: call 0x452860 # call GenerateCheckEvasions()
0x00459cbc: mov %eax,0x1380(%esi,%edi,4) # save ptr in tree->last[ply]
0x00459cc3: mov (%esi,%edi,4),%eax # load tree->hash_move[ply]
0x00459cc9: test %eax,%eax # if this is zero
0x00459ccb: je 0x459cea # then goto the next phase
0x00459ccd: mov %eax,0x1060(%esi,%edi,4) # tree->current_move[ply] = tree->hash_move[ply]
0x00459cd6: movl $0x7,0xb20(%ebx) # set phase to 7 (SORT_ALL_MOVES)
0x00459ce0: mov $0x1,%eax # return 1
0x00459ce9: ret
Note that this pre-Beta Rybka seems not to have a ValidMove routine.
Here is the SORT_ALL_MOVES case.
case SORT_ALL_MOVES:
tree->next_status[ply].phase=REMAINING_MOVES;if(tree->hash_move[ply]){for(movep=tree->last[ply-1],sortv=tree->sort_value;
movep<tree->last[ply];movep++,sortv++)if(*movep == tree->hash_move[ply]){*sortv=-999999;*movep=0;}else{if(p_values[Piece(*movep)+7]< p_values[Captured(*movep)+7])*sortv=p_values[Captured(*movep)+7]-p_values[Piece(*movep)+7];else*sortv=Swap(tree,From(*movep),To(*movep),wtm);}}else{for(movep=tree->last[ply-1],sortv=tree->sort_value;
movep<tree->last[ply];movep++,sortv++)if(p_values[Piece(*movep)+7]< p_values[Captured(*movep)+7])*sortv=p_values[Captured(*movep)+7]-p_values[Piece(*movep)+7];else*sortv=Swap(tree,From(*movep),To(*movep),wtm);}
Note that pre-Beta Rybka also uses -999999 as the sentinel.
0x00459cea: mov (%esi,%edi,4),%eax # load tree->hash_move[ply]
0x00459cee: mov 0x137c(%esi,%edi,4),%ebp
0x00459cf5: movl $0xa,0xb20(%ebx) # tree->next_status[ply].phase=REMAINING_MOVES;
0x00459cff: test %eax,%eax
0x00459d01: mov 0x1380(%esi,%edi,4),%eax
0x00459d08: lea 0x1564(%esi),%ebx
0x00459d0e: je 0x459d87 # if (tree->hash_move[ply])
0x00459d10: cmp %eax,%ebp
0x00459d12: jae 0x459de9 # set up for loop
0x00459d18: mov 0x0(%ebp),%eax LOOP
0x00459d1b: cmp (%esi,%edi,4),%eax # if (*movep == tree->hash_move[ply]
0x00459d1e: jne 0x459d2f
0x00459d20: movl $0xfff0bdc1,(%ebx) # *sortv = -999999
0x00459d26: movl $0x0,0x0(%ebp) # *movep = 0
0x00459d2d: jmp 0x459d74 # else
0x00459d2f: mov %eax,%ecx
0x00459d31: sar $0xf,%ecx # Captured(*movep)
0x00459d34: mov %eax,%edx
0x00459d36: sar $0xc,%edx # Piece(*movep)
0x00459d39: and $0x7,%ecx
0x00459d3c: mov 0x5ffed4(,%ecx,4),%ecx # y = p_values[Captured(*movep) + 7]
0x00459d43: and $0x7,%edx
0x00459d46: mov 0x5ffed4(,%edx,4),%edx # x = p_values[Captured(*movep) + 7]
0x00459d4d: cmp %ecx,%edx
0x00459d4f: jge 0x459d57 # if (x < y)
0x00459d51: sub %edx,%ecx
0x00459d53: mov %ecx,(%ebx) # *sortv= y - x
0x00459d55: jmp 0x459d74 # else
0x00459d57: mov 0x28(%esp),%ecx # load tree pointer
0x00459d5b: mov %eax,%edx
0x00459d5e: sar $0x6,%edx
0x00459d61: and $0x3f,%edx # To(*movep)
0x00459d65: and $0x3f,%eax # From(*movep)
0x00459d69* push %ecx, %edx, %eax, %esi
0x00459d6a: call 0x45ad80 # Swap(tree,From(*movep),To(*movep),wtm)
0x00459d6f: add $0x10,%esp
0x00459d72: mov %eax,(%ebx)
0x00459d74: mov 0x1380(%esi,%edi,4),%eax # determine if loop is done
0x00459d7b: add $0x4,%ebp
0x00459d7e: add $0x4,%ebx
0x00459d81: cmp %eax,%ebp
0x00459d83: jb 0x459d18 # if not done, goto LOOP
0x00459d85: jmp 0x459de9
0x00459d87: cmp %eax,%ebp # else [that is, tree->hash_move[ply] is zero]
0x00459d89: jae 0x459de9
0x00459d8b: jmp 0x459d90
0x00459d8d: lea 0x0(%ecx),%ecx
0x00459d90: mov 0x0(%ebp),%eax LOOP2 START
0x00459d93: mov %eax,%ecx
0x00459d95: sar $0xf,%ecx # Captured(*movep)
0x00459d98: mov %eax,%edx
0x00459d9a: sar $0xc,%edx
0x00459d9d: and $0x7,%ecx # Piece(*movep)
0x00459da0: mov 0x5ffed4(,%ecx,4),%ecx # y = p_values[Captured(*movep) + 7]
0x00459da7: and $0x7,%edx
0x00459daa: mov 0x5ffed4(,%edx,4),%edx # x = p_values[Captured(*movep) + 7]
0x00459db1: cmp %ecx,%edx # if (x < y)
0x00459db3: jge 0x459dbb
0x00459db5: sub %edx,%ecx
0x00459db7: mov %ecx,(%ebx) # *sortv = y - x
0x00459db9: jmp 0x459dd8 # else
0x00459dbb: mov 0x28(%esp),%ecx
0x00459dbf: mov %eax,%edx
0x00459dc2: sar $0x6,%edx
0x00459dc5: and $0x3f,%edx # To(*movep)
0x00459dc9: and $0x3f,%eax # From(*movep)
0x00459dcd: push %ecx, %edx, %eax, %esi
0x00459dce: call 0x45ad80 # call Swap()
0x00459dd6: mov %eax,(%ebx) # *sortv = value from Swap()
0x00459dd8: mov 0x1380(%esi,%edi,4),%eax # determine if loop is done
0x00459ddf: add $0x4,%ebp
0x00459de2: add $0x4,%ebx
0x00459de5: cmp %eax,%ebp
0x00459de7: jb 0x459d90 # if not, goto LOOP2
Next Crafty does an insertion sort in this SORT_ALL_MOVES phase.
case REMAINING_MOVES:for(;tree->next_status[ply].last<tree->last[ply];
tree->next_status[ply].last++)if((*tree->next_status[ply].last)){
tree->current_move[ply]=*tree->next_status[ply].last++;return(REMAINING_MOVES);}return(NONE);
In the second segment, the condition that the number of moves be greater than 3 cannot be said to be typical. Here is the pre-Beta Rybka code for this segment:
< Prev
Table of Contents
by Mark Watkins
The NextMove() and NextEvasions() functions in Crafty also re-appear in pre-Beta Rybka. I will give the latter completely, and for reasons of length just point out one identical element in NextMove().
Phases
First, we have Crafty's numbering of phases.NextEvasion
Crafty uses phases 1, 4, and 10 in NextEvasion(). Here is high-level logic in pre-Beta Rybka.Here is the first part of NextEvasion(), for the case HASH_MOVE:
Note that this pre-Beta Rybka seems not to have a ValidMove routine.
Here is the SORT_ALL_MOVES case.
Note that pre-Beta Rybka also uses -999999 as the sentinel.
Next Crafty does an insertion sort in this SORT_ALL_MOVES phase.
As does pre-Beta Rybka -- I'm not sure comments are that useful.
And finally the REMAINING_MOVES case.
NextMove
Here is the 9th phase in both Crafty and pre-Beta Rybka. It is already somewhat odd to have this HISTORY_MOVES_2 phase.In the second segment, the condition that the number of moves be greater than 3 cannot be said to be typical. Here is the pre-Beta Rybka code for this segment:
The exact similarity with the totality of NextMove() is yet to be determined, but the above should suffice to give an example of code re-use.
What links here?
Up one level