1 /***************************************************************************
2 attack.cpp - Implmentation of attacking-related functions
4 begin : Dom Oct 30 2005
5 copyright : (C) 2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
22 Board::under_attack(uint8_t pos
,uint8_t attacker
)
33 /* check bishop or rook attacks */
34 A88 attacks
= IS_WHITE(attacker
) ? w_attacks
: b_attacks
;
37 #endif //TRACK_ATTACKS
39 /* check if attacked by a knight */
40 killer
= KNIGHT
|attacker
;
42 KnightMove
* hm
= &knightmoves
[pos
];
43 for(int i
=hm
->numm
;i
>=0;i
--)
45 register uint8_t tmp
= hm
->jump
[i
];
54 /* check bishop (or queen) attacks */
55 killer
= BISHOP
|attacker
;
64 if(OUT_OF_BOARD(check
))
66 if((d
[check
] & ((uint8_t)~ROOK
)) == killer
)
69 while(IS_VOID(d
[check
]));
72 /* check rook (or queen) attacks */
73 killer
= ROOK
|attacker
;
82 if(OUT_OF_BOARD(check
))
84 if((d
[check
] & ((uint8_t)~BISHOP
)) == killer
)
87 while(IS_VOID(d
[check
]));
89 #endif // !TRACK_ATTACKS
91 /* check if attacked by a pawn */
93 killer
= PAWN
|attacker
;
94 check
= pos
- up_dir
[IS_WHITE(attacker
)] + RIGHT
;
95 if(!OUT_OF_BOARD(check
) && (d
[check
] == killer
))
99 if(!OUT_OF_BOARD(check
) && (d
[check
] == killer
))
103 /* check if attacked by the other king */
105 killer
= KING
|attacker
;
106 for(int i
=7;i
>=0;i
--)
108 check
= pos
+ kingmoves
[i
];
109 if(OUT_OF_BOARD(check
))
111 if(d
[check
] == killer
)
118 /* count attackes (end possibly defenders) of a piece/square.
119 an array is passed to give info about pinned attacker pieces */
121 Board::list_attackers(uint8_t pos
, uint8_t attacker
, A88 pins
, AttackList
* a
)
127 a
[num_atck
].curr
= a
[num_atck
].count
= 0;
129 /* check if attacked by a knight */
130 killer
= KNIGHT
|attacker
;
132 KnightMove
* hm
= &knightmoves
[pos
];
133 for(int i
=hm
->numm
;i
>=0;i
--)
135 register uint8_t tmp
= hm
->jump
[i
];
136 if(d
[tmp
] == killer
&& !pins
[tmp
])
137 a
[num_atck
].piece
[a
[num_atck
].count
++] = KNIGHT
;
141 /* check if attacked by the king.
142 the king cannot be pinned, at least :) */
144 int deltax
= X(king_pos
[IS_WHITE(attacker
)])-X(pos
);
145 int deltay
= Y(king_pos
[IS_WHITE(attacker
)])-Y(pos
);
146 if(ABS(deltax
)<=1 && ABS(deltay
)<=1)
147 a
[num_atck
].piece
[a
[num_atck
].count
++] = KING
;
150 if(a
[num_atck
].count
)
154 A88 attacks
= IS_WHITE(attacker
) ? w_attacks
: b_attacks
;
155 uint8_t up1
= up_dir
[1-IS_WHITE(attacker
)] + LEFT
;
156 uint8_t up2
= up_dir
[1-IS_WHITE(attacker
)] + RIGHT
;
162 if(!(attacks
[pos
] & m
))
165 uint8_t inc
= -attack_dirs
[r
];
166 uint8_t currpos
= pos
+inc
;
167 a
[num_atck
].curr
= a
[num_atck
].count
= 0;
169 if( (inc
== up1
|| inc
== up2
)
170 && !OUT_OF_BOARD(currpos
)
171 && d
[currpos
]==(PAWN
|attacker
) )
173 /* we found a pawn, enlist it and skip */
174 a
[num_atck
].piece
[a
[num_atck
].count
++] = PAWN
;
178 while(!OUT_OF_BOARD(currpos
))
182 a
[num_atck
].piece
[a
[num_atck
].count
++] = PIECE_OF(d
[currpos
]);
183 if(!(attacks
[currpos
] & m
))
190 if(a
[num_atck
].count
)
193 #else //TRACK_ATTACKS
194 /* check bishop (or queen) attacks */
195 killer
= BISHOP
|attacker
;
197 for(int i
=3;i
>=0;i
--)
199 uint8_t inc
= bishmoves
[i
];
200 uint8_t currpos
= pos
+inc
;
201 a
[num_atck
].curr
= a
[num_atck
].count
= 0;
203 if(OUT_OF_BOARD(currpos
))
205 if( ( (0xf0&(inc
+1)) == up_dir
[1-IS_WHITE(attacker
)])
206 && d
[currpos
]==(PAWN
|attacker
)
207 && (!pins
[currpos
] || ((pins
[currpos
]&DIAG
) &&
208 (bishmoves
[pins
[currpos
]&0x0f]==inc
||
209 bishmoves
[pins
[currpos
]&0x0f]==(uint8_t)-inc
))))
211 /* we found a pawn, enlist it and skip */
212 a
[num_atck
].piece
[a
[num_atck
].count
++] = PAWN
;
218 if(OUT_OF_BOARD(currpos
))
220 if( ((d
[currpos
] & ((uint8_t)~ROOK
))==killer
)
221 && (!pins
[currpos
] || ((pins
[currpos
]&DIAG
) &&
222 (bishmoves
[pins
[currpos
]&0x0f]==inc
||
223 bishmoves
[pins
[currpos
]&0x0f]==(uint8_t)-inc
))))
224 a
[num_atck
].piece
[a
[num_atck
].count
++] = PIECE_OF(d
[currpos
]);
229 if(a
[num_atck
].count
)
233 /* check rook (or queen) attacks */
234 killer
= ROOK
|attacker
;
236 for(int i
=3;i
>=0;i
--)
238 uint8_t inc
= rookmoves
[i
];
239 uint8_t currpos
= pos
+inc
;
240 a
[num_atck
].curr
= a
[num_atck
].count
= 0;
244 if(OUT_OF_BOARD(currpos
))
246 if( ((d
[currpos
] & ((uint8_t)~BISHOP
)) == killer
)
247 && (!pins
[currpos
] || ((pins
[currpos
]&COLM
) &&
248 (rookmoves
[pins
[currpos
]&0x0f]==inc
||
249 rookmoves
[pins
[currpos
]&0x0f]==(uint8_t)-inc
))))
250 a
[num_atck
].piece
[a
[num_atck
].count
++] = PIECE_OF(d
[currpos
]);
255 if(a
[num_atck
].count
)
258 #endif //TRACK_ATTACKS
263 static int vals
[] = { 0, 5, 3, 10, 3, 1, INF
};
266 Board::propagate_see(uint8_t victim
, int numa
, AttackList
* a
, int numd
, AttackList
* d
)
268 uint8_t newvict
= KING
;
271 for(int i
=0;i
<numa
;i
++)
272 if(a
[i
].curr
< a
[i
].count
)
274 if(idxnewvict
==-1 || vals
[a
[i
].piece
[a
[i
].curr
]] < vals
[newvict
])
277 newvict
= a
[i
].piece
[a
[i
].curr
];
284 a
[idxnewvict
].curr
++;
285 return MAX(0, vals
[victim
] - propagate_see(newvict
, numd
, d
, numa
, a
) );
288 /* calculate how much is winning the exchange sequence stating with Move */
290 Board::move_see_val(const Move
& m
)
297 uint8_t piece
= data
[m
.from
];
298 int bof
= vals
[PIECE_OF(data
[m
.to
])] - vals
[PIECE_OF(piece
)];
304 del_attacks(0, m
.from
);
305 #endif //TRACK_ATTACKS
306 atck_num
= list_attackers(m
.to
, color_to_move
, pins
, atck
);
307 def_num
= list_attackers(m
.to
, other_color
, oth_pins
, def
);
308 data
[m
.from
] = piece
;
310 add_attacks(0, m
.from
);
311 #endif //TRACK_ATTACKS
313 return vals
[PIECE_OF(m
.capture
)] -
314 propagate_see( PIECE_OF(data
[m
.from
]), def_num
, def
, atck_num
, atck
);