Musala Soft Logo Конкурс по програмиране на Musala Soft и PC Magazine Bulgaria PC Magazine Bulgaria Logo
  Състезателна система
Сезон 2010 - 2011
Сезон 2009 - 2010
Сезон 2008 - 2009
Сезон 2007 - 2008
Сезон 2006 - 2007
Сезон 2005 - 2006
Правила
Задача 1
Задача 2
Задача 3
Задача 4
Задача 5
Задача 6
Класиране
Финален кръг
Сезон 2004 - 2005
Сезон 2003 - 2004
Сезон 2002 - 2003
Сезон 2001 - 2002
Сезон 2000 - 2001

Коментари към 4та задача (v.1.1)

автор: Владимир Молотков

1. Оптимална стратегия.

1. Първото нещо, което веднага се забелязва е, че при този начин на оценяване на резултатите от турнира на програмите -- максимален брой точки вместо максимален брой спечелени партии -- е възможна ситуация, в която победител в турнира ще бъде една програма, която не е спечелила нито една игра! Нещо повече, програмата спечелила всички игри до една, може да се окаже на последно място! Ето един пример:
 
No 1 2 3 4 5 6 7 8 9 10
1 ---- 100 100 100 100 100 100 100 100 100
2 200 ---- 60 60 60 60 60 60 60 40
3 200 60 ---- 60 60 60 60 60 60 40
4 200 60 60 ---- 60 60 60 60 60 40
5 200 60 60 60 ---- 60 60 60 60 40
6 200 60 60 60 60 ---- 60 60 60 40
7 200 60 60 60 60 60 ---- 60 60 40
8 200 60 60 60 60 60 60 ---- 60 40
9 200 60 60 60 60 60 60 60 ---- 40
10 200 50 50 50 50 50 50 50 50 ----

В тази таблица клетката от i-тия ред и j-тия стълб съдържа резултат от играта на програмата с номер i срещу програмата с номер j. Броят на играещи програми е 10. За простота се предполага, че всяка една от програмите играе срещу всяка друга само една игра, а не 8, както бе в реалния турнир. Вижда се, че програмата номер 1 губи във всичките 9 игри, обаче печели турнира, набирайки 900 точки общо. От друга страна, програмата номер 10 печели максимален възможен брой игри -- 9, обаче със сумарния брой точки -- 600 -- заема последното място, тъй като програми с номер от 2 до 9 набират по 660 точки. 

Този парадоксален пример показва, че стандартните алгоритми за търсене на най-добрия ход, разработени за т.н. "игри с нулева сумарна печалба" (към които се отнасят всички игри на карти, а също така и шах) не са най-добрите в нашия случай.
Ще поясня това с един пример. Да предположим, че при пресмятането на 2 хода напред (популярен израз за това, което един програмист би нарекъл търсене на дълбочина 2 в графа на играта) ход 1 ни гарантира 10 точки, едновременно давайки на противника възможност да спечели 50 точки. Нека ход 2 дава 0 точки на нас и 0 точки на противника. Кой ход от тези 2та е по-добър за нас?

Ако турнира би бил оценяван по стандартния начин -- съотношение на броя победи и загуби, то отговора би бил очевиден: по-добър е този ход, който гарантира максимална разлика между броя на нашите точки и тези на противника. В нашия пример тази разлика е -40 за ход 1 и 0 за ход 2, т.е. ход 2 би бил по-добър. Разбира се, търсенето на дълбочина по-голяма от 2 би могло да промени това съотношение, ние говорим тук за оценката на ходове при фиксирана дълбочина на търсене -- 2 в нашия пример. Интуитивно е ясно, че тази стратегия (ще я наречем прецакваща), давайки повече шансове за спечелване на една игра, евентуално намалява броя на спечелените точки не само на противника, но и на нас също.
Затова аз заложих на друга стратегия (ще я нарека кооперативна), където приоритета е максимализиране на собствени точки, дори и с цената на по-голямо евентуално увеличаване на точките на противника. От гледна точка на тази стратегия в горния пример ход 1 е по-добър.

