간단히 말하면, 마법의 비트 보드는 위치를 차지하고 슬라이딩 조각에 대한 법적 이동을 얻는 효율적인 방법입니다.
먼저 마법 번호를 찾아야합니다. 에 쓰는 코드 중 일부는 마법 번호를 사용하면 마법 번호가 다시 사용됩니다.
시작하려면 5 가지 기능을 작성해야합니다. 특히 매직 넘버를 찾을 때만 사용할 수 있고 매직 넘버를 사용하기 전에 프로그램 시작시 한 번 사용하기 때문에 특히 빠를 필요는 없습니다. 이러한 함수에서 이전 기술을 사용할 수 있습니다.
uint64_t blockermask_rook (int square);
uint64_t blockermask_bishop (int square);
uint64_t moveboard_rook (int square, uint64_t blockerboard);
uint64_t moveboard_bishop (int square, uint64_t blockerboard);
uint64_t blockerboard (int index, uint64_t blockermask);
그래서 차단기 마스크, 이동 보드 및 차단기 보드입니까? 음, 난 그냥 조건을 만들었지 만, 여기에 내가 그들에 의해 의미있는 작업은 다음과 같습니다
/* Example, Rook on e4:
*
* The blocker mask A blocker board The move board
* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0
* 0 1 1 1 0 1 1 0 0 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1
* 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
* 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
*/
블록 커 마스크 및는 더 이상 이동 당신의 조각을 차단 점유 할 수있는 사각형의 모든 것입니다. 가장자리 사각형은 그 부분 일 필요가 없습니다. 왜냐하면 여러분의 조각은 그 사각형을 지나서 더 이상 움직일 수 없기 때문입니다. 이 비트 보드에있는 1의 수는이 조각에 필요한 룩업 테이블의 크기가 & 인 정사각형 조합을 결정합니다. 이 경우 10 개가 있으므로 e4 루크를 차단할 수있는 조각의 2^10 (1024) 개의 가능한 순열이 있습니다.
차단기 보드는 이러한 순열 중 하나입니다. 이 예에서는 b4, c4, e2, e5 및 e7에 조각이 있습니다. 이들은 적 과 친화적 인 조각입니다. 차단기 보드는 항상 차단기 마스크의 하위 집합입니다 (다른 사각형에 조각을 표시 할 필요가 없습니다 (예 : blockers = occupancy & blockermask;
)).
이동 보드는 주어진 차단기 보드에 대해 사용 가능한 이동 결과입니다. 여기에는 조각에 가능한 캡처가 포함됩니다. 자신의 조각을 캡처하는 것도 포함됩니다 (단, 자신의 조각 위치를 NOT으로 제거하면됩니다).
기본적으로 루크와 비숍 모두를 위해 모든 사각형에 차단제 마스크를 생성해야합니다. 그리고 루크와 비숍 모두를 위해 각 광장에 가능한 차단기 보드를 모두 만들어야합니다. 블로커 보드를 생성 할 때 결과 이동 보드도 생성해야합니다. 나중에 사용하기 위해 모든 것을이 배열에 저장하십시오.
이제 각 사각형/조각 콤보에 대해 임의의 64 비트 숫자를 시도하고 마술인지 확인하십시오. magic formula 인 return ((blockerboard*magic) >> (64-bits));
을 사용하여 마술인지 알 수 있습니다.이 마술은 0..2 비트 (e4 루크의 경우 0..1024)의 마법 인덱스를 만듭니다. 특정 조각/정사각형의 경우, 두 개의 차단기 보드가 동일한 마법 색인 을 생성하지만 인 경우 두 개의 차단기 보드는 서로 다른 이동 보드를 가지고 있으며, 이는 머글 (muggle) 번호이므로 새로운 것을 시도해야합니다.
당신이 그것을 얻으면, 64 마법의 주검 번호와 64 마법 주교 번호를 갖게됩니다. 이들을 사용하려면 프로그램 시작시 모든 차단기 마스크, 차단기 보드 및 이동 보드를 초기화하십시오. 그리고 이제 귀하의 프로그램은 효율적으로 모든 사각형 (따라서 여왕)의 주교와 루크를위한 이동 보드를 검색 할 수 있습니다. 그 코드는 다음과 같습니다.
/* Retrieves the move board for the given square and occupancy board. */
uint64_t magic_move_rook (int8_t square, uint64_t occupancy)
{
/* Remove occupants that aren't in the blocker mask for this square. */
occupancy &= Rook.blockmask[square];
/* Calculate the magic move index. */
int index = (occupancy*Rook.magic[square]) >> (64-Rook.bits[square]);
/* Return the pre-calculated move board. */
return Rook.moveboard[square][index];
}
대단히 Zong Zheng Li 님, 제 질문에 답해 주셔서 감사합니다. 지금은 간단한 접근법 (http://chessprogramming.wikispaces.com/Classical+Approach)을 사용하고 있지만 검색 및 평가를 포함하여 전반적인 과정에서 머리를 맞대고 마술 게시판으로 돌아갈 것입니다. – bytefire
@bytefire 예, 내 엔진에서는 고전적인 접근 방식을 사용하기 때문에 임시 구성 요소로 구현하기가 쉽습니다. magic generation으로 바꾸는 것에서 얻은 이득은별로 중요하지 않다는 것을 충분히 빨리 깨달았습니다. ('perft (6)'). – Zong
그건 내가 현재 구현하고있는 것에 의미를 더하기 때문에 매우 도움이된다. 옆 걸음에, 나가 더 방책을 명중하는 때, 나는 "chess"꼬리표를 가진 그래서에 질문을 배치 할 것이다. 더 많은 지원을 기대하고 있습니다 :) – bytefire