Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jump to a specific node from command line? #872

Open
jcguu95 opened this issue May 23, 2022 · 10 comments
Open

Jump to a specific node from command line? #872

jcguu95 opened this issue May 23, 2022 · 10 comments

Comments

@jcguu95
Copy link

jcguu95 commented May 23, 2022

Question

Is it possible to jump to a specific node of an sgf file from
command line. Of course, a domain specific language for
specifying a node is required, or we may use regex matching to
find the nodes with comments. For example,

$> sabaki --load "game.sgf" --node "E5[1]"

Usage

This will be useful because people can then take notes
for GO easily. For example, in org-mode (a la emacs) one can
custimize link protocols as follows.

* Lesson 1: Vital points

A Vital Point is an important shape point for both players, e.g.

+ [[go:~/game.sgf:E5[1]]]

The [[..]] would be turned into a link, which is then bound to
the command (non-existent?) above.

Related

@HackYardo
Copy link

HackYardo commented May 29, 2022

As far as I know, it is a basic feature of GoTextProtocol to load a position from a sgf file by a movenumber:

6.3.5 Regression Commands

  • loadsgf
    arguments filename move_number
      string filename - Name of an sgf file.
      int move_number - Optional move number.
    effects Board size and komi are set to the values given in the sgf file. Board configuration, number of captured stones, and move history are found by replaying the game record up to the position before move_number or until the end if omitted.
    output none
    fails Syntax error. If the file does not exist or cannot be read in because it is broken in some way, fails with the error message ``cannot load file''.
    comments Due to the syntactical limitations of this protocol, the filename cannot include spaces, hash signs (#), or control characters. The command requires the controller and the engine to share file system, or at least that the controller has sufficient knowledge about the file system of the engine. If move_number is larger than the number of moves in the file, read until the end of the file. This command has no support for sgf files with variations or game collections.

So, you can wrap it to implement the custom:

def loadsgf(file,node):
    ...
    loadsgf(file,movenumber)

@jcguu95
Copy link
Author

jcguu95 commented May 29, 2022

This is great! I think I can write a wrapper in python, but how do I send the signal to Sabaki?

@HackYardo
Copy link

HackYardo commented May 30, 2022

You will need to embed the custom loadsgf() into a tiny gtp wrap, e.g. instead path/to/gnugo --mode gtp, use python path/to/script.py in the Sabaki's menu:
image

I find a relevant method in sente.py here.

Or, if you know JavaScript, you can modify the source code of Sabaki and then request a pull.

@HackYardo
Copy link

It is very easy to implement a GTP Wrap. Here is an example written in Julia, a new language similar to Python:

katagoCommand=`./katago gtp -config gtp_custom.cfg -model b6/model.txt.gz`
katagoProcess=open(katagoCommand,"r+")

function query()
    sentence=""
    while true
        sentence=readline()
        if sentence=="" || "" in split(sentence," ")
            continue
        else
            println(katagoProcess,sentence)
            break
        end
    end
    return sentence::String
end

function reply()
    paragraph=""
    while true
        sentence=readline(katagoProcess)
        if sentence==""
            break
        else 
            paragraph="$paragraph$sentence\n"
        end
    end
    println(paragraph)
    return paragraph::String
end

function play()
    while true
        sentence=query()
        paragraph=reply()
        if sentence=="quit"
            break
        else
            continue
        end
    end
end

function main()
    play()
end

main()

@jcguu95
Copy link
Author

jcguu95 commented May 31, 2022

@HackYardo Thank you so much for your help!!

I read through each part of the wonderful doc of sente. It's
very close to what I want. In particular, it can create an
internal gtp engine, which can be called by Sabaki or other go
GUIs. To write a simple AI using sente, as shown in the doc,
we need to implement our own genmove(). I also learn how to
hook such AI with Sabaki. Awesome!

My goal is simpler: to send an external signal to Sabaki for
it to jump to a specific node of a specific sgf file. This should
be done by sending an external signal to sente, and let sente
to ask Sabaki to display a certain node.
Do you know how to do
the last bolded step?

@atw1020
Copy link

atw1020 commented May 31, 2022

As far as I know, it is a basic feature of GoTextProtocol to load a position from a sgf file by a movenumber:

loadSGF is an instruction that Sabaki is giving to the engine. GTP does not provide any method for an engine to tell Sabaki to change moves. Sabaki has no way for a program to tell it what move to advance to as fare as I can tell.

@HackYardo
Copy link

@atw1020 @jcguu95 Well, in my view, you complicate this issue. Yeah, GTP is only a standard, it is not GTP but GTP engines/controllers do the implementing. So that either controllers or engines can implement their GTP extensions. So does a script which wraps gtp engines. That's the point. See the diagram:

user <==> gui <==> controller <==> engine
user <==> Sabaki <==> engine
user <==> Sabaki <==> wrap <==> engine

There is a gtp controler in Sabaki, so one can modify Sabaki to implement some gtp extensions.

@HackYardo
Copy link

HackYardo commented Jun 1, 2022

In details:

user -> loadsgf node -> gui -> controller -> loadsgf(node) -> loadsgf move_number -> engine -> target position -> controller -> gui -> user

Just fill some codes in loadsgf().

@atw1020
Copy link

atw1020 commented Jun 1, 2022

I'm still not sure what you are trying to describe.

If you run `loadsgf in the sabaki console window, an engine using GTP will load the game, but the SGF will not show up in sabaki. As you can see in the screenshot below, the engine is successfully able to load the SGF file, however the sabaki go board does not populate with the game loaded by the command.

Screen Shot 2022-05-31 at 9 32 07 PM

On the other hand, you can also try to have the engine send the loadsgf command to sabaki directly. If you try to send such a command to sabaki, sabaki will ignore it because sabaki is a controller and ignores commands if an engine tries to send them. You can verify this by adding a print statement into the sente GTP engine example (see below for code modification) and then running the engine in sabaki. The command will not show up in the console.

    while session.active():

        # respond to a command from the controller
        response = session.interpret(input(""))
        print(response)

        # try to send
        print("loadsgf ORissei-YamashiroHiroshi38563.sgf")

Is there something I'm missing here? please let me know

@HackYardo
Copy link

Sorry so much for the trouble! I remember Sabaki has a engine sync feature, so you can sync board after loadsgf, but it is "gui leads, engine follows" not vice versa... Meanwhile, this issue is not a GTP thing but a GUI thing...
image

(In fact, I'm writing a web app, it knows none about Go rules and uses showboard to handle Go logic. It is "engine leads, gui follows". So the trouble occurs...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants