GithubHelp home page GithubHelp logo

pleco-rs / pleco Goto Github PK

View Code? Open in Web Editor NEW
354.0 11.0 37.0 1.54 MB

A Rust-based re-write of the Stockfish Chess Engine

Home Page: https://crates.io/crates/pleco

License: GNU General Public License v3.0

Rust 100.00%
chess rust engine library crates-io uci ai bot chess-engine pleco

pleco's Introduction

Pleco Pleco

Build License Commits

Overview

Pleco is a chess Engine & Library derived from Stockfish, written entirely in Rust.

This project is split into two crates, pleco, which contains the library functionality, and pleco_engine, which contains the UCI (Universal Chess Interface) compatible engine.

The overall goal for this project is to utilize the efficiency of Rust to create a Chess AI matching the speed of modern chess engines. For the engine, the majority of the code is a direct port of Stockfish's C++ code. See their website for more information about the engine. As such, the credit for all of the advanced algorithms used for searching, evaluation, and many others, go directly to the maintainers and authors of Stockfish. This project is for speed comparisons between the two languages, as well as for educational purposes.

Standalone Installation and Use

To use pleco as an executable, please navigate to here and read the README.md.

Using Pleco as a Library

To use pleco inside your own Rust projects, Pleco.rs is available as a library on crates.io. Simply include the current version in your Cargo.toml:

[dependencies]
pleco = "x.x.x"

And add the following to a main.rs or lib.rs:

extern crate pleco;

As of version 0.5.0, the pleco library is available on all three Rust channels (stable, beta, nightly).

Basic Usage

Setting up a board position is extremely simple.

use pleco::{Board,Player,PieceType};

let board = Board::start_pos();
assert_eq!(board.count_piece(Player::White,PieceType::P), 8);
assert_eq!(&board.fen(),"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");

Creating a board from a Position

A Board can be created with any valid chess position using a valid FEN (Forsyth-Edwards Notation) String. Check out the Wikipedia article for more information on FEN Strings and their format.

let board = Board::from_fen("rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2").unwrap();

Applying and Generating Moves

Moves are represented with a BitMove structure. They must be generated by a Board object directly, to be considered a valid move. Using Board::generate_moves() will generate all legal BitMoves of the current position for the current player.

use pleco::{Board,BitMove};

let mut board = Board::start_pos(); // create a board of the starting position
let moves = board.generate_moves(); // generate all possible legal moves
board.apply_move(moves[0]);
assert_eq!(board.moves_played(), 1);

We can ask the Board to apply a move to itself from a string. This string must follow the format of a standard UCI Move, in the format [src_sq][dst_sq][promo]. E.g., moving a piece from A1 to B3 would have a uci string of "a1b3", while promoting a pawn would look something like "e7e81". If the board is supplied a UCI move that is either incorrectly formatted or illegal, false shall be returned.

let mut board = Board::start_pos(); // create a board of the starting position
let success = board.apply_uci_move("e7e8q"); // apply a move where piece on e7 -> eq, promotes to queen
assert!(!success); // Wrong, not a valid move for the starting position

Undoing Moves

We can revert to the previous chessboard state with a simple Board::undo_move()

let mut board = Board::start_pos();
board.apply_uci_move("e2e4"); // A very good starting move, might I say
assert_eq!(board.moves_played(),1);
board.undo_move();
assert_eq!(board.moves_played(),0);

For more information about pleco as a library, see the pleco README.md.

Contributing

Any and all contributions are welcome! Open up a PR to contribute some improvements. Look at the Issues tab to see what needs some help.

License

The Pleco Engine is distributed under the GNU General Public License version 3 (or any later version at your option). See LICENSE for full details.

The Pleco crate (the library functionality) is distributed under the terms of the MIT license. See pleco/LICENSE for details.

Opening a pull requests is assumed to signal agreement with these licensing terms.

pleco's People

Contributors

