Small cleanups

No functional change
This commit is contained in:
Calcitem 2021-04-26 22:55:08 +08:00
parent f2afddc415
commit 36af532a41
37 changed files with 199 additions and 329 deletions

View File

@ -34,10 +34,6 @@ BINDIR = $(PREFIX)/bin
PGOBENCH = ./$(EXE) bench
### Source and object files
#SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
# material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
# search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
# nnue/evaluate_nnue.cpp nnue/features/half_kp.cpp
SRCS = bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
mills.cpp misc.cpp movegen.cpp movepick.cpp option.cpp position.cpp rule.cpp \
search.cpp thread.cpp tt.cpp uci.cpp ucioption.cpp

View File

@ -23,7 +23,7 @@
#include "types.h"
#define SET_BIT(x, bit) (x |= (1 << bit))
#define SET_BIT(x, bit) (x |= (1 << bit))
#define CLEAR_BIT(x, bit) (x &= ~(1 << bit))
#define S2(a, b) (square_bb(SQ_##a) | square_bb(SQ_##b))
@ -82,17 +82,17 @@ inline Bitboard star_square_bb_12() noexcept
/// Overloads of bitwise operators between a Bitboard and a Square for testing
/// whether a given bit is set in a bitboard, and for setting and clearing bits.
inline Bitboard operator&(Bitboard b, Square s) noexcept
inline Bitboard operator&(Bitboard b, Square s) noexcept
{
return b & square_bb(s);
}
inline Bitboard operator|(Bitboard b, Square s) noexcept
inline Bitboard operator|(Bitboard b, Square s) noexcept
{
return b | square_bb(s);
}
inline Bitboard operator^(Bitboard b, Square s) noexcept
inline Bitboard operator^(Bitboard b, Square s) noexcept
{
return b ^ square_bb(s);
}

View File

@ -19,13 +19,14 @@
#ifndef DEBUG_H
#define DEBUG_H
#include "config.h"
#include <cstdio>
#ifdef QT_GUI_LIB
#include <QDebug>
#endif
#include "config.h"
//#define QT_NO_DEBUG_OUTPUT
#define CSTYLE_DEBUG_OUTPUT

View File