Всъщност, първоначално аз мислех, че може би най-добрата възможна стратегия би била адаптивна: да се прилага стратегия обратна на тази на противника, т.е. ако противника прилага прецакваща стратегия, ние да прилагаме кооперативна и обратно.
От реализацията на тази стратегия аз се отказах първо от практически съображения: за кодиране и задължителната в такива случаи дезинсекция (която може да отнеме двойно повече време от самото кодиране) просто нямаше достатъчно време. Ама и за самата теза, че адаптивната стратегия е по-добра от кооперативна, освен нейната интуитивна привлекателност, аз не намерих сериозни теоретични аргументи. Освен това възниква въпрос: каква стратегия трябва да се прилага срещу един противник, който също използва адаптивна стратегия? Въпроса е чисто теоретичен -- аз прецених, че вероятността на това, че някой от състезателите ще реализира адаптивна стратегия (и то без бъгове :) в рамките на даденото време е много малка.

Както и да е, анализ на предишните ходове на противника с цел да моделира стратегията на противника би могъл да подобри силата на една игрова програма. Доколкото аз знам, нито в една програма за игра в шах (поне тези с отворен сорс код, най-силната от които е Crafty на Robert Hyatt) подобен анализ не е реализиран. В нашия случай обаче има една ситуация, когато ходовете на противника могат лесно да се предскажат с вероятност близка до 1. Това е
момента, когато прогрмата на противника става тъй да се каже "зомбирана" от сървъра заради цайтнот или някакъв бъг (да речем, човек вътрешно работи с ходове с номера от 0 до 14 и е забравил да ги "преведе" на езика на сървъра, който зомбира програмата веднага след ход 0, който все някога трябва да се случи :). Факта на зомбиране ние не можем да установим веднага, обаче след като ход 6 се среща 5-6 пъти подред, вероятността на това че противника е зомбиран става почти 1.
Практически това значи, че при игра с зомби нашата программа може да удвои дълбочината на търсенето (тъй като в този случай от всяка "четна" позиция в графа на играта излиза само един ход вместо 15 -- ход 6), което на практика може да доведе и до удвояване на спечелените точки. При тренировъчни игри с dummy-player аз изкарвах понякога по 1400 точки!

2. "Двуетажната" иерархична оценка на ходове (избиране на ход максимализиращ нашите точки, а при равенство -- минимизиращ точките на противника) е прекалено груба. Ние трябва да се погрижим и за създаване на позиции, в които вероятността на "комбинации" (едноцветни хоризонтални или вертикални поредици с дължина не по-малка от 3) при следващи ходове е максимална. Броя на възможните комбинации по време на цялата игра е ограничен: при игра от 200 хода може да възникне не повече от (200+25)/3=75. Интуитивно е очевидно (теоретично доказателство аз нямам), че колкото повече цветни клетки присътстват на дъската, толкова по-голяма е вероятността на възникване на поне една комбинация при поредното "вмъкване". Практически извод от това наблюдение: при равни други условия по-добри са тези вмъквания, при които от дъската нищо не изпада. Т.е., хоризонтално вмъкване е по-добре да се прави в онзи ред, които има празни клетки. Аналогично, вертикално вмъкване е по-добре да се прави в един стълбец не запълнен до горе. Така възниква следната "триетажна" оценка:

1) между двата хода избираме този, който гарантира максимум на нашите точки (след depth хода, където depth е дълбочината на търсенето);
2) при равенство на нашите точки избираме този, който гарантира повече цветни клетки останали на дъската (след depth хода);
3) при равенство избираме този, който дава минимум на максимум на точките на противника  (след depth хода).

За елегантно боравене с иерархична оценка от този вид най-добре подхожда следната структура (в C++):