brianch avatar chase-manning avatar definitelynobody avatar kianmeng avatar marcustamvoes avatar npn avatar nvzqz avatar serprex avatar sfleischman105 avatar xxxxxion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pleco's Issues

End-Game Tablebases / Specialized Evaluation

This is probably the weakest part of the engine right now: playing well into the end-game.

Porting over Stockfish End of Game table bases would fix this, and seems pretty easy to do.

Concerns about this crate

I'm currently looking around for a chess AI written in rust. I found Pleco, and it seems like a neat project, it's only one of a handful of crates I've seen that actually implement a chess AI.

However- I have a lot of concerns about this crate.
For starters, the history. @chase-manning made a new version of the crate (Tanton, see #140), but then shortly after seems to be the owner of Pleco. All they've done is various updates to CI and fixing warnings, which is fair enough- but nothing really substantial.

Then, there's the code.
Oh boy, there's a lot of undefined behavior and unsafe code. It's honestly quite daunting to look over it all- so specifically, I'll focus on src/movepick/mod.rs, as it's generally pretty simple.
Let's look at the struct definition for MovePicker:

pub struct MovePicker {
    pick: Pick,
    board: *const Board,
    moves: ScoringMoveList,
    depth: i16,
    ttm: BitMove,
    killers: [BitMove; 2],
    cm: BitMove,
    recapture_sq: SQ,
    threshold: i32,
    main_hist: *const ButterflyHistory,
    capture_hist: *const CapturePieceToHistory,
    cont_hist: *const [*const PieceToHistory; 4],
    cur_ptr: *mut ScoringMove,
    end_ptr: *mut ScoringMove,
    end_bad_captures: *mut ScoringMove,
}

That's.. a lot of pointers. I can't comment on why they're there, but I can speculate.
In MovePicker::new, there are a bunch of references passed as arguments:

    pub fn main_search(
        board: &Board,
        depth: i16,
        main_hist: &ButterflyHistory,
        // there are a lot more
    ) -> Self

..and all of them get stored as a pointer. If I had to guess, whoever wrote the code for MovePicker did not want to deal with lifetimes. Or is a C programmer who uses Rust as if it were C.
At the least this function should be unsafe. What happens if someone passes a Board that goes out of scope?
Then there's this (also in new):

        MovePicker {
            pick,
            board: &*board,
            // more fields
            recapture_sq: unsafe { mem::MaybeUninit::uninit().assume_init() },
            threshold: unsafe { mem::MaybeUninit::uninit().assume_init() },
            /// more fields
        }

Those mem::MaybeUninit::uninit().assume_init()? Insta UB. There's a reason the compiler doesn't let you use uninitialized values- when you create a value on the stack and don't initialize it, the function call will be at the deepest the stack has ever been at best, or point to some random garbage that used to be there. That's assuming that rustc will behave like a C compiler or not put variables into registers. In any case, these can create invalid values (imagine a bool that is not true or false) which can cause a lot of problems.
Further down in the code, there's a similar thing with mem::zeroed!

No comments about why these may be safe by the way!
All of this kind of code is repeated throughout the codebase- it really calls into question the mindset of the person who wrote it.

Potential SIMD inside a Transposition Table

Marking this as a long-term TODO, as the SIMD features required for this have not yet stabilized in rust,

Preface

Currently, the Transposition Table (TT) works with by hashing a Zobrist key to a Cluster. Each Cluster contains 3 possible Entrys, where each one is likely to correlate to a specific position:

pub struct Cluster {
    pub entry: [Entry; CLUSTER_SIZE],
    pub padding: [u8; 2],
}

pub struct Entry {
    pub partial_key: u16,
    pub best_move: BitMove, // What was the best move found here?
    pub score: i16, // What was the Score of this node?
    pub eval: i16, // What is the evaluation of this node
    pub depth: u8, // How deep was this Score Found?
    pub time_node_bound: NodeTypeTimeBound,
}

The key for the TT (the Zobrist Hash) is a u64 corresponding to a position. This hash is not guaranteed to be unique to a specific position, so there is always a risk of collisions / overlap in keys.

We determine which Cluster a hash might lie in by taking the lower x bits of the hash as the index. A TT is always guaranteed to contain 2^x number of Clusters inside of itself, so we can effectively use the lower bits as an index. From there, we determine the Entry a key might lie in by matching the upper 16 bits to the partial_key in each entry.

SIMD

While this is an O(n) operation, we have to search 3 Entrys inside each cluster for a possible match. While this is still a very inexpensive operation, I think it'd be worth the time to explore SIMD operations to both

  1. Increase the Cluster Search speed from O(n) to O(1)
  2. Increase the Cluster size to fit addition Entrys with the O(1) search time.

`Board::get_piece_locations()` causes stack overflow

Running Board::get_piece_locations() causes a stack overflow when run.
This is the code that causes this bug for me:
let board = Board::start_pos()
for (sq, piece) in board.get_piece_locations() {
debug!("{} {:?}", sq, piece); }`

Simplifying PieceLocations

Piece Locations is now a structure of [u8; 32], with each square (consisting of a Piece and a Color) represented as 4 bits.

This makes it very compact, but may provide unnecessary overhead due to needing to mask and shift values. A possible solution is accept wasted space, and use an array of [u8; 64] to represent each square

Compile `pleco_engine` with stable Rust

The following features need to be stabilized before pleco_engine can compile on stable:

For benchmarking:

  • test (Switched to Criterion with #92 )

Dependency stabilization

  • lazy_static nightly (no current tracking issue)
  • pleco needs to be usable on stable as defined by #76 .

Midgame centipawn conversion is off

There's likely a typo in the conversion of values to centipawns.
Line 76 has self.mg() / PAWN_EG, where it should likely be self.mg() / PAWN_MG.

/// Gives the value of the score in centi-pawns
pub fn centipawns(self) -> (f64, f64) {
let mg: f64 = self.mg() as f64 / PAWN_EG as f64;
let eg: f64 = self.eg() as f64 / PAWN_EG as f64;
(mg, eg)
}

Reduce unsafe code

There are mutliple uses of unsafe that can be either replaced with safe code or with an external crate. I propose using this issue to discuss these cases and then document in the code why each unsafe is fine. This makes code review much easier.

  • Transmutes to enums. Totally fine although the compiler generates the same assembly for safe match statements.
  • Custom Arc without weak counter from servo_arc. The discussion to include this in std died here. Why not use the crate? The currently published version has possible UB servo/servo#26358
  • Custom TranspositionTable that allows to trigger undefined behaviour from safe code (if I understand the code correctly):
let tt = TranspositionTable::new_num_entries(40000);
let prng = PRNG::init(932445561);
let key: u64 = prng.rand();
let (found1, entry1): (bool, &mut Entry) = tt.probe(key);
let (found2, entry2) = tt.probe(key); // second mutable reference to the same object -> UB

I did not look into the usecases yet. There are probably alternatives available in the ecosystem.

Implement "QuietChecks" move-generation option

Currently, there is one type of GenTypes option that isn't yet fully implemented in MoveGen::generate(), being GenTypes::QuietChecks. This move generation should return a list of all non-captures & knight promotions that do give check.

It should be noted that the Board cannot be in check when this generation option is supplied.

Document and Implement stdin Functionality

Pleco.rs works primarily with the command line, this functionality needs to be expanded and documented.

  1. Complete implementation UCI commands
  2. Document UCI commads
  3. Create and document other functionality

Re-do Castling rights as a structure

Allow Castling rights to be a struct containing a u8, or alias a type as a u8.

Should take away from some of the confusion surrounding castling rights and implementing move-generation concerning castling in the future

Doesn't Compile due to const_fn feature having been removed

It looks like compilation (on Nightly, release) is failing due to:


error[E0557]: feature has been removed
  --> pleco_engine\src/lib.rs:24:12
   |
24 | #![feature(const_fn)]
   |            ^^^^^^^^ feature has been removed
   |
   = note: split into finer-grained feature gates

BitMove from string

Noticed there is no real way to de serialize a bitmove without using the raw data. Would be nice if we could use the stringified version

Switch to Criterion for Benchmarking.

Right now, we use the standard libraries benchmarking tool for benchmarking.

Despite it's easy of use, there are a couple drawbacks for using it:

  • No customization on the number of runs
  • Output is limited to a number + estimated degree of confidence

It would be beneficial to switch the benchmarks to Criterion.rs, to get more detailed analysis of the benchmarks, alongside additional benchmark customization.

Can't run Pleco

I try to run the pleco binary, but nothing happens. Ever since this commit

57250ef

the main.rs function has been empty. How am I supposed to run this?

Unable to compile with Rust nightly

System Version: macOS 10.14.6 (18G103)
Kernel Version: Darwin 18.7.0
rustc 1.41.0-nightly (25d8a9494 2019-11-29)
Git: master, 0.1.5, 0.1.6

error[E0635]: unknown feature `const_slice_len`
  --> pleco/src/lib.rs:77:42
   |
77 | #![cfg_attr(feature = "nightly", feature(const_slice_len))]
   |                                          ^^^^^^^^^^^^^^^

Universal Chess Interface support and associated `UCISearcher` Trait.

In order to be considered a modern chess engine, Pleco needs to support the Universal Chess Interface (shorthand is UCI) inside of both the engine, as well as the primary searcher. More information about UCI can be found here.

There are four parts I would like to outline for implementing this.

1) main.rs args

When given the command "uci" as an argument (or stdin after load), Engine::uci(...) should be called, letting the Engine handle it from there.

2) Engine

The Engine must contain a Engine::uci(...) method to allow for communication to and from the GUI. Communication uses stdin and stdout to pass commands back and forth. The command "isready" should allow the engine the opportunity to get both a UCI compatible Searcher (more on this later) and a Board object ready. The GUI can send in options to the Engine before the game actually begins, starting with the "setoption" command. All commands leading up to "go" (which starts the game) can be implemented with a simple IO loop.

3) Mid Game Message sending to / from UCI Searcher

When the Searcher is in the midst of searching, the Engine must act as an intermediary between the GUI and the Searcher. Mid-search, the GUI should only be able to send the command "stop" to the Searcher, which should within reasonable time stop the Search and return the best move found so good.

Some problems that need to be dealt with in concern of this:

  • How do we allow stdin to be scanned in a separate thread, but without impacting search performance?
  • What type of structure do we need to pass into the UCI Searcher that allows for checking when to stop?

Furthermore, the Engine needs to be able to do the opposite: Await information from the UCI Searcher and relay that information to the GUI.

4) Implementing the UCISearcher Trait

The UCISearcher Trait should mark specific Searchers as UCI compatible. Currently, the UCISearcher implementation is the following:

pub trait UCISearcher: Searcher {
   fn uci_move(board: Board, timer: &Timer, rx: Arc<Mutex<Option<GuiToEngine>>>) -> BitMove where Self: Sized;
}

Some notes on this:

  • Receiver needs to be solidified in uci_move as determined by item 3.
  • A Sender needs to be given in somewhere, to allow the chess board to communicate back.
  • `fn configuration()' or similar function should allow easily setting up options.

Ready Pleco for Deployment in CCRL (Computer Chess Rating Lists)

To get a rough estimate about how Pleco performs against other engines, it needs to be submitted in the Computer Chess Rating System.

However, a few things need to be done before that can happen.

  • Finish the uci command line interface to allow for the full range of commands.
  • Finish the LazySMP Searcher to use the TranspositionTable correctly, and allow the table to be resized and cleared.
  • Allow parsing of the Board and Limits prior to the start of searching
  • Allow for proper time management based on the UCI protocol
  • Test the current TimeManagement struct for accuracy & parsing errors.
  • Submit to CCRL for engine rating

Other things that would be of use:

  1. Implement use of opening Board bases, SysgzyBases I believe they are called.
  2. Allow for endgame board tables.

can't compile E0554

tried to build engine by:

$ cargo build --release
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   /media/demo/1a16bb7d-7776-4545-b1d6-7f7ec43d7e64/Pleco/pleco/Cargo.toml
workspace: /media/demo/1a16bb7d-7776-4545-b1d6-7f7ec43d7e64/Pleco/Cargo.toml
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   /media/demo/1a16bb7d-7776-4545-b1d6-7f7ec43d7e64/Pleco/pleco_engine/Cargo.toml
workspace: /media/demo/1a16bb7d-7776-4545-b1d6-7f7ec43d7e64/Pleco/Cargo.toml
   Compiling prefetch v0.2.0
   Compiling crossbeam-utils v0.8.1
   Compiling memoffset v0.6.1
   Compiling num-traits v0.2.14
error[E0554]: `#![feature]` may not be used on the stable release channel
  --> /home/demo/.cargo/registry/src/github.com-1ecc6299db9ec823/prefetch-0.2.0/src/lib.rs:18:1
   |
18 | #![feature(link_llvm_intrinsics)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0554`.
error: could not compile `prefetch`

How to solve this?

Changing Board State to a Pointer to the top of a linked List, Rather than a Vector

Current Board State is represented as a pub state: BoardState Inside Board, with a Vec<BoardState> as a way to hold the past BoardStates.

This works alright, but the Board has to copy MoveStates to and from the Board Structure when applying / undoing a move. Making the board have a reference to the board state, rather than containing it's entire struct would be ideal.

Move generator benchmarks

Hi! I'm planning on writing a chess engine in rust to learn the language better and I'm looking for a move generator to use. I'm currently in between Pleco and chess. Do you have any benchmarks on which one is a faster move generator? Thanks in advance!

Publish latest crates for pleco and pleco_engine?

Four years ago on April 29th:

Since that last commit in 2019, there have been 77 commits to the main branch, at least according to git rev-list --count 67d283c9a98c699f681b8153ab156e848575e8ec..main).

