diff --git a/report/img/ps1.jpg b/report/img/ps1.jpg new file mode 100644 index 0000000..0526478 Binary files /dev/null and b/report/img/ps1.jpg differ diff --git a/report/img/ps2.png b/report/img/ps2.png new file mode 100644 index 0000000..94c8a16 Binary files /dev/null and b/report/img/ps2.png differ diff --git a/report/img/ps3.png b/report/img/ps3.png new file mode 100644 index 0000000..9b7a56b Binary files /dev/null and b/report/img/ps3.png differ diff --git a/report/img/ps4.png b/report/img/ps4.png new file mode 100644 index 0000000..7d5d28c Binary files /dev/null and b/report/img/ps4.png differ diff --git a/report/report.aux b/report/report.aux index 7157207..5442762 100644 --- a/report/report.aux +++ b/report/report.aux @@ -36,8 +36,8 @@ \@writefile{toc}{\contentsline {subsection}{\numberline {2.8}更多功能}{7}{subsection.2.8}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.8.1}附加任务 1,2 实现}{7}{subsubsection.2.8.1}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {2.8.1}{\ignorespaces 对局重现}}{9}{figure.2.8.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.9}附加任务 5,6 实现}{9}{subsection.2.9}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.9.1}其他功能}{9}{subsubsection.2.9.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.8.2}附加任务 5,6 实现}{9}{subsubsection.2.8.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.8.3}其他功能}{9}{subsubsection.2.8.3}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {3}联机对战设计}{9}{section.3}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.1}通信协议}{9}{subsection.3.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.2}联机对战逻辑}{10}{subsection.3.2}\protected@file@percent } @@ -45,11 +45,16 @@ \@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.2}一方发起对局,另一方确认对局}{10}{subsubsection.3.2.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.3}完成对局并确认胜负}{10}{subsubsection.3.2.3}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {3.2.1}{\ignorespaces 联机对局界面演示}}{11}{figure.3.2.1}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {4}AI 算法设计}{11}{section.4}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {4}AI 算法设计}{12}{section.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Minimax 搜索和 Alpha-Beta 剪枝}{12}{subsection.4.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.2}估价函数}{13}{subsection.4.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}参数调整}{13}{subsection.4.3}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}SA 参数调整}{14}{subsection.4.3}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.4}AI 对战强度}{14}{subsection.4.4}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {4.4.1}{\ignorespaces 测试过程}}{14}{figure.4.4.1}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {4.4.1}{\ignorespaces 测试过程}}{15}{figure.4.4.1}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {5}感谢}{15}{section.5}\protected@file@percent } -\gdef \@abspage@last{17} +\@writefile{toc}{\contentsline {section}{\numberline {6}附录}{15}{section.6}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {6.1}{\ignorespaces 采用隔壁队伍的 MCTS 测试}}{16}{figure.6.1}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {6.2}{\ignorespaces 感谢 pusheen.com 提供的表情}}{16}{figure.6.2}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {6.3}{\ignorespaces 感谢助教提供的支持}}{17}{figure.6.3}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {6.4}{\ignorespaces 感谢赵培宇同学请吃的饭}}{17}{figure.6.4}\protected@file@percent } +\gdef \@abspage@last{19} diff --git a/report/report.log b/report/report.log index 8dc04f2..a84a301 100644 --- a/report/report.log +++ b/report/report.log @@ -1,4 +1,4 @@ -This is XeTeX, Version 3.141592653-2.6-0.999994 (TeX Live 2022) (preloaded format=xelatex 2023.1.16) 5 JUN 2023 19:51 +This is XeTeX, Version 3.141592653-2.6-0.999994 (TeX Live 2022) (preloaded format=xelatex 2023.2.22) 7 JUN 2023 21:59 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -991,23 +991,28 @@ File: img/teammate.png Graphic file (type bmp) File: img/pk.png Graphic file (type bmp) - [14] [15] (./report.aux) - -Package rerunfilecheck Warning: File `report.out' has changed. -(rerunfilecheck) Rerun to get outlines right -(rerunfilecheck) or use package `bookmark'. - -Package rerunfilecheck Info: Checksums for `report.out': -(rerunfilecheck) Before: 159A39B97E987257127AD834BE5B40C8;2763 -(rerunfilecheck) After: BDB544BA3688DE2207613BCB8DA1CECB;2900. + [14] +File: img/ps1.jpg Graphic file (type bmp) + + [15] +File: img/ps2.png Graphic file (type bmp) + + [16] +File: img/ps3.png Graphic file (type bmp) + +File: img/ps4.png Graphic file (type bmp) + + [17] (./report.aux) +Package rerunfilecheck Info: File `report.out' has not changed. +(rerunfilecheck) Checksum: F334206BAF5E672EF82DC84951036163;2988. ) Here is how much of TeX's memory you used: - 18620 strings out of 477146 - 381384 string characters out of 5829170 - 1041330 words of memory out of 5000000 - 38927 multiletter control sequences out of 15000+600000 + 18662 strings out of 476179 + 382501 string characters out of 5813072 + 1044560 words of memory out of 5000000 + 39020 multiletter control sequences out of 15000+600000 479889 words of font info for 118 fonts, out of 8000000 for 9000 - 622 hyphenation exceptions out of 8191 + 1348 hyphenation exceptions out of 8191 88i,15n,91p,315b,1188s stack positions out of 10000i,1000n,20000p,200000b,200000s -Output written on report.pdf (17 pages). +Output written on report.pdf (19 pages). diff --git a/report/report.out b/report/report.out index 6533ccb..835300f 100644 --- a/report/report.out +++ b/report/report.out @@ -11,8 +11,8 @@ \BOOKMARK [2][-]{subsection.2.7}{\376\377\117\341\140\157\172\227\123\343}{section.2}% 11 \BOOKMARK [2][-]{subsection.2.8}{\376\377\146\364\131\032\122\237\200\375}{section.2}% 12 \BOOKMARK [3][-]{subsubsection.2.8.1}{\376\377\226\104\122\240\116\373\122\241\000\040\0001\000,\0002\000\040\133\236\163\260}{subsection.2.8}% 13 -\BOOKMARK [2][-]{subsection.2.9}{\376\377\226\104\122\240\116\373\122\241\000\040\0005\000,\0006\000\040\133\236\163\260}{section.2}% 14 -\BOOKMARK [3][-]{subsubsection.2.9.1}{\376\377\121\166\116\326\122\237\200\375}{subsection.2.9}% 15 +\BOOKMARK [3][-]{subsubsection.2.8.2}{\376\377\226\104\122\240\116\373\122\241\000\040\0005\000,\0006\000\040\133\236\163\260}{subsection.2.8}% 14 +\BOOKMARK [3][-]{subsubsection.2.8.3}{\376\377\121\166\116\326\122\237\200\375}{subsection.2.8}% 15 \BOOKMARK [1][-]{section.3}{\376\377\200\124\147\072\133\371\142\030\213\276\213\241}{}% 16 \BOOKMARK [2][-]{subsection.3.1}{\376\377\220\032\117\341\123\117\213\256}{section.3}% 17 \BOOKMARK [2][-]{subsection.3.2}{\376\377\200\124\147\072\133\371\142\030\220\073\217\221}{section.3}% 18 @@ -22,6 +22,7 @@ \BOOKMARK [1][-]{section.4}{\376\377\000A\000I\000\040\173\227\154\325\213\276\213\241}{}% 22 \BOOKMARK [2][-]{subsection.4.1}{\376\377\000M\000i\000n\000i\000m\000a\000x\000\040\144\034\175\042\124\214\000\040\000A\000l\000p\000h\000a\000-\000B\000e\000t\000a\000\040\122\152\147\235}{section.4}% 23 \BOOKMARK [2][-]{subsection.4.2}{\376\377\117\060\116\367\121\375\145\160}{section.4}% 24 -\BOOKMARK [2][-]{subsection.4.3}{\376\377\123\302\145\160\214\003\145\164}{section.4}% 25 +\BOOKMARK [2][-]{subsection.4.3}{\376\377\000S\000A\000\040\123\302\145\160\214\003\145\164}{section.4}% 25 \BOOKMARK [2][-]{subsection.4.4}{\376\377\000A\000I\000\040\133\371\142\030\137\072\136\246}{section.4}% 26 \BOOKMARK [1][-]{section.5}{\376\377\141\037\214\042}{}% 27 +\BOOKMARK [1][-]{section.6}{\376\377\226\104\137\125}{}% 28 diff --git a/report/report.pdf b/report/report.pdf index 69b82ff..ad7e4ad 100644 Binary files a/report/report.pdf and b/report/report.pdf differ diff --git a/report/report.synctex.gz b/report/report.synctex.gz index e6a655d..7968ea3 100644 Binary files a/report/report.synctex.gz and b/report/report.synctex.gz differ diff --git a/report/report.tex b/report/report.tex index 2ef179f..7ab048e 100644 --- a/report/report.tex +++ b/report/report.tex @@ -314,7 +314,7 @@ \caption{对局重现} \end{figure} - \subsection{附加任务 5,6 实现} + \subsubsection{附加任务 5,6 实现} \textbf{AI 独立线程} @@ -391,8 +391,10 @@ \caption{联机对局界面演示} \end{figure} - 由于在判断落子成立时禁止了棋手自杀,因此对局结束的条件只有超时和认输两种。 - + 虽然我方在判断落子成立时禁止了自杀,但是对方仍然具有自杀的可能,因此对局结束的条件有自杀、超时和认输 $3$ 种。 + + 当一方自杀后,胜方发送 \verb|SUICIDE_OP|,负方在收到该信息后回复同样的 \verb|SUICIDE_OP|,表示确认以“一方自杀”为理由结束对局。此时联机对战结束,棋盘不能被操作。 + 当一方认输,即点击 Resign 按钮后,认输方发送 \verb|GIVEUP_OP|,胜方在收到该信息后回复 \verb|GIVEUP_END_OP| 表示请求以“一方认输”为理由结束对局。认输方收到 \verb|GIVEUP_END_OP| 回复同样的信息以确认。此时联机对战结束,棋盘不能被操作。 当一方超时,胜方的计时器会调用 \verb|GameWidget::playerTimeout_OL()| 槽函数,发送 \verb|TIMEOUT_END_OP| 表示请求以“一方超时”为理由结束对局,负方回复同样的信息以确认。此时联机对战结束,棋盘不能被操作。 @@ -402,10 +404,12 @@ \section{AI 算法设计} - 由于助教在 \verb|/guidance| 中建议不要卷 AI 的强度,所以本项目 AI 采用推荐的 Minimax 搜索算法。 + 由于助教在 \verb|/guidance| 中建议不要卷 AI 的强度,所以本项目 AI 采用推荐的 Minimax 搜索算法,为 SA + Minimax。 同时,对于用 MCTS 爆杀本项目 AI 的隔壁队伍表示强烈的谴责。 + 同时,对于很多队伍都用 MCTS 欺负老实人的行为表示发自内心的强烈的谴责。 + \subsection{Minimax 搜索和 Alpha-Beta 剪枝} Minimax 算法又叫极小化极大算法,是一种找出失败的最大可能性中的最小值的算法。 @@ -421,8 +425,8 @@ // minimax 搜索 double Bot::alphaBeta(double a, double b, int depth) { - time_t curTime = clock(); - if((curTime - searchStartTime) / (BOT_TIMEOUT * 1000) > 0.9) + qint64 curTime = QDateTime::currentMSecsSinceEpoch(); + if(curTime - searchStartTime > BOT_TIMEOUT * 900) return depth & 1 ? b : a; // 判断超时 if(depth == Max_Dep) return judgeBoard(); // 叶子节点返回估价 @@ -489,32 +493,35 @@ 一开始估价函数以 $e$ 为底数,而大量测试表明,趋近于 $\frac 12$ 而不是 $\frac 1e$ 会更为理想。 - \subsection{参数调整} + \subsection{SA 参数调整} 在 Alpha-Beta 剪枝的过程中,需要传入 $\alpha, \beta$ 的初值。对于理想的 AI 对局来说,$\alpha, \beta$ 都应该趋近于 $\frac 12$。 - 同样在大量的对局测试和 AI 自迭代优化后,笔者取 $\alpha = 0.39,\beta = 0.61$。 + 同样在大量的对局测试(尤其是和隔壁队伍的 MCTS)和 AI 四次自迭代优化后,笔者取 $\alpha = 0.31,\beta = 0.61$,这是一个反常识但是非常高效的参数,原因是因为我们的估价函数 $>0.5$ 不一定会赢,$<0.5$ 也不一定会输,甚至可能负相关\sout{,惊不惊喜意不意外}。 - 此外,笔者对于 Alpha-Beta 剪枝的操作空间做出了一定的优化。AI 对于每一次落子后的估价函数进行模拟退火,若估价函数小于 $\frac 12$,对 $\alpha, \beta$ 带来 $\varepsilon$ 的扰动,$\varepsilon$ 随次数增多而逐渐趋于 $0$。 + 此外,笔者对于 Alpha-Beta 剪枝的操作空间做出了一定的优化。AI 对于每一次落子后的估价函数进行模拟退火,若估价函数波动较大,有 $e^{-\varepsilon/\varepsilon_0}$ 的概率对 $\alpha, \beta$ 带来 $\varepsilon$ 的扰动,$\varepsilon$ 随操作次数增多而逐渐趋于 $0$。 - 实际测试表明,对于较弱的对手,没有必要进行扰动。代码实现如下: + 代码实现如下: \begin{lstlisting} /* --- bot.h --- */ -double eps = 0.03, alpha = 0.39, beta = 0.61; -const double delta = 0.93; +double eps = 0.03, alpha = 0.31, beta = 0.61; +const double delta = 0.97; -alphaBeta(alpha, beta, 0); // 得到最终落子 (finalx, finaly) -judge->PlaceAPiece(finalx, finaly); // 更新落子 -/* 若为联机模式,更新对局 */ double curRatio = judgeBoard(); -if(curRatio < 0.5) +if(curRatio < 0.45 && (rand() % 100 + 1) * 0.01 < exp(-eps / 0.03)) { // 对面太强了,退火一下 - alpha += (0.5 - alpha) * eps; + alpha -= (0.5 - alpha) * eps; beta -= (beta - 0.5) * eps; - eps *= delta; } +if(curRatio > 0.55 && (rand() % 100 + 1) * 0.01 < exp(-eps / 0.03)) +{ + // 对面太菜了,退火一下 + alpha += (0.5 - alpha) * eps; + beta += (beta - 0.5) * eps; +} +eps *= delta; // 降温 \end{lstlisting} \subsection{AI 对战强度} @@ -533,9 +540,11 @@ \caption{测试过程} \end{figure} - 同时由于 Minimax 搜索算法本身就不够优秀,所以与隔壁组的 MCTS 对战结果是打不过,合情合理。 + 同时由于 Minimax 搜索算法本身对搜索时间的利用就不够优秀(非常浪费),所以与隔壁组的 MCTS 对战胜率仅有 $15\%$,合情合理。 对于固定策略的 AI,对战结果可能与先后手相关性较强,该测试样本量较小,所以具体情况尚不明。理论上是因为固定策略会让估价函数有较大幅度的波动,对于调参造成了一定困难。 + + 参数仅对 Minimax 和 MCTS 有较强针对性,对于更多的贪心和随机算法对战结果未知。 \section{感谢} @@ -557,4 +566,57 @@ 感谢雀魂麻将牌谱的设计参考。 + \section{附录} + + 本项目仓库:\href{https://github.com/sheriyuo/Qt-NoGo/}{https://github.com/sheriyuo/Qt-NoGo/} + + 两个 MCTS 打出来的逆天棋局: + + \begin{figure}[!htb] + + \centering + \includegraphics[width=8cm]{img/ps1.jpg} + + \counterwithin{figure}{section} + \caption{采用隔壁队伍的 MCTS 测试} + \end{figure} + + 对参数的评价: + + \begin{figure}[!htb] + + \centering + \includegraphics[width=8cm]{img/ps2.png} + + \counterwithin{figure}{section} + \caption{感谢 pusheen.com 提供的表情} + \end{figure} + + \newpage + 未尝败绩的终结: + + \begin{figure}[!htb] + + \centering + \includegraphics[width=8cm]{img/ps3.png} + + \counterwithin{figure}{section} + \caption{感谢助教提供的支持} + \end{figure} + + 某一个修了一晚上才发现的 RE bug: + + 你直接复制一个 \verb|vector>| 不爆 \verb|heap| 谁爆啊.jpg + + 但是为什么与 \verb|judge| 耦合较低的存档功能会让棋盘主程序 RE 呢?我们不得而知。 + + \begin{figure}[!htb] + + \centering + \includegraphics[width=8cm]{img/ps4.png} + + \counterwithin{figure}{section} + \caption{感谢赵培宇同学请吃的饭} + \end{figure} + \end{document} \ No newline at end of file diff --git a/report/report.toc b/report/report.toc index bee6c0b..b1f871d 100644 --- a/report/report.toc +++ b/report/report.toc @@ -11,17 +11,18 @@ \contentsline {subsection}{\numberline {2.7}信息窗口}{7}{subsection.2.7}% \contentsline {subsection}{\numberline {2.8}更多功能}{7}{subsection.2.8}% \contentsline {subsubsection}{\numberline {2.8.1}附加任务 1,2 实现}{7}{subsubsection.2.8.1}% -\contentsline {subsection}{\numberline {2.9}附加任务 5,6 实现}{9}{subsection.2.9}% -\contentsline {subsubsection}{\numberline {2.9.1}其他功能}{9}{subsubsection.2.9.1}% +\contentsline {subsubsection}{\numberline {2.8.2}附加任务 5,6 实现}{9}{subsubsection.2.8.2}% +\contentsline {subsubsection}{\numberline {2.8.3}其他功能}{9}{subsubsection.2.8.3}% \contentsline {section}{\numberline {3}联机对战设计}{9}{section.3}% \contentsline {subsection}{\numberline {3.1}通信协议}{9}{subsection.3.1}% \contentsline {subsection}{\numberline {3.2}联机对战逻辑}{10}{subsection.3.2}% \contentsline {subsubsection}{\numberline {3.2.1}双方建立连接}{10}{subsubsection.3.2.1}% \contentsline {subsubsection}{\numberline {3.2.2}一方发起对局,另一方确认对局}{10}{subsubsection.3.2.2}% \contentsline {subsubsection}{\numberline {3.2.3}完成对局并确认胜负}{10}{subsubsection.3.2.3}% -\contentsline {section}{\numberline {4}AI 算法设计}{11}{section.4}% +\contentsline {section}{\numberline {4}AI 算法设计}{12}{section.4}% \contentsline {subsection}{\numberline {4.1}Minimax 搜索和 Alpha-Beta 剪枝}{12}{subsection.4.1}% \contentsline {subsection}{\numberline {4.2}估价函数}{13}{subsection.4.2}% -\contentsline {subsection}{\numberline {4.3}参数调整}{13}{subsection.4.3}% +\contentsline {subsection}{\numberline {4.3}SA 参数调整}{14}{subsection.4.3}% \contentsline {subsection}{\numberline {4.4}AI 对战强度}{14}{subsection.4.4}% \contentsline {section}{\numberline {5}感谢}{15}{section.5}% +\contentsline {section}{\numberline {6}附录}{15}{section.6}%