AI勉强能动,还是得改
This commit is contained in:
parent
41917c1d74
commit
24d897eb69
|
@ -34,15 +34,14 @@ void AiThread::run()
|
|||
mutex.unlock();
|
||||
|
||||
ai_ab.setChess(*chess);
|
||||
ai_ab.alphaBetaPruning(1);
|
||||
ai_ab.alphaBetaPruning(5);
|
||||
const char * str = ai_ab.bestMove();
|
||||
qDebug() << str;
|
||||
emit command(str);
|
||||
if (strcmp(str, "error!"))
|
||||
emit command(str);
|
||||
|
||||
// 测试用
|
||||
qDebug() << "thread running " << iTemp << "ms";
|
||||
msleep(250);
|
||||
iTemp += 250;
|
||||
qDebug() << "thread running " << iTemp++ << "times";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,10 +66,10 @@ void AiThread::stop()
|
|||
return;
|
||||
|
||||
mutex.lock();
|
||||
requestInterruption();
|
||||
if (waiting_) {
|
||||
waiting_ = false;
|
||||
pauseCondition.wakeAll();
|
||||
}
|
||||
requestInterruption();
|
||||
mutex.unlock();
|
||||
}
|
||||
|
|
|
@ -92,6 +92,14 @@ void GameController::gameReset()
|
|||
chess.reset();
|
||||
chessTemp = chess;
|
||||
|
||||
// 停掉线程
|
||||
ai1.stop();
|
||||
ai1.quit();
|
||||
ai1.wait();
|
||||
ai2.stop();
|
||||
ai2.quit();
|
||||
ai2.wait();
|
||||
|
||||
// 清除棋子
|
||||
qDeleteAll(pieceList);
|
||||
pieceList.clear();
|
||||
|
@ -210,7 +218,10 @@ void GameController::setEngine1(bool arg)
|
|||
if (arg) {
|
||||
qDebug() << "Player1 is computer.";
|
||||
ai1.setAi(chess);
|
||||
ai1.start();
|
||||
if (ai1.isRunning())
|
||||
ai1.resume();
|
||||
else
|
||||
ai1.start();
|
||||
}
|
||||
else {
|
||||
qDebug() << "Player1 is not computer.";
|
||||
|
@ -221,8 +232,18 @@ void GameController::setEngine1(bool arg)
|
|||
void GameController::setEngine2(bool arg)
|
||||
{
|
||||
isEngine2 = arg;
|
||||
qDebug() << "size of NineChess::ChessData" << sizeof(NineChess::ChessData);
|
||||
qDebug() << "size of NineChess: " << sizeof(chess);
|
||||
if (arg) {
|
||||
qDebug() << "Player2 is computer.";
|
||||
ai2.setAi(chess);
|
||||
if (ai2.isRunning())
|
||||
ai2.resume();
|
||||
else
|
||||
ai2.start();
|
||||
}
|
||||
else {
|
||||
qDebug() << "Player2 is not computer.";
|
||||
ai2.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::setAnimation(bool arg)
|
||||
|
@ -708,18 +729,20 @@ bool GameController::updateScence(NineChess &chess)
|
|||
// 如果还未决出胜负
|
||||
if (chess.whoWin() == NineChess::NOBODY) {
|
||||
if (chess.whosTurn() == NineChess::PLAYER1) {
|
||||
ai1.resume();
|
||||
if(isEngine1)
|
||||
ai1.resume();
|
||||
ai2.pause();
|
||||
}
|
||||
else {
|
||||
if(isEngine2)
|
||||
ai2.resume();
|
||||
ai1.pause();
|
||||
ai2.resume();
|
||||
}
|
||||
}
|
||||
// 如果已经决出胜负
|
||||
else {
|
||||
ai1.pause();
|
||||
ai1.pause();
|
||||
ai1.stop();
|
||||
ai2.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -633,7 +633,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
|
|||
return false;
|
||||
}
|
||||
// 移子
|
||||
move_ = currentPos << 8 + pos;
|
||||
move_ = (currentPos << 8) + pos;
|
||||
player_ms = update(time_p);
|
||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u.%03u", currentPos / SEAT, currentPos % SEAT + 1,
|
||||
c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000);
|
||||
|
@ -910,7 +910,7 @@ bool NineChess::place(int pos)
|
|||
return false;
|
||||
}
|
||||
// 移子
|
||||
move_ = currentPos << 8 + pos;
|
||||
move_ = (currentPos << 8) + pos;
|
||||
board[pos] = board[currentPos];
|
||||
board[currentPos] = '\x00';
|
||||
currentPos = pos;
|
||||
|
|
|
@ -111,15 +111,15 @@ public:
|
|||
enum NineChess::Actions action;
|
||||
|
||||
// 玩家1剩余未放置子数
|
||||
int8_t player1_InHand;
|
||||
char player1_InHand;
|
||||
// 玩家2剩余未放置子数
|
||||
int8_t player2_InHand;
|
||||
char player2_InHand;
|
||||
// 玩家1盘面剩余子数
|
||||
int8_t player1_Remain;
|
||||
char player1_Remain;
|
||||
// 玩家1盘面剩余子数
|
||||
int8_t player2_Remain;
|
||||
char player2_Remain;
|
||||
// 尚待去除的子数
|
||||
int8_t num_NeedRemove;
|
||||
char num_NeedRemove;
|
||||
|
||||
/* 本打算用如下的结构体来表示“三连”
|
||||
struct Mill {
|
||||
|
|
|
@ -22,11 +22,17 @@ depth(3) // 默认3层深度
|
|||
NineChessAi_ab::~NineChessAi_ab()
|
||||
{
|
||||
deleteTree(rootNode);
|
||||
rootNode = nullptr;
|
||||
}
|
||||
|
||||
void NineChessAi_ab::buildChildren(Node *node)
|
||||
{
|
||||
char opponent;
|
||||
// 如果有子节点,则返回,避免重复建立
|
||||
if (node->children.size())
|
||||
return;
|
||||
|
||||
// 临时变量
|
||||
char opponent = chessTemp.data.turn == NineChess::PLAYER1 ? 0x20 : 0x10;
|
||||
// 列出所有合法的下一招
|
||||
switch (chessTemp.data.action)
|
||||
{
|
||||
|
@ -49,28 +55,29 @@ void NineChessAi_ab::buildChildren(Node *node)
|
|||
char newPos;
|
||||
for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) {
|
||||
if (!chessTemp.choose(i))
|
||||
break;
|
||||
continue;
|
||||
if ((chessTemp.data.turn == NineChess::PLAYER1 && (chessTemp.data.player1_Remain > chessTemp.rule.numAtLest || !chessTemp.rule.canFly)) ||
|
||||
(chessTemp.data.turn == NineChess::PLAYER2 && (chessTemp.data.player2_Remain > chessTemp.rule.numAtLest || !chessTemp.rule.canFly))) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (newPos == chessTemp.moveTable[i][j]) {
|
||||
newPos = chessTemp.moveTable[i][j];
|
||||
if (newPos && !chessTemp.board[newPos]) {
|
||||
Node * newNode = new Node;
|
||||
newNode->parent = node;
|
||||
newNode->value = 0;
|
||||
newNode->move = i << 8 + newPos;
|
||||
newNode->move = (i << 8) + newPos;
|
||||
node->children.push_back(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int j = NineChess::SEAT; j < (NineChess::RING + 1)*NineChess::SEAT; j++) {
|
||||
if (newPos & chessTemp.board[j])
|
||||
break;
|
||||
Node * newNode = new Node;
|
||||
newNode->parent = node;
|
||||
newNode->value = 0;
|
||||
newNode->move = i << 8 + j;
|
||||
node->children.push_back(newNode);
|
||||
if (!chessTemp.board[j]) {
|
||||
Node * newNode = new Node;
|
||||
newNode->parent = node;
|
||||
newNode->value = 0;
|
||||
newNode->move = (i << 8) + j;
|
||||
node->children.push_back(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +85,6 @@ void NineChessAi_ab::buildChildren(Node *node)
|
|||
break;
|
||||
|
||||
case NineChess::ACTION_CAPTURE:
|
||||
opponent = chessTemp.data.turn == NineChess::PLAYER1 ? 0x20 : 0x10;
|
||||
// 全成三的情况
|
||||
if (chessTemp.isAllInMills(opponent)) {
|
||||
for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) {
|
||||
|
@ -94,13 +100,13 @@ void NineChessAi_ab::buildChildren(Node *node)
|
|||
else {
|
||||
for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) {
|
||||
if (chessTemp.board[i] & opponent) {
|
||||
if (chessTemp.isInMills(i))
|
||||
break;
|
||||
Node * newNode = new Node;
|
||||
newNode->parent = node;
|
||||
newNode->value = 0;
|
||||
newNode->move = -i;
|
||||
node->children.push_back(newNode);
|
||||
if (!chessTemp.isInMills(i)) {
|
||||
Node * newNode = new Node;
|
||||
newNode->parent = node;
|
||||
newNode->value = 0;
|
||||
newNode->move = -i;
|
||||
node->children.push_back(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +145,12 @@ void NineChessAi_ab::setChess(const NineChess &chess)
|
|||
this->chess = chess;
|
||||
chessTemp = chess;
|
||||
chessData = &(chessTemp.data);
|
||||
deleteTree(rootNode);
|
||||
rootNode = new Node;
|
||||
rootNode->value = 0;
|
||||
rootNode->move = 0;
|
||||
rootNode->parent = nullptr;
|
||||
|
||||
requiredQuit = false;
|
||||
// 生成棋子价值表
|
||||
for (int j = 0; j < NineChess::SEAT; j++)
|
||||
|
@ -191,9 +203,9 @@ int NineChessAi_ab::evaluate(Node *node)
|
|||
case NineChess::ACTION_CHOOSE:
|
||||
case NineChess::ACTION_PLACE:
|
||||
break;
|
||||
// 如果形成去子状态,每有一个可去的子,算100分
|
||||
// 如果形成去子状态,每有一个可去的子,算500分
|
||||
case NineChess::ACTION_CAPTURE:
|
||||
value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 100 : -chessData->num_NeedRemove * 100;
|
||||
value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 500 : -chessData->num_NeedRemove * 500;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -240,11 +252,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
|||
// 对先手,搜索Max
|
||||
if (chessTemp.whosTurn() == NineChess::PLAYER1) {
|
||||
for (auto child : node->children) {
|
||||
hashTable.push_back({chessTemp.data, 0, depth});
|
||||
dataStack.push(chessTemp.data);
|
||||
chessTemp.command(child->move);
|
||||
value = alphaBetaPruning(depth - 1, alpha, beta, child);
|
||||
chessTemp.data = hashTable.back().data;
|
||||
hashTable.pop_back();
|
||||
chessTemp.data = dataStack.top();
|
||||
dataStack.pop();
|
||||
// 取最大值
|
||||
if (value > alpha)
|
||||
alpha = value;
|
||||
|
@ -259,11 +271,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
|||
// 对后手,搜索Min
|
||||
else {
|
||||
for (auto child : node->children) {
|
||||
hashTable.push_back({ chessTemp.data, 0, depth });
|
||||
dataStack.push(chessTemp.data);
|
||||
chessTemp.command(child->move);
|
||||
value = alphaBetaPruning(depth - 1, alpha, beta, child);
|
||||
chessTemp.data = hashTable.back().data;
|
||||
hashTable.pop_back();
|
||||
chessTemp.data = dataStack.top();
|
||||
dataStack.pop();
|
||||
// 取最小值
|
||||
if (value < beta)
|
||||
beta = value;
|
||||
|
@ -293,7 +305,7 @@ const char *NineChessAi_ab::bestMove()
|
|||
break;
|
||||
}
|
||||
srand((unsigned)time(0));
|
||||
int i = rand() % 12;
|
||||
int i = rand() % n;
|
||||
return move2string(moves[i]);
|
||||
}
|
||||
|
||||
|
@ -304,16 +316,16 @@ const char *NineChessAi_ab::move2string(int16_t move)
|
|||
chessTemp.pos2cp(-move, c, p);
|
||||
sprintf(cmdline, "-(%1u,%1u)", c, p);
|
||||
}
|
||||
else if (move & 0x00ff) {
|
||||
chessTemp.pos2cp(move & 0x00ff, c, p);
|
||||
sprintf(cmdline, "(%1u,%1u)", c, p);
|
||||
}
|
||||
else {
|
||||
else if (move & 0x7f00) {
|
||||
int c1, p1;
|
||||
chessTemp.pos2cp(move >> 8, c1, p1);
|
||||
chessTemp.pos2cp(move & 0x00ff, c, p);
|
||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", c1, p1, c, p);
|
||||
}
|
||||
else {
|
||||
chessTemp.pos2cp(move & 0x007f, c, p);
|
||||
sprintf(cmdline, "(%1u,%1u)", c, p);
|
||||
}
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
#include "ninechess.h"
|
||||
#include <list>
|
||||
#include <stack>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 注意:NineChess类不是线程安全的!
|
||||
// 所以不能在ai类中修改NineChess类的静态成员变量,切记!
|
||||
|
@ -79,6 +82,8 @@ private:
|
|||
|
||||
// 根节点
|
||||
Node * rootNode;
|
||||
// 局面数据栈
|
||||
stack<NineChess::ChessData> dataStack;
|
||||
// 局面数据哈希表
|
||||
list<struct Hash> hashTable;
|
||||
// 哈希表最大大小
|
||||
|
|
Loading…
Reference in New Issue