Since the original repo has changed ownership, I don't know if the crate publishing permissions have been transferred to the new maintainers. If they have been, would it be possible to publish a new version, even if it's only a patch version of each? This would help the crate seem more actively maintained and possibly encourage more contributions.

How to generate the best possible moves from a given board?

Hi, Im trying to learn Pleco-Rs and i dont know how to generate the best possible move.
For example instead of this :
let moves = board.generate_moves(); // generate all possible legal moves board.apply_move(moves[0]); assert_eq!(board.moves_played(), 1);

to have this
let moves = board.generate_generate_best_moves(); // generate all the best legal moves board.apply_move(moves[0]); assert_eq!(board.moves_played(), 1);

PGN Parser

I feel like this would be a useful thing for a chess library to have. At the bear minimum, we should be able to parse a PGN file and turn it into a Board.

I'm not too great at parsing text/files, so if anyone wants to help with this, I would gladfully mentor.

Give speed comparisons vs Stockfish

The README says "This project is for speed comparisons between the two languages".
Would you please update the README to give some speed comparisons between Pleco and Stockfish?

Improve the Evaluation of a Board

Currently, the evaluation function is very simple. All it does is sum up the value of each piece, look at double'd pawns, and checks for basic king safety.

While this is fast (and simple), evaluation is one of the most important parts of a chess engine. Hell, some engines really primarily on evaluation instead of speed to get high ELO rankings.

