|
457 | 457 | castle:{ |
458 | 458 | }, |
459 | 459 |
|
460 | | - evaluate: function(aGame,evalValues,material) { |
| 460 | + evaluate: function(aGame,evalValues,material,pieceCnt,pieceValue) { |
461 | 461 |
|
462 | 462 | // check lack of material to checkmate |
463 | 463 | var white=material[1].count; |
464 | 464 | var black=material[-1].count; |
465 | | - var pieceCnt = 0, n = white.length; |
466 | | - |
467 | | - for(var i=0; i<n && pieceCnt<2; i++) pieceCnt += white[i]; |
468 | | - if(pieceCnt <= 1 // white king single |
| 465 | + |
| 466 | + if(pieceCnt[1] <= 1 // white king single |
469 | 467 | || white[10] + white[28] == 0) { // or captured |
470 | 468 | this.mFinished=true; |
471 | 469 | this.mWinner=-1; |
472 | 470 | } |
473 | | - pieceCnt = 0; |
474 | | - for(var i=0; i<n && pieceCnt<2; i++) pieceCnt += black[i]; |
475 | | - if(pieceCnt <= 1 // black king single |
| 471 | + |
| 472 | + if(pieceCnt[-1] <= 1 // black king single |
476 | 473 | || black[10] + black[28] == 0) { // or captured |
477 | 474 | this.mFinished=true; |
478 | 475 | this.mWinner=1; |
479 | 476 | } |
480 | 477 |
|
481 | 478 | // reconstruct piece values per player |
482 | | - var difVal = evalValues['pieceValue']; |
483 | | - var totVal = difVal/evalValues['pieceValueRatio'] - 1; |
484 | | - var wVal = 0.5*(totVal + difVal) + 4; |
485 | | - var bVal = 0.5*(totVal - difVal) + 4; |
| 479 | + var wVal = pieceValue[1] + 4; |
| 480 | + var bVal = pieceValue[-1] + 4; |
486 | 481 |
|
487 | 482 | // calculate expected material gain from promotions |
488 | 483 | var wProm = 0, bProm = 0; // promotion gain |
489 | | - for(var i=0; i<n; i++) { // what players gain if all their pieces promote |
490 | | - var gain = promoGain[i]; |
491 | | - wProm += white[i] * gain; |
492 | | - bProm += black[i] * gain; |
493 | | - } |
| 484 | + this.pieces.forEach(function(piece,index) { |
| 485 | + if(piece.p<0 || piece.t>18 || piece.t==10) return; // absent, already promoted or king |
| 486 | + var h=geometry.height; |
| 487 | + var factor=0.9, s=speed[piece.t]; |
| 488 | + if(s) { // reduce bonus for leapers that have far to go |
| 489 | + var rank=geometry.R(piece.p); |
| 490 | + if(piece.s<0) rank=h-1-rank; // convert to player POV |
| 491 | + if(rank>8) rank=8; // flat in zone |
| 492 | + rank+=2; |
| 493 | + factor-=(64-rank*rank)*s*0.002; // deduct up to 0.72 (for 1st-rank stepper) |
| 494 | + } |
| 495 | + factor*=promoGain[piece.t]; |
| 496 | + if(piece.s>0) wProm+=factor; else bProm +=factor; |
| 497 | + }); |
494 | 498 | var wFrac = (bVal < 20 ? 1 : (wVal - bVal + 20)/wVal); // likely fraction to promote |
495 | 499 | var bFrac = (wVal < 20 ? 1 : (bVal - wVal + 20)/bVal); |
496 | | -// evalValues['pieceValue'] += 0.9*(wFrac*wProm - bFrac*bProm); |
497 | | - |
498 | | - // motivate pawns to reach the promotion line |
499 | | - var distPromo=aGame.cbUseTypedArrays?new Int8Array(3):[0,0,0]; |
500 | | - var height=geometry.height; |
501 | | - var pawns=material[1].byType[0],pawnsLength; |
502 | | - if(pawns) { |
503 | | - pawnsLength=pawns.length; |
504 | | - for(var i=0;i<pawnsLength;i++) |
505 | | - switch(height-geometry.R(pawns[i].p)) { |
506 | | - case 4: distPromo[0]++; break; |
507 | | - case 5: distPromo[1]++; break; |
508 | | - case 6: distPromo[2]++; break; |
509 | | - } |
510 | | - } |
511 | | - pawns=material[-1].byType[2],pawnsLength; |
512 | | - if(pawns) { |
513 | | - pawnsLength=pawns.length; |
514 | | - for(var i=0;i<pawnsLength;i++) |
515 | | - switch(geometry.R(pawns[i].p)) { |
516 | | - case 3: distPromo[0]--; break; |
517 | | - case 4: distPromo[1]--; break; |
518 | | - case 5: distPromo[2]--; break; |
519 | | - } |
520 | | - } |
521 | | - if(distPromo[0]!=0) |
522 | | - evalValues['distPawnPromo1']=distPromo[0]; |
523 | | - if(distPromo[1]!=0) |
524 | | - evalValues['distPawnPromo2']=distPromo[1]; |
525 | | - if(distPromo[2]!=0) |
526 | | - evalValues['distPawnPromo3']=distPromo[2]; |
527 | | - |
528 | | - // motivate knights and bishops to deploy early |
529 | | - var minorPiecesMoved=0; |
530 | | - for(var tt=4;tt<=5;tt++) |
531 | | - for(var s=1;s>=-1;s-=2) { |
532 | | - var pieces=material[s].byType[tt]; |
533 | | - if(pieces) |
534 | | - for(var i=0;i<pieces.length;i++) |
535 | | - if(pieces[i].m) |
536 | | - minorPiecesMoved+=s; |
537 | | - } |
538 | | - if(minorPiecesMoved!=0) { |
539 | | - evalValues['minorPiecesMoved']=minorPiecesMoved; |
540 | | - } |
541 | | - |
| 500 | + evalValues['pieceValue'] += 0.9*(wFrac*wProm - bFrac*bProm); |
542 | 501 | } |
543 | 502 |
|
544 | 503 | } |
|
672 | 631 | } } } |
673 | 632 |
|
674 | 633 | var promoGain = []; |
| 634 | + var speed = [9,9,6,7,3,4,3,2,3,4,-6,5,3,3,0,0,7,3,0]; |
675 | 635 |
|
676 | 636 | var OriginalInitialPosition = Model.Board.InitialPosition; |
677 | 637 | Model.Board.InitialPosition = function(aGame) { |
|
0 commit comments