struct EVAL{int MyPoints, DeletedCells, OpponentPoints;};

със
operator>(...) дефиниран в съответствие с правилата 1)--3) горе.

За този вариант на оценка аз се сетих чак на следващия ден след като изпратих програмата.
На практика беше реализиран теоретически малко по-лош вариант използващ структура

struct EVAL{int Points, DeletedCells;};

със съответно дефинирани operator>(...) и operator==(...)
. За оценка на ходове се използваха 2 екземпляра на тази структура -- MyEVAL и OpponentEVAL -- като оценката на ходовете протичаше по следната схема:

1) между двата хода избираме този, който има по-голям MyEVAL (след depth хода, където depth е дълбочината на търсенето);
2) при равенство на MyEVAL избираме този, който  дава по-малък OpponentEVAL (след depth хода);

 в резултат на което оценката ставаше "4-етажна" (2х2=4). Този вариант е по-лош, тъй като няма никаква разумна причина да минимизира  разделно клетките премахнати от мен и тези премахнати от опонента, вместо да се минимизира тяхната сума. П
ри това "4-ти етаж" на оценката имаше един бъг (максимизиране на клетките премахнати след ходовете на противника, вместо тяхното минимизиране), произлизащ от това, че аз използвах operator>(...) с обърнати аргументи в качеството на "по-малък" в 2), вместо да дефинирам коректния operator<(...).
Този леко бъгясал вариант беше реализиран в функцията Eval3XX(...) в моя сорс файл Insert.h.
Експерименти с обезпаразитен Eval3XX(...) показаха обаче, че този бъг в 4-ти етаж се проявава много рядко: в 30 случайни игри с 200 хода той не се е проявил нито веднъж :))) -- всички 3000 хода избрани от поправения вариант на Eval3XX(...) съвпаднаха с тези избрани от бъгясала конкурсна версия! Този факт аз си обяснявам с това, че има много силна корелация между броя спечелени точки и броя на премахнати от дъската клетки, т.е. тези две величини са силно зависими.

Има и още един по-съществен бъг в тази функция (който аз открих чак преди 2 дена): тя извиква рекурсивно не себе си, а един по-стар вариант, EvalX(...), за който аз смятах, че минимаксна процедура реализирана в него съдържа грешки (и тя наистина ги съдържа). По-новите варианти на процедури се получават, естественно, през клониране на старите варианти, след което в тях се правят съответните промени. В дадения случай аз пропуснах да променя в новата функция рекурсивно извикване на старата. След като аз все пак забелязах този бъг и го оправих, получи се следния парадоксален резултат: "безбъгова" версия набира съществено по-малко точки в игрите, отколкото бъгясалата! Т. е., първото място на моята програма може би се дължи на това, че аз не бях забелязал този бъг навреме :)!
Причината на този парадокс е, разбира се в това, че новата версия съдържа по-тънък бъг от старата, обаче с по-тежки последици. Коректния вариант на минимакса -- Eval4XX(...) -- аз успях да напиша едва днес -- 12 март. Е, може би и той е бъгясал :), обаче бие всички предишни версии по резултати.

2. Търсенето.

1. Ще напомним, че търсенето на оптимален за дълбочина depth ход в графа на играта състои в оценка на всяка позиция, отстояща от текущата на разстояние не по-голямо от depth, и избиране на хода в съответствие с някакъв вариант на минимаксна процедура (грубо казано, избиране на ход гарантиращ най-голяма оценка за нас и при най-силните ходове на противника). Ще напомним също, че графа на една игра е един ориентиран граф, чиито върхове са всички позиции, произлизащи от началната в резултат на някоя поредица от ходове, а ребрата излизащи от една позиция са всички ходове възможни в дадена позиция. В нашия случай във всяка една позиция са възможни 15 хода, тъй че при търсенето на дълбочина depth трябва да бъдат оценени 15+...+15depth позиции. Т.е., времето необходимо за оценка на дълбочина depth+1 е примерно 15 пъти по-голямо от това за дълбочината depth.