Determine the Stage of the Game

In order to evaluate the board, we need to determine the specific stage of the game we're in. For example, in the middle game we certainly need to evaluate the safety of the king in regards to the pawns and other structures around it. The more friendly pieces surrounding the king, the safer it is. However, in the end-game (where there are less than 8 pieces), king safety shouldn't be evaluated by how many pieces are surrounding the king directly.

The first thing that needs to be done is splitting the game into different "stages". These will be represented by a GameStage enum. Secondly, we need to determine which stage the board is in. There is a little unclarity on how we should do this. The number of pieces left in the game should obviously be a large factor in this, but other metrics are needed.

Another unknown, can a board be in multiple stages at once? Can it be in a mix of stages?

Lastly, do we include this in the pleco library? Or do we push this to the pleco_engine library and allow for usage of the TranspositionTable inside of it?

Document functionality of Pleco on the Wiki

Pleco has a ton of features and customization. However, it's not very clear on how to actually incorporate the crate inside of a project.

The Wiki needs to be updated to include at least:

  1. Basic operation and creating boards
  2. Functions available to the board, and when to use each
  3. How to generate moves from the board

Alternate Implementation of Parallel Search Strategy

Currently, all the parallel algorithms implement Principal Variation Splitting (See section on ChessProgramming Wiki) to utilize mutli-core processing. PVS works by searching a set amount of moves sequentially to find an alpha cut-off, and then the remaining nodes are searched in parallel with that alpha cutoff. Can this be done better?