@ -34,16 +34,17 @@
#define HASH_KEY_DISABLE
constexpr size_t HASH_SIZE_DEFAULT = 1031; // A prime number as key size gives a better distribution of values in buckets
namespace CTSL //Concurrent Thread Safe Library
namespace CTSL // Concurrent Thread Safe Library
{
//The class represting the key map.
//It is expected for user defined types, the key function will be provided.
//By default, the std::key function will be used
//If the key size is not provided, then a defult size of 1031 will be used
//The key table itself consists of an array of key buckets.
//Each key bucket is implemented as singly linked list with the head as a dummy node created
//during the creation of the bucket. All the key buckets are created during the construction of the map.
//Locks are taken per bucket, hence multiple threads can write simultaneously in different buckets in the key map
// The class representing the key map.
// It is expected for user defined types, the key function will be provided.
// By default, the std::key function will be used
// If the key size is not provided, then a default size of 1031 will be used
// The key table itself consists of an array of key buckets.
// Each key bucket is implemented as singly linked list with the head as a dummy node created
// during the creation of the bucket. All the key buckets are created during the construction of the map.
// Locks are taken per bucket, hence multiple threads can write simultaneously in different buckets in the key map
#ifdef HASH_KEY_DISABLE
#define hashFn Key
template <typename K, typename V>
@ -59,9 +60,9 @@ namespace CTSL //Concurrent Thread Safe Library
#ifdef ALIGNED_LARGE_PAGES
hashTable = (HashNode<K, V>*)aligned_large_pages_alloc(sizeof(HashNode<K, V>) * hashSize);
#else
hashTable = new HashNode<K, V>[hashSize]; //create the key table as an array of key nodes
hashTable = new HashNode<K, V>[hashSize]; // Create the key table as an array of key nodes
#endif // ALIGNED_LARGE_PAGES
memset(hashTable, 0, sizeof(HashNode<K, V>) * hashSize);
#else
hashTable = new HashBucket<K, V>[hashSize]; //create the key table as an array of key buckets
@ -76,15 +77,15 @@ namespace CTSL //Concurrent Thread Safe Library
delete [] hashTable;
#endif
}
//Copy and Move of the HashMap are not supported at this moment
// Copy and Move of the HashMap are not supported at this moment
HashMap(const HashMap&) = delete;
HashMap(HashMap&&) = delete;
HashMap& operator=(const HashMap&) = delete;
HashMap& operator=(HashMap&&) = delete;
//Function to find an entry in the key map matching the key.
//If key is found, the corresponding value is copied into the parameter "value" and function returns true.
//If key is not found, function returns false.
// Function to find an entry in the key map matching the key.
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
// If key is not found, function returns false.
bool find(const K &key, V &value) const
{
K hashValue = hashFn(key) & (hashSize - 1) ;
@ -113,8 +114,8 @@ namespace CTSL //Concurrent Thread Safe Library
prefetch((void *)addr);
}
//Function to insert into the key map.
//If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair.
// Function to insert into the key map.
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair.
K insert(const K &key, const V &value)
{
K hashValue = hashFn(key) & (hashSize - 1);
@ -130,7 +131,7 @@ namespace CTSL //Concurrent Thread Safe Library
return hashValue;
}
//Function to remove an entry from the bucket, if found
// Function to remove an entry from the bucket, if found
void erase(
#ifndef DISABLE_HASHBUCKET
const K &key
@ -146,7 +147,7 @@ namespace CTSL //Concurrent Thread Safe Library
}
//Function to clean up the hasp map, i.e., remove all entries from it
// Function to clean up the hasp map, i.e., remove all entries from it
void clear()
{
#ifdef DISABLE_HASHBUCKET
@ -161,7 +162,7 @@ namespace CTSL //Concurrent Thread Safe Library
void resize(size_t size)
{
// TODO
// TODO: Resize
if (size < 0x1000000) {
// New size is too small, do not resize
return;
@ -175,7 +176,7 @@ namespace CTSL //Concurrent Thread Safe Library
return;
}
//Function to dump the key map to file
// Function to dump the key map to file
void dump(const std::string &filename)
{
#ifdef DISABLE_HASHBUCKET
@ -282,5 +283,5 @@ namespace CTSL //Concurrent Thread Safe Library
#endif
};
}
#endif
#endif // HASH_MAP_H_

View File

@ -19,12 +19,12 @@
#ifndef HASH_NODE_H_
#define HASH_NODE_H_
#include <shared_mutex>
#include "config.h"
#include <shared_mutex>
namespace CTSL //Concurrent Thread Safe Library
namespace CTSL // Concurrent Thread Safe Library
{
// Class representing a templatized key node
// Class representing a template key node
template <typename K, typename V>
class HashNode
{
@ -53,16 +53,16 @@ namespace CTSL //Concurrent Thread Safe Library
void setKey(K key_) {key = key_;}
#ifndef DISABLE_HASHBUCKET
HashNode *next; //Pointer to the next node in the same bucket
HashNode *next; // Pointer to the next node in the same bucket
#endif
private:
K key; //the key key
V value; //the value corresponding to the key
K key; // the key key
V value; // the value corresponding to the key
};
//Class representing a key bucket. The bucket is implemented as a singly linked list.
//A bucket is always constructed with a dummy head node
// Class representing a key bucket. The bucket is implemented as a singly linked list.
// A bucket is always constructed with a dummy head node
template <typename K, typename V>
class HashBucket
{
@ -75,14 +75,15 @@ namespace CTSL //Concurrent Thread Safe Library
clear();
}
//Function to find an entry in the bucket matching the key
//If key is found, the corresponding value is copied into the parameter "value" and function returns true.
//If key is not found, function returns false
// Function to find an entry in the bucket matching the key
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
// If key is not found, function returns false
bool find(const K &key, V &value) const
{
// A shared mutex is used to enable multiple concurrent reads
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
HashNode<K, V> * node = head;
#ifdef DISABLE_HASHBUCKET
if (node == nullptr) {
return false;
@ -93,28 +94,27 @@ namespace CTSL //Concurrent Thread Safe Library
return true;
}
#else // DISABLE_HASHBUCKET
while (node != nullptr)
{
if (node->getKey() == key)
{
while (node != nullptr) {
if (node->getKey() == key) {
value = node->getValue();
return true;
}
node = node->next;
}
#endif // DISABLE_HASHBUCKET
return false;
}
//Function to insert into the bucket
//If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair
// Function to insert into the bucket
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair
void insert(const K &key, const V &value)
{
//Exclusive lock to enable single write in the bucket
// Exclusive lock to enable single write in the bucket
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
#ifdef DISABLE_HASHBUCKET
if (head == nullptr)
{
if (head == nullptr) {
head = new HashNode<K, V>(key, value);
return;
}
@ -124,39 +124,31 @@ namespace CTSL //Concurrent Thread Safe Library
HashNode<K, V> * prev = nullptr;
HashNode<K, V> * node = head;
while (node != nullptr && node->getKey() != key)
{
while (node != nullptr && node->getKey() != key) {
prev = node;
node = node->next;
}
if (nullptr == node) //New entry, create a node and add to bucket
{
if(nullptr == head)
{
if (nullptr == node) { // New entry, create a node and add to bucket
if (nullptr == head) {
head = new HashNode<K, V>(key, value);
}
else
{
} else {
prev->next = new HashNode<K, V>(key, value);
}
}
else
{
node->setValue(value); //Key found in bucket, update the value
} else {
node->setValue(value); // Key found in bucket, update the value
}
#endif // DISABLE_HASHBUCKET
}
//Function to remove an entry from the bucket, if found
// Function to remove an entry from the bucket, if found
void erase(const K &key)
{
//Exclusive lock to enable single write in the bucket
// Exclusive lock to enable single write in the bucket
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
#ifdef DISABLE_HASHBUCKET
if (head == nullptr) //Key not found, nothing to be done
{
if (head == nullptr) { // Key not found, nothing to be done
return;
}
@ -168,24 +160,17 @@ namespace CTSL //Concurrent Thread Safe Library
HashNode<K, V> *prev = nullptr;
HashNode<K, V> *node = head;
while (node != nullptr && node->getKey() != key)
{
while (node != nullptr && node->getKey() != key) {
prev = node;
node = node->next;
}
if (nullptr == node) //Key not found, nothing to be done
{
if (nullptr == node) { //Key not found, nothing to be done
return;
}
else //Remove the node from the bucket
{
if (head == node)
{
} else { //Remove the node from the bucket
if (head == node) {
head = node->next;
}
else
{
} else {
prev->next = node->next;
}
delete node; //Free up the memory
@ -198,21 +183,23 @@ namespace CTSL //Concurrent Thread Safe Library
{
//Exclusive lock to enable single write in the bucket
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
#ifdef DISABLE_HASHBUCKET
if (head != nullptr)
{
if (head != nullptr) {
delete head;
}
#else // DISABLE_HASHBUCKET
HashNode<K, V> * prev = nullptr;
HashNode<K, V> * node = head;
while(node != nullptr)
{
while(node != nullptr) {
prev = node;
node = node->next;
delete prev;
}
#endif // DISABLE_HASHBUCKET
head = nullptr;
}
@ -222,4 +209,4 @@ namespace CTSL //Concurrent Thread Safe Library
};
}
#endif
#endif // HASH_NODE_H_

View File

@ -426,7 +426,7 @@ void move_priority_list_shuffle()
#endif
}
Depth getSearchDepth(const Position *pos)
Depth get_search_depth(const Position *pos)
{
if (!gameOptions.getDeveloperMode()) {
return (Depth)gameOptions.getSkillLevel();
@ -578,8 +578,6 @@ Depth getSearchDepth(const Position *pos)
assert(d <= 32);
//loggerDebug("Depth: %d\n", d);
#ifdef FLUTTER_UI
LOGD("Search depth: %d\n", d);
#endif // FLUTTER_UI

View File

@ -37,7 +37,7 @@ namespace Mills
void adjacent_squares_init() noexcept;
void mill_table_init();
void move_priority_list_shuffle();
Depth getSearchDepth(const Position *pos);
Depth get_search_depth(const Position *pos);
}

View File

@ -106,7 +106,6 @@ struct Tie : public streambuf
int log(int c, const char *prefix)
{
static int last = '\n'; // Single log file
if (last == '\n')
@ -118,7 +117,6 @@ struct Tie : public streambuf
class Logger
{
Logger() : in(cin.rdbuf(), file.rdbuf()), out(cout.rdbuf(), file.rdbuf())
{
}

View File

@ -38,7 +38,7 @@ ExtMove *generate<PLACE>(Position &pos, ExtMove *moveList)
for (auto s : MoveList<LEGAL>::movePriorityList) {
if (!pos.get_board()[s]) {
*cur++ = (Move)s;
}
}
}
return cur;

View File

@ -103,7 +103,7 @@ void MovePicker::score()
//cur->value += bannedCount; // placing phrase, place nearby ban point
// for 12 men, white 's 2nd move place star point is as important as close mill (TODO)
// for 12 men, white 's 2nd move place star point is as important as close mill (TODO)
if (rule.piecesCount == 12 &&
pos.count<ON_BOARD>(WHITE) < 2 && // patch: only when white's 2nd move
Position::is_star_square(static_cast<Square>(m))) {
@ -142,7 +142,7 @@ void MovePicker::score()
}
}
// prefer remove piece that mobility is strong
// prefer remove piece that mobility is strong
cur->value += emptyCount;
}
#endif // !SORT_MOVE_WITHOUT_HUMAN_KNOWLEDGES

View File

@ -246,7 +246,7 @@ Position &Position::set(const string &fenStr, Thread *th)
// 2. Active color
ss >> token;
sideToMove = (token == 'b' ? BLACK : WHITE);
them = ~sideToMove; // Stockfish do not need to set them
them = ~sideToMove; // Note: Stockfish do not need to set them
// 3. Phrase
ss >> token;
@ -667,7 +667,7 @@ bool Position::put_piece(Square s, bool updateRecord)
|| is_all_in_mills(them)
#endif
) {
assert(pieceInHandCount[BLACK] >= 0 && pieceInHandCount[WHITE] >= 0);
assert(pieceInHandCount[BLACK] >= 0 && pieceInHandCount[WHITE] >= 0);
if (pieceInHandCount[BLACK] == 0 && pieceInHandCount[WHITE] == 0) {
if (check_if_game_is_over()) {
@ -695,7 +695,7 @@ bool Position::put_piece(Square s, bool updateRecord)
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
update_key_misc();
action = Action::remove;
}
}
} else if (phase == Phase::moving) {
@ -709,7 +709,7 @@ bool Position::put_piece(Square s, bool updateRecord)
}
#endif // MUEHLE_NMM
// if illegal
// If illegal
if (pieceOnBoardCount[sideToMove] > rule.piecesAtLeastCount ||
!rule.mayFly) {
if ((square_bb(s) & MoveList<LEGAL>::adjacentSquaresBB[currentSquare]) == 0) {
@ -857,7 +857,7 @@ bool Position::remove_piece(Square s, bool updateRecord)
change_side_to_move();
check:
check_if_game_is_over();
check_if_game_is_over();
return true;
}
@ -972,18 +972,13 @@ void Position::update_score()
}
score[winner]++;
// Test Point
if (winner == BLACK)
{
winner = winner;
}
}
}
bool Position::check_if_game_is_over()
{
if (phase == Phase::ready || phase == Phase::gameOver) {
if (phase == Phase::ready ||
phase == Phase::gameOver) {
return true;
}
@ -1005,7 +1000,7 @@ bool Position::check_if_game_is_over()
return true;
}
if (phase == Phase::moving && action == Action::select && is_all_surrounded(sideToMove)) {
if (phase == Phase::moving && action == Action::select && is_all_surrounded(sideToMove)) {
if (rule.isLoseButNotChangeSideWhenNoWay) {
set_gameover(~sideToMove, GameOverReason::loseReasonNoWay);
return true;
@ -1013,7 +1008,7 @@ bool Position::check_if_game_is_over()
change_side_to_move(); // TODO: Need?
return false;
}
}
}
return false;
}
@ -1038,7 +1033,7 @@ int Position::get_mobility_diff()
}
}
}
}
}
}
return mobilityBlack - mobilityWhite;
@ -1080,13 +1075,7 @@ inline void Position::change_side_to_move()
inline Key Position::update_key(Square s)
{
// PieceType is board[s]
// 0b00 - no piece, 0b01 = 1 black, 0b10 = 2 white, 0b11 = 3 ban
const int pieceType = color_on(s);
// TODO: this is std, but current code can work
//Location loc = board[s];
//int pieceType = loc == 0x0f? 3 : loc >> 4;
st.key ^= Zobrist::psq[pieceType][s];

View File

@ -36,11 +36,11 @@
struct StateInfo
{
// Copied when making a move
int rule50 {0};
int pliesFromNull;
int rule50 {0};
int pliesFromNull;
// Not copied when making a move (will be recomputed anyhow)
Key key;
Key key;
};
@ -115,7 +115,7 @@ public:
bool check_if_game_is_over();
void remove_ban_stones();
void set_side_to_move(Color c);
void change_side_to_move();
Color get_winner() const noexcept;
void set_gameover(Color w, GameOverReason reason);
@ -133,7 +133,7 @@ public:
int potential_mills_count(Square to, Color c, Square from = SQ_0);
bool is_all_in_mills(Color c);
void surrounded_pieces_count(Square s, int &nOurPieces, int &nTheirPieces, int &nBanned, int &nEmpty);
void surrounded_pieces_count(Square s, int &ourPieceCount, int &theirPieceCount, int &bannedCount, int &emptyCount);
bool is_all_surrounded(Color c
#ifdef MUEHLE_NMM
, Square from = SQ_0, Square to = SQ_0
@ -164,15 +164,13 @@ public:
bool move_piece(File f1, Rank r1, File f2, Rank r2);
bool move_piece(Square from, Square to);
bool undo_move_piece(Square from, Square to);
// Data members
Piece board[SQUARE_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];
Bitboard byColorBB[COLOR_NB];
// TODO: [0] is sum of Black and White
int pieceInHandCount[COLOR_NB]{ 0, 12, 12 }; // TODO
int pieceOnBoardCount[COLOR_NB]{ 0, 0, 0 };
int pieceInHandCount[COLOR_NB] { 0, 12, 12 };
int pieceOnBoardCount[COLOR_NB] { 0, 0, 0 };
int pieceToRemoveCount{ 0 };
int gamePly { 0 };
Color sideToMove { NOCOLOR };
@ -271,9 +269,6 @@ inline void Position::put_piece(Piece pc, Square s)
board[s] = pc;
byTypeBB[ALL_PIECES] |= byTypeBB[type_of(pc)] |= s;
byColorBB[color_of(pc)] |= s;
//index[s] = pieceCount[pc]++;
//pieceList[pc][index[s]] = s;
//pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
}
inline bool Position::put_piece(File f, Rank r)
@ -295,11 +290,6 @@ inline bool Position::remove_piece(File f, Rank r)
return ret;
}
inline bool Position::undo_move_piece(Square from, Square to)
{
return move_piece(to, from); // TODO
}
inline bool Position::move_piece(Square from, Square to)
{
if (select_piece(from)) {

View File

@ -22,7 +22,7 @@
#include "types.h"
struct Rule rule = {
"打三棋(12连棋)", // 打三棋
"打三棋(12连棋)", // 打三棋
// 规则说明
"1. 双方各12颗子棋盘有斜线\n"
"2. 摆棋阶段被提子的位置不能再摆子,直到走棋阶段;\n"
@ -43,7 +43,6 @@ struct Rule rule = {
99 // 99半步即50回合
};
// TODO
const struct Rule RULES[N_RULES] = {
{
"成三棋", // 成三棋

View File

@ -28,30 +28,41 @@ struct Rule
const char description[512];
// Number of pieces each player has at the beginning.
// The number of pieces each player has
int piecesCount;
int piecesAtLeastCount; // Default is 3
// Add four diagonal lines to the board.
bool hasDiagonalLines;
// In the placing phase, the points of removed pieces will no longer be able to place.
bool hasBannedLocations;
// The player who moves second in the placing phrase moves first in the moving phrase.
bool isDefenderMoveFirst;
// When closing more than one mill at once, may also remove several opponent pieces.
// If a player close more than one mill at once,
// she will be able to remove the number of mills she closed.
bool mayRemoveMultiple;
// May remove from mills even if there are other pieces available.
// By default, players must remove any other pieces first before removing a piece from a formed mill.
// Enable this option to disable the limitation.
bool mayRemoveFromMillsAlways;
// At the end of the placing phase, when the board is full,
// the side that places first loses the game, otherwise, the game is a draw.
bool isBlackLoseButNotDrawWhenBoardFull;
// The player will lose if his opponent blocks them so that they cannot be moved.
// Change side to move if this option is disabled.
bool isLoseButNotChangeSideWhenNoWay;
// Player may fly if he is down to three pieces.
bool mayFly;
// If a player has only three pieces left,
// she is allowed to move the piece to any free point.
size_t maxStepsLedToDraw;
};

View File

@ -84,12 +84,12 @@ int Thread::search()
int np = bestvalue / VALUE_EACH_PIECE;
if (np > 1) {
cout << "Lazy Mode: " << np << endl;
originDepth = 4;
originDepth = 4; // TODO
} else {
originDepth = getDepth();
originDepth = get_depth();
}
} else {
originDepth = getDepth();
originDepth = get_depth();
}
const time_t time0 = time(nullptr);
@ -117,10 +117,6 @@ int Thread::search()
}
#endif // THREEFOLD_REPETITION
#if defined(UCI_DO_BEST_MOVE) || defined(QT_GUI_LIB)
//posKeyHistory.push_back(rootPos->key());
#endif // UCI_DO_BEST_MOVE
assert(posKeyHistory.size() < 256);
}
@ -175,7 +171,7 @@ int Thread::search()
if (is_timeout(startTime)) {
loggerDebug("originDepth = %d, depth = %d\n", originDepth, i);
goto out;
goto out;
}
}
@ -284,8 +280,6 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
}
#endif /* ENDGAME_LEARNING */
const bool atRoot = (originDepth == depth);
#ifdef TRANSPOSITION_TABLE_ENABLE
// check transposition-table
@ -297,7 +291,7 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
const Value probeVal = TranspositionTable::probe(posKey, depth, alpha, beta, type
#ifdef TT_MOVE_ENABLE
, ttMove
#endif // TT_MOVE_ENABLE
#endif // TT_MOVE_ENABLE
);
if (probeVal != VALUE_UNKNOWN) {
@ -307,20 +301,6 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
bestValue = probeVal;
#if 0
// TODO: Need adjust value?
if (position->turn == BLACK)
bestValue += tte.depth - depth;
else
bestValue -= tte.depth - depth;
#endif
#ifdef TT_MOVE_ENABLE
// if (ttMove != MOVE_NONE) {
// bestMove = ttMove;
// }
#endif // TT_MOVE_ENABLE
return bestValue;
}
#ifdef TRANSPOSITION_TABLE_DEBUG
@ -329,15 +309,8 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
}
#endif
//hashMapMutex.unlock();
#endif /* TRANSPOSITION_TABLE_ENABLE */
#if 0
if (position->phase == Phase::placing && depth == 1 && pos->pieceToRemoveCount > 0) {
depth--;
}
#endif
// process leaves
// Check for aborted search
@ -380,14 +353,7 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
}
#if 0
// Follow morris, do not save to TT
if (moveCount == 0) {
return -VALUE_INFINITE;
}
#endif
#if 0
// TODO: weak
// TODO: Weak
if (bestMove != MOVE_NONE) {
for (int i = 0; i < moveCount; i++) {
if (mp.moves[i].move == bestMove) { // TODO: need to write value?
@ -468,7 +434,6 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
if (Threads.stop.load(std::memory_order_relaxed))
return VALUE_ZERO;
// TODO: Not follow morris
if (value >= bestValue) {
bestValue = value;
@ -530,7 +495,9 @@ bool is_timeout(TimePoint startTime)
TimePoint elapsed = now() - startTime;
if (elapsed > limit) {
#ifdef _WIN32
loggerDebug("\nTimeout. elapsed = %lld\n", elapsed);
#endif
return true;
}

View File

@ -57,13 +57,6 @@ public:
memcmp(arr, other.arr, size()));
}
#if 0
T operator*(const Stack<T> &obj)
{
return (obj.arr);
};
#endif
T &operator[](int i)
{
return arr[i];
@ -141,7 +134,7 @@ public:
private:
T *arr;
int p{ -1 };
int p { -1 };
};
}

View File

@ -25,7 +25,7 @@
#include <cstdint>
#include <ratio>
#ifdef _WIN32
#include <intrin.h>
#include <intrin.h>
#endif
namespace stopwatch {
@ -51,7 +51,7 @@ struct rdtscp_clock {
constexpr unsigned int ui = 0;
return time_point(duration((static_cast<std::uint64_t>(ui))));
#endif
}
}
};
// A timer using the specified clock.

View File

@ -16,8 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <QBuffer>
#include <QUuid>
#include <QDataStream>
@ -31,6 +29,8 @@
#include "option.h"
#include "test.h"
#include "config.h"
#ifdef PERFECT_AI_SUPPORT
#include "perfect/perfect.h"
#endif

View File

@ -71,7 +71,7 @@ Thread::Thread(size_t n
/// for its termination. Thread should be already waiting.
Thread::~Thread()
{
{
assert(!searching);
exit = true;
@ -79,13 +79,16 @@ Thread::~Thread()
stdThread.join();
}
/// Thread::clear() reset histories, usually before a new game
void Thread::clear() noexcept
{
// TODO
// TODO: Do nothing
return;
}
/// Thread::start_searching() wakes up the thread that will start the search
void Thread::start_searching()
@ -97,12 +100,12 @@ void Thread::start_searching()
void Thread::pause()
{
// TODO: Can work?
std::lock_guard<std::mutex> lk(mutex);
searching = false;
cv.notify_one(); // Wake up the thread in idle_loop()
}
/// Thread::wait_for_search_finished() blocks on the condition variable
/// until the thread has finished searching.
@ -118,8 +121,6 @@ void Thread::wait_for_search_finished()
void Thread::idle_loop()
{
//bestvalue = lastvalue = VALUE_ZERO;
while (true) {
std::unique_lock<std::mutex> lk(mutex);
searching = false;
@ -132,18 +133,18 @@ void Thread::idle_loop()
lk.unlock();
// TODO: Stockfish doesn't have this
// Note: Stockfish doesn't have this
if (rootPos == nullptr || rootPos->side_to_move() != us) {
continue;
}
clearTT();
clear_tt();
#ifdef PERFECT_AI_SUPPORT
if (gameOptions.getPerfectAiEnabled()) {
bestMove = perfect_search();
assert(bestMove != MOVE_NONE);
strCommand = nextMove();
strCommand = next_move();
if (strCommand != "" && strCommand != "error!") {
emitCommand();
}
@ -165,7 +166,7 @@ void Thread::idle_loop()
strCommand = "draw";
emitCommand();
} else {
strCommand = nextMove();
strCommand = next_move();
if (strCommand != "" && strCommand != "error!") {
emitCommand();
}
@ -330,11 +331,11 @@ void Thread::analyze(Color c)
}
if (lv < -VALUE_EACH_PIECE && v == 0) {
cout << strThem << " made a bad move, " << strUs << "pulled back the balance of power!" << endl;
cout << strThem << " made a bad move, " << strUs << " pulled back the balance of power!" << endl;
}
if (lv < 0 && v > 0) {
cout << strThem << " made a bad move, " << strUs << "reversed the situation!" << endl;
cout << strThem << " made a bad move, " << strUs << " reversed the situation!" << endl;
}
if (lv == 0 && v > VALUE_EACH_PIECE) {
@ -342,15 +343,15 @@ void Thread::analyze(Color c)
}
if (lv > VALUE_EACH_PIECE && v == 0) {
cout << strThem << "Good move, pulled back the balance of power" << endl;
cout << strThem << "made a good move, pulled back the balance of power" << endl;
}
if (lv > 0 && v < 0) {
cout << strThem << "Good move, reversed the situation!" << endl;
cout << strThem << "made a good move, reversed the situation!" << endl;
}
if (lv == 0 && v < -VALUE_EACH_PIECE) {
cout << strThem << "made a good move!" << endl;
cout << strThem << " made a good move!" << endl;
}
if (lv != v) {
@ -410,12 +411,12 @@ out:
cout << endl << endl;
}
Depth Thread::getDepth()
Depth Thread::get_depth()
{
return Mills::getSearchDepth(rootPos);
return Mills::get_search_depth(rootPos);
}
void Thread::clearTT()
void Thread::clear_tt()
{
if (strcmp(rule.name, rule.name) != 0) {
#ifdef TRANSPOSITION_TABLE_ENABLE
@ -424,7 +425,7 @@ void Thread::clearTT()
}
}
string Thread::nextMove()
string Thread::next_move()
{
#ifdef ENDGAME_LEARNING
// Check if very weak
@ -457,12 +458,6 @@ string Thread::nextMove()
#endif // TRANSPOSITION_TABLE_DEBUG
#endif // TRANSPOSITION_TABLE_ENABLE
#if 0
if (foundBest == false) {
loggerDebug("Warning: Best Move NOT Found\n");
}
#endif
return UCI::move(bestMove);
}
@ -525,7 +520,7 @@ void ThreadPool::set(size_t requested)
clear();
#ifdef TRANSPOSITION_TABLE_ENABLE
// Reallocate the hash with the new threadpool size
// Reallocate the hash with the new thread pool size
TT.resize(size_t(Options["Hash"]));
#endif
@ -560,8 +555,6 @@ void ThreadPool::start_thinking(Position *pos, bool ponderMode)
// setupStates->back() later. The rootState is per thread, earlier states are shared
// since they are read-only.
for (Thread *th : *this) {
// TODO
//th->rootPos->set(pos->fen(), &setupStates->back(), th);
th->rootPos = pos;
}

View File

@ -39,7 +39,7 @@
/// per-thread pawn and material hash tables so that once we get a
/// pointer to an entry its life time is unlimited and we don't have
/// to care about someone changing the entry under our feet.
class Thread
class Thread
#ifdef QT_GUI_LIB
: public QObject
#endif
@ -74,9 +74,9 @@ public:
void setAi(Position *p);
void setAi(Position *p, int time);
void clearTT();
string nextMove();
Depth getDepth();
void clear_tt();
string next_move();
Depth get_depth();
int getTimeLimit() const
{
@ -104,15 +104,15 @@ public:
#ifdef TRANSPOSITION_TABLE_ENABLE
#ifdef TRANSPOSITION_TABLE_DEBUG
size_t tteCount{ 0 };
size_t ttHitCount{ 0 };
size_t ttMissCount{ 0 };
size_t ttInsertNewCount{ 0 };
size_t ttAddrHitCount{ 0 };
size_t ttReplaceCozDepthCount{ 0 };
size_t ttReplaceCozHashCount{ 0 };
#endif
#endif
size_t tteCount { 0 };
size_t ttHitCount { 0 };
size_t ttMissCount { 0 };
size_t ttInsertNewCount { 0 };
size_t ttAddrHitCount { 0 };
size_t ttReplaceCozDepthCount { 0 };
size_t ttReplaceCozHashCount { 0 };
#endif // TRANSPOSITION_TABLE_DEBUG
#endif // TRANSPOSITION_TABLE_ENABLE
public:
Depth originDepth { 0 };
@ -164,7 +164,7 @@ struct ThreadPool : public std::vector<Thread *>
void clear();
void set(size_t);
MainThread *main() const
MainThread *main() const
{
return static_cast<MainThread *>(front());
}

View File

@ -19,6 +19,7 @@
#include "tt.h"
#ifdef TRANSPOSITION_TABLE_ENABLE
static constexpr int TRANSPOSITION_TABLE_SIZE = 0x1000000; // 8-128M:102s, 4-64M:93s 2-32M:91s 1-16M: 冲突
HashMap<Key, TTEntry> TT(TRANSPOSITION_TABLE_SIZE);
@ -66,7 +67,7 @@ Value TranspositionTable::probe(const Key &key,
break;
case BOUND_UPPER:
if (tte.value8 <= alpha) {
return alpha; // TODO: https://github.com/calcitem/Sanmill/issues/25
return alpha;
}
break;
case BOUND_LOWER:
@ -106,7 +107,6 @@ int TranspositionTable::save(const Value &value,
#endif // TT_MOVE_ENABLE
)
{
//hashMapMutex.lock();
TTEntry tte {};
if (search(key, tte)) {

View File

@ -28,10 +28,10 @@ using namespace CTSL;
/// TTEntry struct is the 4 bytes transposition table entry, defined as below:
///
/// value 8 bit
/// depth 8 bit
/// type 8 bit
/// age 8 bit
/// value 8 bit
/// depth 8 bit
/// bound type 8 bit
/// age 8 bit
struct TTEntry
{
@ -76,6 +76,7 @@ class TranspositionTable
{
public:
static bool search(const Key &key, TTEntry &tte);
static Value probe(const Key &key,
const Depth &depth,
const Value &alpha,

View File

@ -115,8 +115,6 @@ typedef uint32_t Bitboard;
constexpr int MAX_MOVES = 64;
constexpr int MAX_PLY = 48;
enum Move : int32_t
{
MOVE_NONE,
@ -145,20 +143,20 @@ enum class Phase : uint16_t
none,
ready,
placing, // Placing men on vacant points
moving, // Moving men to adjacent points or
moving, // Moving men to adjacent points or
// (optional) Moving men to any vacant point when the player has been reduced to three men
gameOver
};
// enum class that represents an action that one player can take when it's
// his turn at the board. The can be on of the following:
// - select a piece on the board;
// - place a piece on the board;
// - move a piece on the board:
// - slide a piece between two adjacent locations;
// - 'jump' a piece to any empty location if the player has less than
// - Select a piece on the board;
// - Place a piece on the board;
// - Move a piece on the board:
// - Slide a piece between two adjacent locations;
// - 'Jump' a piece to any empty location if the player has less than
// three pieces and mayFly is |true|;
// - remove an opponent's piece after successfully closing a mill;
// - Remove an opponent's piece after successfully closing a mill.
enum class Action : uint16_t
{
none,
@ -170,12 +168,12 @@ enum class Action : uint16_t
enum class GameOverReason
{
noReason,
// A player wins by reducing the opponent to two pieces
// (where they could no longer form mills and thus be unable to win)
loseReasonlessThanThree,
// A player wins by leaving them without a legal move.
// A player wins by leaving them without a legal move.
loseReasonNoWay,
loseReasonBoardIsFull,
@ -222,7 +220,6 @@ enum Value : int8_t
VALUE_PLACING_WINDOW = VALUE_EACH_PIECE_PLACING_NEEDREMOVE + (VALUE_EACH_PIECE_ONBOARD - VALUE_EACH_PIECE_INHAND) + 1,
VALUE_MOVING_WINDOW = VALUE_EACH_PIECE_MOVING_NEEDREMOVE + 1,
};
enum Rating : int8_t
@ -307,7 +304,7 @@ using Depth = int8_t;
enum : int
{
DEPTH_NONE = 0, // TODO: -6,
DEPTH_NONE = 0,
DEPTH_OFFSET = DEPTH_NONE
};
@ -363,19 +360,6 @@ enum Rank : int
RANK_1 = 1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB = 8
};
#if 0
/// Score enum stores a middlegame and an endgame value in a single integer (enum).
/// The least significant 16 bits are used to store the middlegame value and the
/// upper 16 bits are used to store the endgame value. We have to take care to
/// avoid left-shifting a signed int to avoid undefined behavior.
enum Score : int
{
SCORE_ZERO
};
#endif
#define ENABLE_BASE_OPERATORS_ON(T) \
constexpr T operator+(T d1, int d2) { return T(int(d1) + d2); } \
constexpr T operator-(T d1, int d2) { return T(int(d1) - d2); } \
@ -414,11 +398,6 @@ constexpr Color operator~(Color c)
return Color(c ^ 3); // Toggle color
}
// constexpr Piece operator~(Piece p)
// {
// return Piece(p ^ 8); // Swap color of piece
// }
constexpr Square make_square(File f, Rank r)
{
return Square((f << 3) + r - 1);
@ -466,7 +445,7 @@ constexpr PieceType type_of(Piece pc)
constexpr bool is_ok(Square s)
{
return s == SQ_NONE || (s >= SQ_BEGIN && s < SQ_END); // TODO: SQ_NONE?
return s == SQ_NONE || (s >= SQ_BEGIN && s < SQ_END);
}
constexpr File file_of(Square s)
@ -495,14 +474,6 @@ constexpr Square to_sq(Move m)
return Square(m & 0x00FF);
}
constexpr int from_to(Move m)
{
#if 0
return m & 0xFFF;
#endif
return m & 0xFFFF; // TODO
}
constexpr MoveType type_of(Move m)
{
if (m < 0) {

View File

@ -73,7 +73,7 @@ void position(Position *pos, istringstream &is)
repetition = 0;
posKeyHistory.clear();
pos->set(fen, Threads.main());
// Parse move list (if any)

View File

@ -31,7 +31,8 @@ namespace UCI {
class Option;
/// Custom comparator because UCI options should be case insensitive
struct CaseInsensitiveLess {
struct CaseInsensitiveLess
{
bool operator() (const std::string&, const std::string&) const;
};
@ -39,8 +40,8 @@ struct CaseInsensitiveLess {
typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap;
/// Option class implements an option as defined by UCI protocol
class Option {
class Option
{
typedef void (*OnChange)(const Option&);
public:

View File

@ -56,7 +56,6 @@ Java_com_calcitem_sanmill_MillEngine_startup(JNIEnv *env, jobject obj)
pthread_join(thread_id, NULL);
}
// getInstance() 有并发问题,这里首先主动建立实例,避免后续创建重复
CommandChannel::getInstance();
usleep(10);
@ -83,7 +82,6 @@ Java_com_calcitem_sanmill_MillEngine_send(JNIEnv *env, jobject, jstring command)
env->ReleaseStringUTFChars(command, pCommand);
return success ? 0 : -1;
}

View File

@ -408,7 +408,7 @@
"@hasBannedLocations": {
"description": "Mark and delay removing pieces"
},
"hasBannedLocations_Detail": "In the placing phase, the points of removed pieces will no longer be able to place. ",
"hasBannedLocations_Detail": "In the placing phase, the points of removed pieces will no longer be able to place.",
"@hasBannedLocations_Detail": {
"description": "In the placing phase, the points of removed pieces will no longer be able to place unless moving phase is entered."
},

View File

@ -27,18 +27,13 @@ import 'package:path_provider/path_provider.dart';
import 'package:sanmill/generated/l10n.dart';
import 'package:sanmill/style/app_theme.dart';
import 'package:sanmill/widgets/navigation_home_screen.dart';
//import 'package:stack_trace/stack_trace.dart';
//import 'common/config.dart';
import 'services/audios.dart';
//import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async {
var catcher = Catcher(rootWidget: SanmillApp(), ensureInitialized: true);
//DateTime now = DateTime.now();
//String formattedDate = DateFormat('yyyy-MM-dd_kk-mm').format(now);
String externalDirStr;
try {
Directory? externalDir = await getExternalStorageDirectory();
@ -55,16 +50,6 @@ Future<void> main() async {
print("ExternalStorageDirectory: " + externalDirStr);
String recipients = "calcitem@outlook.com";
/// Create catcher configuration.
/// Debug configuration with dialog report mode and console handler.
/// It will show dialog and once user accepts it, error will be shown
/// in console.
//CatcherOptions debugOptions = CatcherOptions(
// PageReportMode(showStackTrace: true), [ConsoleHandler()]);
//SentryOptions sopt = new SentryOptions();
//sopt.dsn =
// "https://62c565096ba146a6b70bc57dbb72386c@o525088.ingest.sentry.io/5638585";
CatcherOptions debugOptions =
CatcherOptions(PageReportMode(showStackTrace: true), [
ConsoleHandler(),
@ -121,9 +106,6 @@ class SanmillApp extends StatefulWidget {
class _SanmillAppState extends State<SanmillApp> {
@override
void initState() {
//Chain.capture(() {
// Config.loadSettings();
//});
super.initState();
}

View File

@ -19,6 +19,7 @@
import 'position.dart';
import 'types.dart';
// TODO
class GameRecorder {
int? halfMove, fullMove;
String? lastPositionWithRemove = "";

View File

@ -19,8 +19,8 @@
class Rule {
String name = "Nine Men's Morris";
String description = "";
int piecesCount = 9; // 9 or 12
int piecesAtLeastCount = 3; // Default is 3
int piecesCount = 9;
int piecesAtLeastCount = 3;
bool hasDiagonalLines = false;
bool hasBannedLocations = false;
bool isDefenderMoveFirst = false;

View File

@ -42,7 +42,7 @@ class Move {
MoveType type = MoveType.none;
// Used to restore fen step conter when regreting
// Used to restore fen step counter when undoing move
String counterMarks = "";
parse() {

View File

@ -50,7 +50,7 @@ class _DrawerUserControllerState extends State<DrawerUserController>
late AnimationController iconAnimationController;
late AnimationController animationController;
double scrolloffset = 0.0;
double scrollOffset = 0.0;
@override
void initState() {
@ -71,9 +71,9 @@ class _DrawerUserControllerState extends State<DrawerUserController>
scrollController
..addListener(() {
if (scrollController.offset <= 0) {
if (scrolloffset != 1.0) {
if (scrollOffset != 1.0) {
setState(() {
scrolloffset = 1.0;
scrollOffset = 1.0;
try {
widget.drawerIsOpen!(true);
} catch (_) {}
@ -89,9 +89,9 @@ class _DrawerUserControllerState extends State<DrawerUserController>
duration: const Duration(milliseconds: 0),
curve: Curves.fastOutSlowIn);
} else {
if (scrolloffset != 0.0) {
if (scrollOffset != 0.0) {
setState(() {
scrolloffset = 0.0;
scrollOffset = 0.0;
try {
widget.drawerIsOpen!(false);
} catch (_) {}
@ -164,13 +164,13 @@ class _DrawerUserControllerState extends State<DrawerUserController>
// for example scrolloffset == 1
// means drawer is close we just allow touching all widget.screen View
IgnorePointer(
ignoring: scrolloffset == 1 || false,
ignoring: scrollOffset == 1 || false,
child: widget.screenView,
),
// alternative touch(user Interface) for widget.screen,
// for example, drawer is close we need to
// tap on a few home screen area and close the drawer
if (scrolloffset == 1.0)
if (scrollOffset == 1.0)
InkWell(
onTap: () {
onDrawerClick();
@ -237,7 +237,7 @@ class _DrawerUserControllerState extends State<DrawerUserController>
}
void onDrawerClick() {
// if scrollcontroller.offset != 0.0
// if scrollController.offset != 0.0
// then we set to closed the drawer(with animation to offset zero position)
// if is not 1 then open the drawer
scrollController.animateTo(

View File

@ -26,8 +26,8 @@ BoardItem::BoardItem(QGraphicsItem *parent) :
{
Q_UNUSED(parent)
// Put center of the board in the center of the scene
setPos(0, 0);
// Put center of the board in the center of the scene
setPos(0, 0);
// Initialize 24 points
for (int r = 0; r < FILE_NB; r++) {

View File

@ -51,10 +51,12 @@ private slots:
void displayError(QAbstractSocket::SocketError socketError);
void enableGetActionButton();
void sessionOpened();
void setPort(uint16_t p) noexcept
{
this->port = p;
}
uint16_t getPort() noexcept
{
return port;

View File

@ -759,10 +759,6 @@ void Game::updateTime()
time_t *ourSeconds = &elapsedSeconds[sideToMove];
time_t theirSeconds = elapsedSeconds[~sideToMove];
// if (!(phase == Phase::placing || phase == Phase::moving)) {
// return;
// }
currentTime = time(NULL);
if (timePoint >= *ourSeconds) {
@ -810,8 +806,6 @@ void Game::timerEvent(QTimerEvent *event)
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
//QMessageBox::about(NULL, "游戏结果", message);
#ifndef DONOT_PLAY_WIN_SOUND
playSound(GameSound::win, winner);
#endif
@ -977,7 +971,7 @@ bool Game::actionPiece(QPointF p)
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
// Insert the new chess score line into listmodel
// Insert the new chess score line into list model
currentRow = manualListModel.rowCount() - 1;
int k = 0;
@ -1028,7 +1022,6 @@ bool Game::actionPiece(QPointF p)
return result;
}
bool Game::resign()
{
const bool result = position.resign(position.sideToMove);
@ -1037,7 +1030,7 @@ bool Game::resign()
return false;
}
// Insert the new record line into listmodel
// Insert the new record line into list model
currentRow = manualListModel.rowCount() - 1;
int k = 0;
@ -1087,7 +1080,6 @@ bool Game::command(const string &cmd, bool update /* = true */)
default:
break;
}
//#endif
if (position.get_phase() == Phase::ready) {
gameStart();
@ -1144,7 +1136,7 @@ bool Game::command(const string &cmd, bool update /* = true */)
if (r++ > currentRow)
break;
}
// Insert the new chess score line into listmodel
// Insert the new chess score line into list model
while (i != move_hostory()->end()) {
manualListModel.insertRow(++currentRow);
manualListModel.setData(manualListModel.index(currentRow), (*i++).c_str());

View File

@ -93,7 +93,7 @@ bool GameScene::pos2polar(QPointF pos, File &file, Rank &rank)
return board->pos2polar(pos, file, rank);
}
void GameScene::setDiagonal(bool arg /*= true*/)
void GameScene::setDiagonal(bool arg)
{
if (board) {
board->setDiagonal(arg);

View File

@ -135,7 +135,7 @@ void MillGameWindow::closeEvent(QCloseEvent *event)
bool MillGameWindow::eventFilter(QObject *watched, QEvent *event)
{
// This function is overridded just to make the rules menu (dynamic) display prompts
// This function is overridden just to make the rules menu (dynamic) display prompts
if (watched == ui.menu_R &&
event->type() == QEvent::ToolTip) {
const auto *he = dynamic_cast <QHelpEvent *> (event);
@ -644,7 +644,6 @@ void MillGameWindow::on_actionOpen_O_triggered()
// Files larger than 1MB are not supported
if (file.size() > 0x100000) {
// 定义新对话框
QMessageBox msgBox(QMessageBox::Warning,
tr("The file is too large"), tr("Files larger than 1MB are not supported"), QMessageBox::Ok);
msgBox.exec();