Съществуват 2 стандартни метода на намаляване на времето на търсенето.

2. Hash таблици. Единия от тях -- използване на hash (aka transposition) таблици -- се основава на това, че често пъти една и съща позиция възниква като резултат на две различни поредици от ходове (с други думи, графа на играта не е дърво). В такава ситуация има смисъл да се запазят всичките позиции, възникващи след първите няколко хода (до няква дълбочина depth1<depth), заедно с техните оценки при дълбочина depth, в една hash таблица. При оценката на някоя позиция с дълбочина не по-голяма от depth1 преди да "се гмурне" до дълбочината depth се гледа, дали тази позиция (заедно с нейната оценка на дълбочина depth) не присътства вече в hash таблицата. Ако я има -- няма нужда от дълбоко гмуркане, а чисто и просто взимаме оценката от таблицата. Това може да намали значително времето на търсене на дадена дълбочина и, като резултат, да даде възможност да се търси оптималния ход в рамките на дадения таймаут на по-голяма дълбочина.

Например, в нашия случай е очевидно, че ако първия стълбец на дадена позиция е празен, то позициите, възникващи след ходове от 1 до 6 съвпадат. Аналогична е ситуацията в случай на празния последен стълбец и ходовете от 10 до 15. Ако и двата стълбеца са празни, то е достатъчно вместо 15 хода да се анализират само 5. Вижда се, че в случая на depth1==1 няма нужда от никакви hash таблици, а трябва само да се провери, дали в първия или последен стълбец някои от горните клетки не са празни. Ако има празни клетки, то можем да изключим анализирането на някои от "хоризонтални"  ходове, заменяйки тях с ходове 6 или 10.
Нещо повече, такъв тип псевдохеширане може да бъде приложен към всяка една позиция на оценявания подграф на играта, а не само към позициите които са на един ход разстояние от началната. Такова редуциране на графа на играта се получава само с добавяне на 2 реда във гореспоменатата функция Eval3XX(...). Аз прецених, че ефекта от този прост трик ще е по-голям от евентуалното построяване на hash таблицата, защото в резултат на един ход позицията на дъската като правило се променя драстично, тъй че вероятността на това, че една и съща позиция ще възникне в резултат на две различни поредици от ходове е малка. Освен тези очевидни частни случаи, които току що бяха разгледани и се третират без никакви hash таблици. Трябва да се отбележи също така, че дори ако две различни редици от ходове довеждат до една и съща позиция на дъската, оценките за самите тези поредици от ходове могат да бъдат напълно различни -- в тази игра точките се извличат от ходове, а не от самите позиции. Затова аз и не съм опитвал да реализирам hash таблици от класически тип.