Engine doesn't work in Arena

I tried to use pleco_engine in Arena but it keeps panicking. I'm running it on Debian buster x86-64.

Reproduction steps:

  1. Compile pleco_engine, add engine to Arena, then load it as engine 1
  2. Start engine
  3. Arena doesn't output analysis, and the logs show that it panicked
2021-05-02 15:14:32.208**----------New game---2021-05-02 15:14:32,208 Sun -------------
2021-05-02 15:14:33.370*1*Start calc, move no: 1
2021-05-02 15:14:33.371-->1:ucinewgame
2021-05-02 15:14:33.371-->1:isready
2021-05-02 15:14:33.371<--1:readyok
2021-05-02 15:14:33.378-->1:position startpos moves e2e4
2021-05-02 15:14:33.378-->1:go wtime 300000 btime 300000 winc 0 binc 0
2021-05-02 15:14:33.378<--1:info id 0 start
2021-05-02 15:14:33.378<--1:thread '1' panicked at 'attempted to leave type `movepick::pick::Pick` uninitialized, which is invalid', /home/makoto/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/mod.rs:660:9
2021-05-02 15:14:33.378<--1:stack backtrace:
2021-05-02 15:14:33.379<--1:   0:     0x55fcb6c5c530 - std::backtrace_rs::backtrace::libunwind::trace::hdcf4f90f85129e83
2021-05-02 15:14:33.379<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
2021-05-02 15:14:33.380<--1:   1:     0x55fcb6c5c530 - std::backtrace_rs::backtrace::trace_unsynchronized::h2669e30cb82f6732
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2021-05-02 15:14:33.380<--1:   2:     0x55fcb6c5c530 - std::sys_common::backtrace::_print_fmt::hfbda19e17f6db318
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/sys_common/backtrace.rs:67:5
2021-05-02 15:14:33.380<--1:   3:     0x55fcb6c5c530 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1a8751bf59281272
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/sys_common/backtrace.rs:46:22
2021-05-02 15:14:33.380<--1:   4:     0x55fcb6c1b0ef - core::fmt::write::h7aa6cd0067dca82a
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/core/src/fmt/mod.rs:1094:17
2021-05-02 15:14:33.380<--1:   5:     0x55fcb6c5bd44 - std::io::Write::write_fmt::hd7dd3a1df9b6befb
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/io/mod.rs:1580:15
2021-05-02 15:14:33.380<--1:   6:     0x55fcb6c5b8c5 - std::sys_common::backtrace::_print::h551e9ec8a9fa8106
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/sys_common/backtrace.rs:49:5
2021-05-02 15:14:33.380<--1:   7:     0x55fcb6c5b8c5 - std::sys_common::backtrace::print::ha4b1c5e95fa040b3
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/sys_common/backtrace.rs:36:9
2021-05-02 15:14:33.380<--1:   8:     0x55fcb6c5b8c5 - std::panicking::default_hook::{{closure}}::h0b34c9ab7fb9f857
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/panicking.rs:208:50
2021-05-02 15:14:33.380<--1:   9:     0x55fcb6c5a8bb - std::panicking::default_hook::h3067e8318decd17a
2021-05-02 15:14:33.380<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/panicking.rs:225:9
2021-05-02 15:14:33.380<--1:  10:     0x55fcb6c5a8bb - std::panicking::rust_panic_with_hook::h81b8facc50f34daa
2021-05-02 15:14:33.381<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/panicking.rs:591:17
2021-05-02 15:14:33.381<--1:  11:     0x55fcb6c75910 - std::panicking::begin_panic_handler::{{closure}}::ha376ab85d95a000e
2021-05-02 15:14:33.381<--1:  12:     0x55fcb6c758ac - std::sys_common::backtrace::__rust_end_short_backtrace::h6795c8afdd1a77e6
2021-05-02 15:14:33.382<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/sys_common/backtrace.rs:141:18
2021-05-02 15:14:33.382<--1:  13:     0x55fcb6c7585d - rust_begin_unwind
2021-05-02 15:14:33.382<--1:BytesRead > 0
2021-05-02 15:14:33.382<--1:n > 0
2021-05-02 15:14:33.382<--1:-- LiesThread.Execute terminated --
2021-05-02 15:14:33.383<--1::5
2021-05-02 15:14:33.383<--1:  14:     0x55fcb6c131f0 - core::panicking::panic_fmt::hbe99dddd3092ba3c
2021-05-02 15:14:33.383<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/core/src/panicking.rs:92:14
2021-05-02 15:14:33.383<--1:  15:     0x55fcb6c1313c - core::panicking::panic::h3de4db67bd397eb3
2021-05-02 15:14:33.383<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/core/src/panicking.rs:50:5
2021-05-02 15:14:33.383<--1:  16:     0x55fcb6c3ae2c - pleco_engine::search::Searcher::search::h5101e7830a14161b
2021-05-02 15:14:33.383<--1:  17:     0x55fcb6c3a524 - pleco_engine::search::Searcher::search::h5101e7830a14161b
2021-05-02 15:14:33.383<--1:  18:     0x55fcb6c36378 - pleco_engine::search::Searcher::search_root::ha097df830d13b18a
2021-05-02 15:14:33.383<--1:  19:     0x55fcb6c359ac - std::sys_common::backtrace::__rust_begin_short_backtrace::hfe1ee00e5ba6c1af
2021-05-02 15:14:33.383<--1:  20:     0x55fcb6c35679 - core::ops::function::FnOnce::call_once{{vtable.shim}}::h5f7dd8b7c406aef8
2021-05-02 15:14:33.383<--1:  21:     0x55fcb6c79455 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h3aa31cb6360b59d9
2021-05-02 15:14:33.383<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/alloc/src/boxed.rs:1546:9
2021-05-02 15:14:33.383<--1:  22:     0x55fcb6c79455 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h7719d3c7c5841461
2021-05-02 15:14:33.383<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/alloc/src/boxed.rs:1546:9
2021-05-02 15:14:33.383<--1:  23:     0x55fcb6c79455 - std::sys::unix::thread::Thread::new::thread_start::hfbe13ead469fd0bc
2021-05-02 15:14:33.383<--1:                               at /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/library/std/src/sys/unix/thread.rs:71:17
2021-05-02 15:14:33.383<--1:  24:     0x7fe79102afa3 - start_thread
2021-05-02 15:14:33.383<--1:  25:     0x7fe790dd34cf - clone
2021-05-02 15:14:33.383<--1:  26:                0x0 - <unknown>

Question about the license

Hello,

Since pleco_engine is a re-write of Stockfish, shouldn't it use the GPL license too? The GPL and MIT aren't compatible.

Edit: Aren't compatible in the GPL -> MIT direction (since the later is more permissive, doesn't have copyleft)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.