LeelaChessZero (lc0)

The Leela Chess Zero (lc0) neural network chess engine for Flutter.

About

Leela Chess Zero (lc0) is an open-source chess engine that uses deep neural networks to evaluate positions. It's based on the same approach as AlphaZero, using Monte Carlo Tree Search (MCTS) guided by a neural network.

Requirements

  • iOS: IPHONEOS_DEPLOYMENT_TARGET >= 13.0
  • Android: minSdkVersion >= 24
  • Neural network weights file (see below)

Installation

Add dependency to pubspec.yaml:

dependencies:
  LeelaChessZero: ^1.0.0

Usage

Initialize engine

import 'package:LeelaChessZero/lc0.dart';

// create a new instance
final lc0 = Lc0();

// state is a ValueListenable<Lc0State>
print(lc0.state.value); // Lc0State.starting

// the engine takes a few moments to start
await Future.delayed(...)
print(lc0.state.value); // Lc0State.ready

Async initialization

// Wait for engine to be ready
final lc0 = await lc0Async();

UCI commands

Waits until the state is ready before sending commands.

lc0.stdin = 'uci';
lc0.stdin = 'setoption name WeightsFile value /path/to/weights.pb.gz';
lc0.stdin = 'position startpos moves e2e4 e7e5';
lc0.stdin = 'go nodes 1000';
lc0.stdin = 'stop';

Engine output is directed to a Stream<String>:

lc0.stdout.listen((line) {
  print(line);
});

Dispose / Hot reload

// sends the UCI quit command
lc0.stdin = 'quit';

// or even easier...
lc0.dispose();

Note: Only one instance can be created at a time. The factory method Lc0() will throw StateError if called when an existing instance is active.

Neural Network Weights

Unlike Stockfish which embeds evaluation weights at compile time, lc0 requires you to provide a neural network weights file at runtime.

Bundled Weights

This package includes Maia-1900 weights (~1.2MB) - a neural network trained to play like a ~1900 rated human player. Maia networks are from the maia-chess project.

To use the bundled weights, first copy them from assets to a writable location:

import 'dart:io';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';

Future<String> extractWeights() async {
  final dir = await getApplicationDocumentsDirectory();
  final weightsPath = '${dir.path}/maia-1900.pb.gz';

  if (!await File(weightsPath).exists()) {
    final data = await rootBundle.load('assets/weights/maia-1900.pb.gz');
    await File(weightsPath).writeAsBytes(data.buffer.asUint8List());
  }

  return weightsPath;
}

// Then configure lc0:
final weightsPath = await extractWeights();
lc0.stdin = 'setoption name WeightsFile value $weightsPath';

Loading custom weights

lc0.stdin = 'setoption name WeightsFile value /path/to/weights.pb.gz';
Network Size Strength Notes
Maia ~1-10MB Human-like Plays like humans at various levels
T80 ~15MB Strong Good balance of strength/speed

Download networks from lczero.org or maiachess.com.

Differences from Stockfish

Aspect lc0 Stockfish
Evaluation Neural network NNUE + classical
Search MCTS Alpha-beta
Weights Runtime loaded Compile-time embedded
Speed Slower per node Faster per node
Style More strategic More tactical

Credits

Libraries

lc0