3. Alpha-Beta. Втория класически начин за намаляване на минимаксното търсене -- обрязване (pruning или cut-off) на графа на търсене. Той се основава на това, че често пъти е възможно да се прецени a priori, че един подграф излизащ от някоя междинна позиция X няма нужда да бъде изследван докрай, тъй като неговата частична оценка получена до момента е по-малка (ако в X опонента е на ход) или по-голяма (ако в позиция X сме на ход ние и X не е начална позиция) от текущата най-добрата за нас оценка. Конкретни реализации на това просто наблюдение във вид на рекурсивни алгоритми имат различни форми. Първия от тези алгоритми -- alpha-beta търсене -- бе публикуван от А.Брудно в 1963 г. Една негова по-проста модификация бе предложена от D.Knuth и R.Moore в 1975г. под името Negamax. Едно просто описание на alpha-beta (и на минимакс) във вид на псевдокод може да се намери на стр.6 от популярната обзорна статия на J.Schaeffer: "The Games computers (and people) play", която може да бъде намерена в интернет (за съжаление нямам под ръка линка към сайта, от който я изтеглих). Според тази статия използване на alpha-beta вместо минимакс без обрязване може, в най-добрия случай, да удвои (в рамките на фиксирани времеви ограничения) дълбочината на търсенето.
Какво значи "в най-добрия случай"? Броя на позициите в "обрязания" граф силно зависи от подредбата на ходове във всяка една позиция на "необрязания" такъв. Най-добрия случай, т.е. най-малък обрязан граф, се получава тогава, когато ходовете за всяка позиция са подредени така, че най-добрия ход е и най-първия. Разбира се, ако такава подредба би била известна само за една от позициите -- началната -- ние изобшо нямахме да имаме нужда от никакъв минимакс! Затова се използват различни трикове с оглед да се получи подредбата на ходове поне за позиции с малка дълбочина, в които подредби вероятността на това, че един от първите ходове е най-добър е голяма. Един от тези трикове е т.н. итеративно "задълбочаване" (iterative deepening), при който преди да се провежда търсенето при дълбочината depth се провежда търсенето при дълбочините по-малки от depth, като при търсенето с дълбочина depth в начална позиция се исползва подредбата получена при търсенето с дълбочина depth-1. Лошото при този метод е, че горе долу хубавата подредба се получава само за началната позиция, не и за останалите. Тъй че този метод позволява не удвояване на дълбочината на търсенето, а само увеличаване на тази дълбочина на доста по-скромна величина от порядъка на 1-2. На мен ми се струва, че следния метод би дал по-добри резултати: във всяка една от вътрешните позиции провеждаме търсенето с дълбочина 1, като при същинския рекурсивен поиск ще исползваме грубата наредба, получена от това бързо търсене. На първите места при такава наредба ще излязат т.н. "активни" ходове. В шаха това са вземания, шахове и т.д., а в случай на нашата игра -- ходове, произвеждащи комбинации, т.е. носещи ненулеви точки.

Стига с общата теория, да се върнем към нашата конкретна игра. Лошото е, че ние не можем да приложим alpha-beta алгоритъм към нашия случай буквално. Причината не е в това, че тук се използва 3- или 4-етажна оценка вместо проста 1-етажна оценка във вид на число. Ние винаги можем да сведем многоетажната оценка към едно число като вземем сума от различните елементи със някакви тегла. Да речем вместо 3-етажния EVAL горе можем да исползваме 1000*MyPoints+DeletedCells+0.001*OpponentPoints с обикновени оператори >, <, == за числа.
Дълбоката причина на усложняването на кода на alpha-beta алгоритм е в това, че когато се използва кооперативна стратегия вместо прецакваща, играта излиза от класа игри с нулева сума, което с по-прости думи значи, че максималната оценка за нас не съвпада с минималната оценка за противника. Това е причината за това,че в модификацията пригодена за кооперативна стратегия, на обикновения рекурсивен минимакс без обрязване (функцията Eval3XX(...)), аз бях принуден да исползвам двоен цикъл (пробягващ всички поредици от 2 последователни хода) вместо одинарния преди рекурсивно извикване на Eval3XX(...). Да намеря и адекватната модификация на alpha-beta алгоритм за случай на кооперативната стратегия аз не се и опитах по време на конкурса -- просто нямах време за това.
Е, вчера се понапънах малко :) и, освен че поправих бъговете в минимакса, заменяйки бъгова Eval3XX() на безбъгова (до доказване на противното :) функция Eval4XX(), реализирах и половината от обрязвания на класически alpha-beta. По-конкретно, тези обрязвания, които възникват в позициите, в които е хода на опонента. Съществено е да се отбележи, че Eval4XX() не зависи от никакви аргументи alpha и beta. Тя се получава от обезпаразитена версия на минимакс без обрязване със добавяне на 2 реда само. Аз не съм използвал в нея никакви специални подредби на ходове, при което все пак се обрязват приблизително 1/2 от позициите в графа на търсенето. С други думи, времето на търсене при дълбочината depth се намалява двойно.

