npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sabaki/gtp

v3.0.0

Published

A Node.js module for handling GTP engines.

Downloads

129

Readme

@sabaki/gtp CI

A Node.js module for handling GTP engines.

Installation

Use npm to install:

$ npm install @sabaki/gtp

Usage

Controller Usage

Use the Controller class to interact with an engine:

const {StreamController, Controller, Command, Response} = require('@sabaki/gtp')

async function main() {
  let leela = new Controller('./path/to/leela', ['--gtp', '--noponder'])
  leela.start()

  let response = null

  try {
    response = await leela.sendCommand({name: 'genmove', args: ['B']})
  } catch (err) {
    throw new Error('Failed to send command!')
  }

  if (response.error) {
    throw new Error('Command not understood by Leela!')
  }

  console.log(response.content)
  await leela.stop()
}

main().catch(err => console.log(`Error: ${err}`))

Engine Usage

Use the Engine class to create an engine:

const {Engine} = require('@sabaki/gtp')

let testEngine = new Engine('Test Engine', '0.1')

testEngine.command('play', (command, out) => {
  if (command.args.length === 0) return out.err('player not specified')
  out.send('playing for ' + command.args[0])
})

testEngine.start()

API

Command

A GTP command is represented by an object of the following form:

{
  id?: <Integer> | null,
  name: <String>,
  args?: <String[]>
}

Command.fromString(input)

  • input <String> - The GTP command as string, e.g. 1 genmove B

Returns a Command object, representing input.

Command.toString(command)

Returns a GTP command string represented by command to be sent to an engine.


Response

A response from a GTP engine is represented by an object of the following form:

{
  id?: <Integer> | null,
  content: <String>,
  error?: <Boolean>
}

Response.fromString(input)

  • input <String> - The GTP response as string, e.g. =1 ok

Returns a Response object, representing input.

Response.toString(response)

Returns a GTP response string represented by response, something that an engine might send.


class StreamController extends EventEmitter

Use this class to control GTP engines on arbitrary communication channels. To spawn engine processes automatically, use Controller.

new StreamController(input, output)

Event: command-sent

This event is emitted when a command is sent to the engine. Using the subscribe function you can get updates every time the engine responds with a new line, see streamController.sendCommand().

Event: response-received

This event is emitted when the engine finishes sending a response.

streamController.input

<Writable> - The input stream of the GTP engine.

streamController.output

<Readable> - The output stream of the GTP engine.

streamController.commands

<Command[]> - The command queue.

streamController.busy

<Boolean> - Indicates whether the controller is waiting for an engine response or not.

async streamController.sendCommand(command[, subscriber])

  • command <Command>
  • subscriber <Function> (optional)
    • evt <Object>

Sends a command to the engine and returns a response object. You can pass a subscriber function to get updates every time the engine responds with a new line. subscriber is called with an object evt with the following properties:

  • line <String> - The contents of the incoming line.
  • end <Boolean> - true if incoming line is the last line of response.
  • command <Command> - The command to which the response belongs.
  • response <Response> - The partial response until now, including the incoming line with all the previous lines.

streamController.close()

Cleans up listeners.


class Controller extends EventEmitter

Use this class to spawn GTP engine processes and control them over stdin and stdout.

new Controller(path[, args[, spawnOptions]])

Event: started

This event is emitted when the engine process starts.

Event: stopped

  • evt <Object>
    • signal <String> - The signal by which the engine process was terminated.

This event is emitted after the engine process ends.

Event: stderr

  • evt <Object>
    • content <String>

This event is emitted when the engine process finishes printing a line on stderr.

Event: command-sent

See corresponding event in StreamController.

Event: response-received

See corresponding event in StreamController.

controller.path

<String> - The path to an executable file, the GTP engine.

controller.args

<String[]> - Additional arguments that are passed to the engine when started.

controller.spawnOptions

<Object> - See Node.js documentation.

controller.process

<ChildProcess> | null - The GTP engine process.

controller.commands

<Command[]> - The command queue.

controller.busy

<Boolean> - Indicates whether the controller is waiting for an engine response or not.

controller.start()

Spawns a process of the engine if necessary.

async controller.stop([timeout])

  • timeout <number> (optional) - Default: 3000

Sends a quit command to the engine. If engine doesn't respond, it will be killed after timeout ms.

async controller.kill()

Kills the engine process.

async controller.sendCommand(command[, subscriber])

See corresponding function in StreamController.


class ControllerStateTracker

Use this class to keep track of the state of an engine. This class is also able to synchronize the state of an engine to a given state.

EngineState

The state of an engine is represented by an object of the following structure:

{
  komi: <number>,
  boardsize: <[number, number]>,
  timeSettings: {
    mainTime: <number>,
    byoyomiTime: <number>,
    byoyomiStones: <number>
  },
  history: <Command[]>
}
  • Values will be null if we do not know the engine state.
  • boardsize contains the width and height of the board.
  • history is an array of set_free_handicap and play commands.

new ControllerStateTracker(controller)

ControllerStateTracker.fromStreamController(input, output)

Equivalent to new ControllerStateTracker(new StreamController(input, output)).

ControllerStateTracker.fromController(path[, args[, spawnOptions]])

Equivalent to new ControllerStateTracker(new Controller(path, args, spawnOptions)).

stateTracker.controller

<StreamController> or <Controller> - The controller of the engine that we're tracking the state of.

stateTracker.state

<EngineState> - The state of the engine controlled by stateTracker.controller.

stateTracker.syncing

<Boolean> - Indicates whether the controller is performing a sync right now.

async stateTracker.knowsCommand(commandName)

  • commandName <String>

Returns a boolean whether the engine supports the given command.

async stateTracker.queueCommand(command)

Sends the given command to the engine after all ongoing syncs have finished and returns the response.

async stateTracker.sync(state)

Tries to sync the engine to the given state. Omit keys or set values to null in the state object if you do not want to change the engine state for particular keys.


class Engine extends EventEmitter

Use this class to create a GTP engine using the communication channels of your choice.

new Engine([name[, version]])

  • name <String> (optional)
  • version <String> (optional)

The following GTP commands have a default implementation:

  • protocol_version
  • name
  • version
  • list_commands
  • quit

Event: started

This event is emitted when the engine has started.

Event: stopped

This event is emitted when the engine has stopped.

Event: command-received

This event is emitted after a command has been received.

Event: command-processing

This event is emitted when a command is about to be processed.

Event: command-processed

This event is emitted after a command has been processed.

engine.handlers

<Object> - An object with the command names as keys, and handler functions as values.

engine.commands

<Command[]> - The command queue.

engine.busy

<Boolean> - If true, a command is being processed right now.

engine.command(name, handler)

  • name <String> - The command name.
  • handler <Function> | <String>

Sets a handler for the given command. handler will be called with the following arguments:

  • command <Command>
  • out <Object>
    • send(content) - Sends a successful response with the given content.
    • err(content) - Sends an error response with the given content.
    • write(content) - Writes given content to response.
    • end() - When using write, use this method to indicate end of response.

handler can be an async function or return a Promise. In this case, you don't need to call out.end() explicitly.

You can also pass a string as handler to immediately return a response.

engine.start([options])

  • options <Object> (optional)
    • input <Readable> (optional) - Default: process.stdin
    • output <Writable> (optional) - Default: process.stdout

Starts listening to commands.

engine.stop()

Stops listening.