2017-03-29 17:30:37 +02:00
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
var geometry = Model.Game.cbBoardGeometryGrid(4,8);
|
|
|
|
|
|
|
|
Model.Game.cbDefine = function() {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
geometry: geometry,
|
|
|
|
|
|
|
|
pieceTypes: {
|
|
|
|
|
|
|
|
0: {
|
|
|
|
name: 'pawn-w',
|
|
|
|
aspect: 'pawn',
|
|
|
|
graph: this.cbPawnGraph(geometry,1),
|
|
|
|
value: 1,
|
|
|
|
abbrev: '',
|
|
|
|
fenAbbrev: 'P',
|
|
|
|
epCatch: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
1: {
|
|
|
|
name: 'ipawn-w',
|
|
|
|
aspect: 'pawn',
|
|
|
|
graph: this.cbInitialPawnGraph(geometry,1),
|
|
|
|
value: 1,
|
|
|
|
abbrev: '',
|
|
|
|
fenAbbrev: 'P',
|
|
|
|
initial: [{s:1,p:4},{s:1,p:5},{s:1,p:6},{s:1,p:7}],
|
|
|
|
epCatch: true,
|
|
|
|
epTarget: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
2: {
|
|
|
|
name: 'pawn-b',
|
|
|
|
aspect: 'pawn',
|
|
|
|
graph: this.cbPawnGraph(geometry,-1),
|
|
|
|
value: 1,
|
|
|
|
abbrev: '',
|
|
|
|
fenAbbrev: 'P',
|
|
|
|
epCatch: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
3: {
|
|
|
|
name: 'ipawn-b',
|
|
|
|
aspect: 'pawn',
|
|
|
|
graph: this.cbInitialPawnGraph(geometry,-1),
|
|
|
|
value: 1,
|
|
|
|
abbrev: '',
|
|
|
|
fenAbbrev: 'P',
|
|
|
|
initial: [{s:-1,p:24},{s:-1,p:25},{s:-1,p:26},{s:-1,p:27}],
|
|
|
|
epCatch: true,
|
|
|
|
epTarget: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
4: {
|
|
|
|
name: 'knight',
|
|
|
|
graph: this.cbKnightGraph(geometry),
|
|
|
|
value: 2.9,
|
|
|
|
abbrev: 'N',
|
|
|
|
initial: [{s:1,p:2},{s:-1,p:30}],
|
|
|
|
},
|
|
|
|
|
|
|
|
5: {
|
|
|
|
name: 'bishop',
|
|
|
|
graph: this.cbBishopGraph(geometry),
|
|
|
|
value: 3.1,
|
|
|
|
abbrev: 'B',
|
|
|
|
initial: [{s:1,p:1},{s:-1,p:29}],
|
|
|
|
},
|
|
|
|
|
|
|
|
6: {
|
|
|
|
name: 'rook',
|
|
|
|
graph: this.cbRookGraph(geometry),
|
|
|
|
value: 5,
|
|
|
|
abbrev: 'R',
|
|
|
|
initial: [{s:1,p:3},{s:-1,p:31}],
|
|
|
|
castle: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
7: {
|
|
|
|
name: 'queen',
|
|
|
|
graph: this.cbQueenGraph(geometry),
|
|
|
|
abbrev: 'Q',
|
|
|
|
},
|
|
|
|
|
|
|
|
8: {
|
|
|
|
name: 'king',
|
|
|
|
isKing: true,
|
|
|
|
graph: this.cbKingGraph(geometry),
|
|
|
|
abbrev: 'K',
|
|
|
|
initial: [{s:1,p:0},{s:-1,p:28}],
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
promote: function(aGame,piece,move) {
|
|
|
|
if(piece.t==1)
|
|
|
|
return [0];
|
|
|
|
else if(piece.t==3)
|
|
|
|
return [2];
|
|
|
|
else if(piece.t==0 && geometry.R(move.t)==7)
|
|
|
|
return [4,5,6,7];
|
|
|
|
else if(piece.t==2 && geometry.R(move.t)==0)
|
|
|
|
return [4,5,6,7];
|
|
|
|
return [];
|
|
|
|
},
|
|
|
|
|
|
|
|
castle: {
|
|
|
|
"0/3": {k:[1,2],r:[2,1],n:"O-O"},
|
2017-08-15 17:19:29 +02:00
|
|
|
"28/31": {k:[29,30],r:[30,29],n:"O-O"},
|
2017-03-29 17:30:37 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
evaluate: function(aGame,evalValues,material) {
|
|
|
|
// check lack of material to checkmate
|
|
|
|
var white=material[1].count;
|
|
|
|
var black=material[-1].count;
|
|
|
|
if(!white[0] && !white[1] && !white[4] && !white[5] && !white[6] && !white[7]) { // white king single
|
|
|
|
if(!black[2] && !black[3] && !black[6] && !black[7] && (black[4]+black[5]<2 || black[5]<2)) {
|
|
|
|
this.mFinished=true;
|
|
|
|
this.mWinner=JocGame.DRAW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!black[2] && !black[3] && !black[4] && !black[5] && !black[6] && !black[7]) { // black king single
|
|
|
|
if(!white[0] && !white[1] && !white[6] && !white[7] && (white[4]+white[5]<2 || white[5]<2)) {
|
|
|
|
this.mFinished=true;
|
|
|
|
this.mWinner=JocGame.DRAW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check 50 moves without capture
|
|
|
|
if(this.noCaptCount>=100) {
|
|
|
|
this.mFinished=true;
|
|
|
|
this.mWinner=JocGame.DRAW;
|
|
|
|
}
|
|
|
|
|
|
|
|
// motivate pawns to reach the promotion line
|
|
|
|
var distPromo=aGame.cbUseTypedArrays?new Int8Array(3):[0,0,0];
|
|
|
|
var height=geometry.height;
|
|
|
|
var pawns=material[1].byType[0],pawnsLength;
|
|
|
|
if(pawns) {
|
|
|
|
pawnsLength=pawns.length;
|
|
|
|
for(var i=0;i<pawnsLength;i++)
|
|
|
|
switch(height-geometry.R(pawns[i].p)) {
|
|
|
|
case 2: distPromo[0]++; break;
|
|
|
|
case 3: distPromo[1]++; break;
|
|
|
|
case 4: distPromo[2]++; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pawns=material[-1].byType[2],pawnsLength;
|
|
|
|
if(pawns) {
|
|
|
|
pawnsLength=pawns.length;
|
|
|
|
for(var i=0;i<pawnsLength;i++)
|
|
|
|
switch(geometry.R(pawns[i].p)) {
|
|
|
|
case 1: distPromo[0]--; break;
|
|
|
|
case 2: distPromo[1]--; break;
|
|
|
|
case 3: distPromo[2]--; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(distPromo[0]!=0)
|
|
|
|
evalValues['distPawnPromo1']=distPromo[0];
|
|
|
|
if(distPromo[1]!=0)
|
|
|
|
evalValues['distPawnPromo2']=distPromo[1];
|
|
|
|
if(distPromo[2]!=0)
|
|
|
|
evalValues['distPawnPromo3']=distPromo[2];
|
|
|
|
|
|
|
|
// motivate knights and bishops to deploy early
|
|
|
|
var minorPiecesMoved=0;
|
|
|
|
for(var t=4;t<=5;t++)
|
|
|
|
for(var s=1;s>=-1;s-=2) {
|
|
|
|
var pieces=material[s].byType[t];
|
|
|
|
if(pieces)
|
|
|
|
for(var i=0;i<pieces.length;i++)
|
|
|
|
if(pieces[i].m)
|
|
|
|
minorPiecesMoved+=s;
|
|
|
|
}
|
|
|
|
if(minorPiecesMoved!=0) {
|
|
|
|
evalValues['minorPiecesMoved']=minorPiecesMoved;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-08-16 12:36:28 +02:00
|
|
|
})();
|