Каква е ситуацията с другата половина от обрязванията? Медитирайки над картинката от стр.4 на горецитирания Schaeffer, илюстрираща един конкретен пример на минимаксното търсене, аз съобразих, че за да се отреже и другата половинка, функцията Eval4XX() трябва все пак да се сдобие с още един аргумент (по-точно 2: аналог на beta от класически случай -- тук той се разцепва на beta и betaOp заради 4-етажност на оценката) и в нея трябва да се добавят още няколко реда. Това аз не съм го направил още. Сорса с полуобрязания минимакс може да се изтегли тук.
А който се интересува от напълно обрязана версия трябва да я обреже самостоятелно, като едно лесно упражнение :). Или да почака, докато по-новата версия се появи на моя сайт. На този линк аз ще слагам всички обновления, като смятам евентуално да заменя 4-етажна версия на минимакс с по-прецизна и, надявам се, по-елегантна, 3-етажна версия, а също така да изпробвам и различни начини на ускоряване на alpha-beta. Ама кога ще стане всичко това и ще стане ли изобшо -- не мога да кажа, тъй като имам и други работи да върша освен да се забавлявам с тази играчка :).

3. Дълбочината на търсене и таймаут.

На моя компютър с Athlon64 3200+ (2.0Ghz) намиране на 100 хода при дълбочината на търсенето depth=5 отнема от 7 до 14 секунди. Говоря тук за конкурсния вариант, а така също и за неговата поправена версия без обрязване. Т.е. ако тестовете наистина протичаха на ветеранския "AMD Athlon на 1.2 GHz", както се пише в Правилата на конкурса, то и тогава е било възможно в повечето случаи да търси ходове при тази дълбочина през цялата игра..
От друга страна, търсенето на дълбочина 6 отнема вече доста над 100 секунди. Тъй че аз прецених, че без да е реализирано alpha-beta търсенето, и то с доста добра подредба на ходове, едно таково търсене, макар и частично (търсенето на дълбочина 6 да речем измежду 2-3 най-добри при дълбочина 5 хода) няма никакъв смисъл. Така, че аз се ограничих със дълбочина 5.
За случая когато все пак прогрмата ще изпадне в цайтнот, аз предвидих просто  превключване към търсенето на дълбочина 4, ако търсенето ще отнеме повече от 17 секунди (при игра с 200 хода).

4. Влиянието на wildcards.

Очевидно е, че ако параметър К, описващ скритите картинки не е по-малък от дълбочината на търсенето (при мен -- 5 за незомбирани програми и 10 за зомбирани), то той не оказва никакво влияние на процедурата на търсене, тъй че може чисто и просто да бъде игнориран.
В противен случай има два начина за борба с него: прост и сложен. Простия начин състои в ограничаване на дълбочината на търсенето до К. Сложния --  в усложняване на процедура на търсенето, с пресмятанията на математически очаквания на средни, минимални и т.д. точки в зоната на "диви картинки". Т.е. голяма загуба на време за кодиране + почти 100% гаранция за поява на трудно откриваеми бъгове. Тъй че аз благоразумно избрах простия начин. Още повече след като видях в тренировъчни игри, че и сървера е достатъчно благоразумен и държи този параметър далеч отвъд интервала [1,...,10].

5. Реализация на позициите.

