\r
void\r
Connect (int sqr, int piece, int dir)\r
-{\r
- int x, step = kStep[dir], r1 = p[piece].range[dir], r2 = p[piece].range[dir+1], piece1, piece2;\r
+{ // scan to both sides along ray to elongate attacks from there, and remove our own attacks on there, if needed\r
+ int x, step = kStep[dir], r1 = p[piece].range[dir], r2 = p[piece].range[dir+4], piece1, piece2;\r
int d1, d2, r, y, c;\r
\r
if((attacks[2*sqr] + attacks[2*sqr+1]) & attackMask[dir]) { // there are incoming attack(s) from 'behind'\r
attacks[2*y + (piece1 & WHITE)] += one[dir]; // count attack\r
UPDATE_MOBILITY(piece1, d2);\r
} else UPDATE_MOBILITY(piece1, r1 - d1); // does not connect, but could still gain mobility\r
- if(d1 + d2 <= (r2 = p[piece2].range[dir])) { // 2 hits 1\r
+ if(d1 + d2 <= (r2 = p[piece2].range[dir+4])) { // 2 hits 1\r
attacks[2*x + (piece2 & WHITE)] += one[dir+4]; // count attack\r
UPDATE_MOBILITY(piece2, d1);\r
} else UPDATE_MOBILITY(piece2, r2 - d2); // does not connect, but could still gain mobility\r
+ // if r1 or r2<0, moves typically jump, and thus cannot be unblocked. Exceptions are FF and BS distant moves.\r
+ // test for d1+d2 > 2 && rN == F && d== 3 or rN == S\r
\r
} else { // we were only attacked from behind\r
\r
r = (r2 = p[piece1].range[dir]) - d1;\r
- if(r < 0 || c > one[dir+1]) { // Oops! This was not our attacker, or not the only one. There must be a jump attack from even further behind!\r
+ if(r < 0 || c > one[dir+4]) { // Oops! This was not our attacker, or not the only one. There must be a jump attack from even further behind!\r
// for now, forget jumpers\r
}\r
y = sqr; \r
}\r
// we hit nothing with the extended move of the attacker behind us.\r
UPDATE_MOBILITY(piece1, r2 - d1);\r
- r = r1 - r2; // extra squares covered by mover\r
+ r = r1 - r2 + d1; // extra squares covered by mover\r
while(r-- > 0)\r
if(board[y+=step] != EMPTY) {\r
d2 = dist[y-sqr]; piece2 = board[y];\r
return;\r
}\r
}\r
+ // if r2<0 we should again test for F and S moves\r
\r
} else // no incoming attack from behind\r
if(c = (attacks[2*sqr] + attacks[2*sqr+1]) & attackMask[dir+4]) { // but incoming attack(s) from 'ahead'\r
}\r
// we hit nothing with the extended move of the attacker behind us.\r
UPDATE_MOBILITY(piece2, r2 - d1);\r
- r = r2 - r1; // extra squares covered by mover\r
+ r = r2 - r1 + d2; // extra squares covered by mover\r
while(r-- > 0)\r
if(board[x-=step] != EMPTY) {\r
d1 = dist[x-sqr]; piece1 = board[x];\r
}\r
}\r
\r
+inline int\r
+Hit (int r, int d)\r
+{ // test if move with range r reaches over (un-obstructed) distance d\r
+ if(r < 0) switch(r) {\r
+ case J: return (d == 2);\r
+ case D:\r
+ case L: return (d <= 2);\r
+ case T:\r
+ case F: return (d <= 3);\r
+ case S: return 1;\r
+ default: return 0;\r
+ } else return (d <= r);\r
+ return 0; // not reached\r
+}\r
+\r
void\r
-Disconnect (int sqr, int dir)\r
+Disconnect (int sqr, int piece, int dir)\r
{\r
- int x = sqr, step = kStep[dir], piece1, piece2, y;\r
+ int x = sqr, step = kStep[dir], piece1, piece2, d1, d2, r1, r2, y;\r
while( board[x+=step] == EMPTY );\r
- if(board[x] != EDGE) { // x has hit a piece\r
- piece1 = board[x];\r
+ piece1 = board[x];\r
+ if(piece1 != EDGE) { // x has hit a piece\r
+ d1 = dist[x-sqr];\r
+ r1 = p[piece1].range[dir+4];\r
y = sqr; while( board[y-=step] == EMPTY );\r
- if(board[y] != EDGE) { // both ends of the ray hit a piece\r
- piece2 = board[y];\r
- \r
+ piece2 = board[y];\r
+ if(piece2 != EDGE) { // both ends of the ray hit a piece\r
+ d2 = dist[y-sqr];\r
+ r2 = p[piece2].range[dir];\r
+ if(r1 >= d1) { // piece1 hits us\r
+ attacks[2*sqr + (piece1 & WHITE)] += one[dir+4];\r
+ if(r1 >= d1 + d2) // was hitting piece2 before, now blocked\r
+ attacks[2*y + (piece1 & WHITE)] -= one[dir+4];\r
+ }\r
+ if(r2 >= d2) { // piece2 hits us\r
+ attacks[2*sqr + (piece2 & WHITE)] += one[dir];\r
+ if(r2 >= d1 + d2) // was hitting piece1 before, now blocked\r
+ attacks[2*x + (piece2 & WHITE)] -= one[dir];\r
+ }\r
+ if( Hit(p[piece].range[dir], d1) )\r
+ attacks[2*sqr + stm] += one[dir];\r
+ if( Hit(p[piece].range[dir+4], d2) )\r
+ attacks[2*sqr + stm] += one[dir+4];\r
return;\r
}\r
} else {\r
x = sqr; while( board[x-=step] == EMPTY );\r
- if(board[x] == EDGE) return; // ray empty on both sides\r
+ piece1 = board[x];\r
+ if(piece1 == EDGE) return; // ray empty on both sides\r
+ d1 = dist[x-sqr];\r
+ r1 = p[piece1].range[dir];\r
+ dir += 4;\r
}\r
- // we only get here if one side hits a \r
- \r
+ // we only get here if one side looks to the board edge\r
+ if(r1 >= d1) // piece1 hits us\r
+ attacks[2*sqr + (piece1 & WHITE)] += one[dir^4];\r
+ if( Hit(p[piece].range[dir], d1) )\r
+ attacks[2*sqr + stm] += one[dir];\r
}\r
\r
void\r
{ // determines attacks on square and blocking when a piece lands on an empty square\r
int i;\r
for(i=0; i<4; i++) {\r
- Disconnect(sqr, i);\r
+ Disconnect(sqr, board[sqr], i);\r
}\r
}\r
\r