gambit
Silnik szachowy w Scali 3. Generowanie ruchów, ocena pozycji i przeszukiwanie - kompletny mózg do gry w szachy, budowany scala-cli.
Silnik szachowy w Scali 3. Trzy trudne rzeczy naraz: bezbłędne generowanie ruchów, sensowna ocena pozycji i przeszukiwanie, które w rozsądnym czasie wybierze dobry ruch. Kompletny mózg do gry.
Wprowadzenie
Silnik szachowy tylko z pozoru jest jednym projektem. To trzy podsystemy, z których każdy może zepsuć całość na własny sposób, i dopiero razem dają coś, co gra sensownie. gambit jest o tym, żeby te trzy części zgadzały się ze sobą na tyle dobrze, że wynik zaczyna przypominać grającego przeciwnika, a nie generator losowych ruchów.
Scala 3 daje tu wyrazisty język do modelowania planszy, ruchów i drzewa wariantów. Ale prawdziwe wyzwanie nie jest składniowe, tylko algorytmiczne: bezbłędny generator, uczciwa ocena i przeszukiwanie, które nie liczy w nieskończoność.
Trzy problemy, które muszą się zgadzać
Generator ruchów, który raz na milion pozycji przepuści nielegalny ruch, sprawi, że silnik zagra coś niemożliwego. Ocena, która źle waży figury, poprowadzi go w przegraną z przekonaniem. Przeszukiwanie bez odcięć będzie myśleć godzinami nad ruchem, który ma paść w sekundę.
wszystkie legalne ruchy w każdej pozycji, łącznie z roszadą, biciem w przelocie i promocją.
liczba obrazująca, kto stoi lepiej, gdy partia jeszcze trwa.
alfa-beta, które odrzuca gałęzie, których nie opłaca się liczyć.
Żadnego z tych trzech nie da się zbyć. Słaby w którymkolwiek z nich silnik przegra, i to z konkretnego, dającego się wskazać powodu, a nie z ogólnej słabości.
Alfa-beta, czyli sztuka nieliczenia
Naiwne przeszukiwanie sprawdza każdą możliwą kontynuację, a tych są miliardy już na kilka ruchów w głąb. Odcięcie alfa-beta zauważa, że jeśli jedna odpowiedź przeciwnika już obala wariant, reszty jego odpowiedzi nie trzeba liczyć. Przy dobrym porządku ruchów tnie to przestrzeń tak mocno, że silnik sięga głębiej w tym samym czasie.
Węzły do przeszukania na tej samej głębokości (orientacyjnie, tys.)
To nie jest drobna optymalizacja, tylko różnica między silnikiem, który widzi trzy ruchy do przodu, a takim, który widzi sześć. W szachach ta głębia przekłada się wprost na siłę gry.
Perft, czyli dowód poprawności generatora
Poprawność generatora ruchów weryfikuje się tak zwanym perft: liczysz wszystkie pozycje osiągalne na zadaną głębokość i porównujesz z liczbami, które cała społeczność szachowa zna na pamięć. Jeśli twoja liczba się nie zgadza, masz gdzieś buga, i to dokładnie widać, na której głębokości rozjazd się zaczyna.
Perft z pozycji startowej
| Głębokość | Liczba pozycji |
|---|---|
| 1 | 20 |
| 2 | 400 |
| 3 | 8902 |
| 4 | 197281 |
| 5 | 4865609 |
Efektem jest kompletny silnik, który bierze pozycję i oddaje ruch: generator wystawia wszystkie legalne kontynuacje, ocena mówi, która prowadzi w lepszą stronę, a alfa-beta przeszukuje na tyle głęboko, na ile pozwala czas. Trzy podsystemy, które z osobna są tylko częściami, razem dają przeciwnika, który potrafi zagrać.
Perft jest wzorcowym przykładem testu, który naprawdę może paść. Nie sprawdza, że coś działa, tylko porównuje twoją liczbę z liczbą znaną z góry, więc każdy błąd w generatorze natychmiast rozjeżdża wynik.
Więcej projektów
Inne realizacje z tej samej kategorii - zobacz, jak podchodzimy do podobnych wyzwań.
Masz podobny projekt?
Napisz do nas - wycena jest bezpłatna i wraca w godzinę.