Тъй като за кодиране на цвета на една картинка са нужни не повече от 3 бита, то целия един ред от дъската може да се кодира със два байта (short или int16). Т.е. е достатъчен масив от 5 2-байтови числа за изобразяването на цялата дъска. При това С++ позволява да се определи по елегантен начин едно 2-байтово число като един масив от 5 3-битови числа, достъпа до елементите на който става с доста хитро дефиниран operator [] (този трик аз взаимствах от дефиницията на класа bitset от STL). Предимства на такова компактно представяне: по-малко време на клониране на позиция, а също така представянето на операция на хоризонталното вмъкване в един пълен ред като много бърза операция на ляво или дясно отместване (<< или >>). При търсенето на най-добрия ход тези операции се правят многократно. Най-голяма файда от такъв тип компактификация на позициите имат игри в които се поддържат големи hash таблици. Например шах, само че в шаха за кодиране на съдържанието на една клетка от дъската са нужни 4 бита, а не 3. В случай на нашата игра файда няма: търсенето с "компактна" дъска се е оказало със 1 до 2% по-бавно, отколкото с дъската, реализирана с най-обикновен масив от 5х5 байта. Въпреки това аз избрах компактната реализация, тъй като в некомпактната възниква един странен бъг по-време на търсенето на дълбочина 6, причини за който аз нямах време  да търся. 
Също така се оказа полезно да се включи в дефиницията на class Board (представящ позициите) още един масив, съдържащ броя на празните клетки във всеки един стълбец. Поддържането на тази  допълнителна структура намалява доста времето на търсенето в позиции с полупразна дъска, намалявайки дължината на вътрешни цикли във функцията MakeMove() -- най-често извикваната функция в процедурата на търсене.

6. Какво ново има?

Засега (14 март) -- нищо.

16 март.
1. Версията Eval4XX
правеше всъщност само 1/4 от обрязванията заради това, че на едно място в сорса се използваше
operator< вместо operator<=. След поправката Eval4XX с обрязване стана 4 пъти по-бърза от такава без обрязване.
2. Най-накрая написах процедураta на търсене с 3-етажна оценка: функция Eval5(...). Както чистия минимакс, така и неговата
alpha-beta версия. Както и се очакваше, кода стана по-елегантен: той реализира псевдокода на "класическия" alpha-beta.
Eval5() бие по резултати всички предишни версии. Обаче има някакъв тънък бъг, причините на който аз още не успях да открия.
Работата е там, че alpha-beta версия на Eval5() не е функционално еквивалентна на Eval5() без обрязване. С други думи, тя
изглежда обрязва повече подграфове от графа на играта, отколкото е позволено. И въпреки това тя дава малко по-добри резултати,
отколкото версия без обрязване, което е странно. При това тича 6 пъти по-бързо.

19 март.
Написах 3-етажна версия -- Eval5X() -- която като че ли няма вече бъгове, тъй като всички резултати на alpha-beta вариант съвпадат с тези на чистия минимакс без обрязване. Eval5X() има един аргумент повече, отколкото класическия alpha-beta. Този аргумент се е оказал необходим заради следната причина: в тази игра оценката на някоя позиция X зависи не толкова от позицията X, колкото от ходове водещи к нея. Затова трябва да има един аргумент eval0 от типа EVAL, съдържащ оценката на поредица от ходове, водещи к X. Тази оценка е адитивна функция на поредицата от ходове: оценката за поредицата е равна на сума от оценките на всеки един ход от поредицата.
Alpha-beta вариант на тази нова версия е около 25 пъти (!!!) по-бърз от вариант без обрязване: за една игра от 200 хода се харчи
средно по-малко от 0.4 секунди при търсенето на дълбочина 5. При това без никаква специална предварителна подредба на ходове! Това значи, че в рамките на таймаут от конкурса дълбочината на поиска би могла да бъде 6 вместо 5. Освен това, тази последна версия бие всички предишни версии по средните резултати, понякога съществено, давайки до 5--10% процента точки повече. При това точките на противника се намаляват средно със същия процент, въпреки че при 3-етажната оценка този фактор е с най-малката значимост. Това се обяснява вероятно с това, че ресурса "точки" е ограничен, както бе отбелязано горе.
 

Ако  ще се появи нещо ново, обновената версия на тези коментари ще бъде качена тук.

За въпроси можете да ни пишете на адрес: konkurs@musala.com.

Supported by Musala Soft Ltd.

Copyright 2000-2010 by Musala Soft Ltd. All rights reserved.