From cd160ddd4110069b96496f135a952ae679a1717d Mon Sep 17 00:00:00 2001 From: CalciteM Team Date: Fri, 13 Sep 2019 00:31:20 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20millgame=20=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8D=E4=B8=BA=20position=20=E7=9B=B8=E5=85=B3=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- millgame.pro | 4 +- millgame.vcxproj | 4 +- millgame.vcxproj.filters | 12 +- src/ai/evaluate.h | 2 +- src/ai/movegen.h | 2 +- src/ai/search.h | 2 +- src/ai/tt.h | 4 +- src/ai/zobrist.h | 2 +- src/base/thread.h | 2 +- src/game/{millgame.cpp => position.cpp} | 2 +- src/game/{millgame.h => position.h} | 0 src/game/positon.h | 407 ++++++++++++++++++++++++ src/ui/qt/gamecontroller.h | 2 +- 13 files changed, 426 insertions(+), 19 deletions(-) rename src/game/{millgame.cpp => position.cpp} (99%) rename src/game/{millgame.h => position.h} (100%) create mode 100644 src/game/positon.h diff --git a/millgame.pro b/millgame.pro index a26807ed..6bac1a7e 100644 --- a/millgame.pro +++ b/millgame.pro @@ -26,7 +26,7 @@ SOURCES += \ src/ai/movegen.cpp \ src/ai/tt.cpp \ src/game/board.cpp \ - src/game/millgame.cpp \ + src/game/position.cpp \ src/game/rule.cpp \ src/main.cpp \ src/base/thread.cpp \ @@ -57,7 +57,7 @@ HEADERS += \ src/ai/search.h \ src/ai/zobrist.h \ src/game/board.h \ - src/game/millgame.h \ + src/game/position.h \ src/game/rule.h \ src/game/types.h \ src/ui/qt/client.h \ diff --git a/millgame.vcxproj b/millgame.vcxproj index 90cc7429..437080fb 100644 --- a/millgame.vcxproj +++ b/millgame.vcxproj @@ -453,7 +453,7 @@ - + @@ -696,7 +696,7 @@ - + diff --git a/millgame.vcxproj.filters b/millgame.vcxproj.filters index 51367e0d..6a5edab4 100644 --- a/millgame.vcxproj.filters +++ b/millgame.vcxproj.filters @@ -75,9 +75,6 @@ ui - - game - base @@ -111,6 +108,9 @@ ai + + game + @@ -299,9 +299,6 @@ ui - - game - ai @@ -320,6 +317,9 @@ ai + + game + diff --git a/src/ai/evaluate.h b/src/ai/evaluate.h index 1cd8e5f1..78120be2 100644 --- a/src/ai/evaluate.h +++ b/src/ai/evaluate.h @@ -24,7 +24,7 @@ #include "config.h" -#include "millgame.h" +#include "position.h" #include "search.h" class Evaluation diff --git a/src/ai/movegen.h b/src/ai/movegen.h index d5277a68..67028c29 100644 --- a/src/ai/movegen.h +++ b/src/ai/movegen.h @@ -23,7 +23,7 @@ #define MOVEGEN_H #include "config.h" -#include "millgame.h" +#include "position.h" #include "search.h" class MoveList diff --git a/src/ai/search.h b/src/ai/search.h index 3428fa84..80d5051d 100644 --- a/src/ai/search.h +++ b/src/ai/search.h @@ -34,7 +34,7 @@ #include #include -#include "millgame.h" +#include "position.h" #include "hashmap.h" #ifdef MEMORY_POOL diff --git a/src/ai/tt.h b/src/ai/tt.h index 00644c0b..9027ac20 100644 --- a/src/ai/tt.h +++ b/src/ai/tt.h @@ -3,7 +3,7 @@ #include "config.h" #include "types.h" -#include "millgame.h" +#include "position.h" #include "search.h" #include "hashmap.h" @@ -12,7 +12,7 @@ using namespace CTSL; #ifdef TRANSPOSITION_TABLE_ENABLE class TranspositionTable -{ +{ public: // 定义哈希值的类型 enum HashType : uint8_t diff --git a/src/ai/zobrist.h b/src/ai/zobrist.h index 048d8abc..0c7cf753 100644 --- a/src/ai/zobrist.h +++ b/src/ai/zobrist.h @@ -20,7 +20,7 @@ #include -#include "millgame.h" +#include "position.h" static const hash_t zobrist0[Board::N_LOCATIONS][POINT_TYPE_COUNT] = { #ifdef TRANSPOSITION_TABLE_CUTDOWN diff --git a/src/base/thread.h b/src/base/thread.h index 669b3a80..054dd042 100644 --- a/src/base/thread.h +++ b/src/base/thread.h @@ -26,7 +26,7 @@ #include #include #include -#include "millgame.h" +#include "position.h" #include "search.h" #include "server.h" #include "client.h" diff --git a/src/game/millgame.cpp b/src/game/position.cpp similarity index 99% rename from src/game/millgame.cpp rename to src/game/position.cpp index 6c61a102..dd7440ef 100644 --- a/src/game/millgame.cpp +++ b/src/game/position.cpp @@ -20,7 +20,7 @@ *****************************************************************************/ #include -#include "millgame.h" +#include "position.h" #include "search.h" #include "movegen.h" diff --git a/src/game/millgame.h b/src/game/position.h similarity index 100% rename from src/game/millgame.h rename to src/game/position.h diff --git a/src/game/positon.h b/src/game/positon.h new file mode 100644 index 00000000..7c38606f --- /dev/null +++ b/src/game/positon.h @@ -0,0 +1,407 @@ +/***************************************************************************** + * Copyright (C) 2018-2019 MillGame authors + * + * Authors: liuweilhy + * Calcitem + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifndef POSITION_H +#define POSITION_H + +#include +#include +#include + +#include "config.h" +#include "types.h" +#include "rule.h" +#include "board.h" + +using namespace std; + + +// 棋局结构体,算法相关,包含当前棋盘数据 +// 单独分离出来供AI判断局面用,生成置换表时使用 +class PositionContext +{ +public: + Board board; + + // 局面的哈希值 + hash_t hash{}; + + // Zobrist 数组 + hash_t zobrist[Board::N_LOCATIONS][POINT_TYPE_COUNT]{}; + + // 局面阶段标识 + enum PositionStage stage; + + // 轮流状态标识 + enum Player turn; + + // 动作状态标识 + enum Action action + { + }; + + // 玩家1剩余未放置子数 + int nPiecesInHand_1{}; + + // 玩家2剩余未放置子数 + int nPiecesInHand_2{}; + + // 玩家1盘面剩余子数 + int nPiecesOnBoard_1{}; + + // 玩家1盘面剩余子数 + int nPiecesOnBoard_2{}; + + // 尚待去除的子数 + int nPiecesNeedRemove{}; +}; + +// 棋类(在数据模型内,玩家只分先后手,不分黑白) +// 注意:Position 类不是线程安全的! +// 所以不能跨线程修改 Position 类的静态成员变量,切记! +class Position +{ + // AI友元类 + friend class MillGameAi_ab; + +public: + // 赢盘数 + int score_1 {}; + int score_2 {}; + int score_draw {}; + + uint64_t rand64() { + return static_cast(rand()) ^ + (static_cast(rand()) << 15) ^ + (static_cast(rand()) << 30) ^ + (static_cast(rand()) << 45) ^ + (static_cast(rand()) << 60); + } + + uint64_t rand56() + { + return rand64() << 8; + } + + static int playerToId(enum Player player); + + static Player getOpponent(enum Player player); + +private: + + // 创建哈希值 + void constructHash(); + +public: + explicit Position(); + virtual ~Position(); + + // 拷贝构造函数 + explicit Position(const Position &); + + // 运算符重载 + Position &operator=(const Position &); + + // 设置配置 + bool configure(bool giveUpIfMostLose, bool randomMove); + + // 设置棋局状态和棋盘上下文,用于初始化 + bool setContext(const struct Rule *rule, + step_t maxStepsLedToDraw = 0, // 限制步数 + int maxTimeLedToLose = 0, // 限制时间 + step_t initialStep = 0, // 默认起始步数为0 + int flags = GAME_NOTSTARTED | PLAYER1 | ACTION_PLACE, // 默认状态 + const char *board = nullptr, // 默认空棋盘 + int nPiecesInHand_1 = 12, // 玩家1剩余未放置子数 + int nPiecesInHand_2 = 12, // 玩家2剩余未放置子数 + int nPiecesNeedRemove = 0 // 尚待去除的子数 + ); + + // 获取棋局状态和棋盘上下文 + void getContext(struct Rule &rule, step_t &step, int &flags, int *&board, + int &nPiecesInHand_1, int &nPiecesInHand_2, int &nPiecesNeedRemove); + + // 获取当前规则 + const struct Rule *getRule() const + { + return ¤tRule; + } + + // 获取棋盘数据 + const int *getBoard() const + { + return context.board.locations; + } + + // 获取当前棋子位置点 + int getCurrentLocation() const + { + return currentLocation; + } + + // 判断位置点是否为星位 (星位是经常会先占的位置) + static bool isStarPoint(int location) + { + return (location == 17 || location == 19 || location == 21 || location == 23); + } + + // 获取当前步数 + int getStep() const + { + return currentStep; + } + + // 获取从上次吃子开始经历的移动步数 + int getMoveStep() const + { + return moveStep; + } + + // 获取是否必败时认输 + bool getGiveUpIfMostLose() const + { + return giveUpIfMostLose_; + } + + // 获取 AI 是否随机走子 + bool getRandomMove() const + { + return randomMove_; + } + + // 获取局面阶段标识 + enum PositionStage getStage() const + { + return context.stage; + } + + // 获取轮流状态标识 + enum Player whosTurn() const + { + return context.turn; + } + + // 获取动作状态标识 + enum Action getAction() const + { + return context.action; + } + + // 判断胜负 + enum Player whoWin() const + { + return winner; + } + + // 玩家1和玩家2的用时 + void getElapsedTime(time_t &p1_ms, time_t &p2_ms); + + // 获取棋局的字符提示 + const string getTips() const + { + return tips; + } + + // 获取当前着法 + const char *getCmdLine() const + { + return cmdline; + } + + // 获得棋谱 + const list *getCmdList() const + { + return &cmdlist; + } + + // 获取开局时间 + time_t getStartTimeb() const + { + return startTime; + } + + // 重新设置开局时间 + void setStartTime(int stimeb) + { + startTime = stimeb; + } + + // 玩家1剩余未放置子数 + int getPiecesInHandCount_1() const + { + return context.nPiecesInHand_1; + } + + // 玩家2剩余未放置子数 + int getPiecesInHandCount_2() const + { + return context.nPiecesInHand_2; + } + + // 玩家1盘面剩余子数 + int getPiecesOnBoardCount_1() const + { + return context.nPiecesOnBoard_1; + } + + // 玩家1盘面剩余子数 + int getPiecesOnBoardCount_2() const + { + return context.nPiecesOnBoard_2; + } + + // 尚待去除的子数 + int getNum_NeedRemove() const + { + return context.nPiecesNeedRemove; + } + + // 计算玩家1和玩家2的棋子活动能力之差 + int getMobilityDiff(enum Player turn, const Rule &rule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, bool includeFobidden); + + // 游戏重置 + bool reset(); + + // 游戏开始 + bool start(); + + // 选子,在第r圈第s个位置,为迎合日常,r和s下标都从1开始 + bool choose(int r, int s); + + // 落子,在第r圈第s个位置,为迎合日常,r和s下标都从1开始 + bool _place(int r, int s, int time_p = -1); + + // 去子,在第r圈第s个位置,为迎合日常,r和s下标都从1开始 + bool _capture(int r, int s, int time_p = -1); + + // 认输 + bool giveup(Player loser); + + // 命令行解析函数 + bool command(const char *cmd); + + // 更新时间和状态,用内联函数以提高效率 + inline int update(int time_p = -1); + + // 是否分出胜负 + bool win(); + bool win(bool forceDraw); + + // 清除所有禁点 + void cleanForbiddenPoints(); + + // 改变轮流 + enum Player changeTurn(); + + // 设置提示 + void setTips(); + + // 下面几个函数没有算法无关判断和无关操作,节约算法时间 + bool command(int move); + bool choose(int location); + bool place(int location, int time_p = -1, int8_t cp = 0); + bool capture(int location, int time_p = -1, int8_t cp = 0); + + // hash 相关 + hash_t getHash(); + hash_t revertHash(int location); + hash_t updateHash(int location); + hash_t updateHashMisc(); + +public: /* TODO: move to private */ + // 棋局上下文 + PositionContext context; + + // 当前使用的规则 + struct Rule currentRule + { + }; + + // 棋局上下文中的棋盘数据,单独提出来 + int *board_; + + // 棋谱 + list cmdlist; + + // 着法命令行用于棋谱的显示和解析, 当前着法的命令行指令,即一招棋谱 + char cmdline[64]{}; + + /* + 当前着法,AI会用到,如下表示 + 0x 00 00 + location1 location2 + 开局落子:0x00??,??为棋盘上的位置 + 移子:0x__??,__为移动前的位置,??为移动后的位置 + 去子:0xFF??,??取位置补码,即为负数 + + 31 ----- 24 ----- 25 + | \ | / | + | 23 -- 16 -- 17 | + | | \ | / | | + | | 15 08 09 | | + 30-22-14 10-18-26 + | | 13 12 11 | | + | | / | \ | | + | 21 -- 20 -- 19 | + | / | \ | + 29 ----- 28 ----- 27 + */ + int32_t move_{}; + + // 选中的棋子在board中的位置 + int currentLocation{}; + +private: + // 棋局哈希值 + // uint64_t hash; + + // 胜负标识 + enum Player winner; + + // 当前步数 + step_t currentStep {}; + + // 从走子阶段开始或上次吃子起的步数 + int moveStep {}; + + // 是否必败时认输 + bool giveUpIfMostLose_ {false}; + + // AI 是否随机走子 + bool randomMove_ {true}; + + // 游戏起始时间 + time_t startTime {}; + + // 当前游戏时间 + time_t currentTime {}; + + // 玩家1用时(秒) + time_t elapsedSeconds_1 {}; + + // 玩家2用时(秒) + time_t elapsedSeconds_2 {}; + + // 当前棋局的字符提示 + string tips; +}; + +#endif /* POSITION_H */ diff --git a/src/ui/qt/gamecontroller.h b/src/ui/qt/gamecontroller.h index 97544164..3520425a 100644 --- a/src/ui/qt/gamecontroller.h +++ b/src/ui/qt/gamecontroller.h @@ -37,7 +37,7 @@ #include #include -#include "millgame.h" +#include "position.h" #include "gamescene.h" #include "pieceitem.h" #include "thread.h"