parent
f2afddc415
commit
36af532a41
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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] = {
|
||||
{
|
||||
"成三棋", // 成三棋
|
||||
|
|
17
src/rule.h
17
src/rule.h
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
28
src/thread.h
28
src/thread.h
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
9
src/tt.h
9
src/tt.h
|
@ -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,
|
||||
|
|
51
src/types.h
51
src/types.h
|
@ -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) {
|
||||
|
|
|
@ -73,7 +73,7 @@ void position(Position *pos, istringstream &is)
|
|||
|
||||
repetition = 0;
|
||||
posKeyHistory.clear();
|
||||
|
||||
|
||||
pos->set(fen, Threads.main());
|
||||
|
||||
// Parse move list (if any)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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."
|
||||
},
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import 'position.dart';
|
||||
import 'types.dart';
|
||||
|
||||
// TODO
|
||||
class GameRecorder {
|
||||
int? halfMove, fullMove;
|
||||
String? lastPositionWithRemove = "";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue