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

Search progress visualization (evolving from 'PV board capture results' discussion) #100

Open
qcgm1978 opened this issue Nov 28, 2023 · 5 comments

Comments

@qcgm1978
Copy link
Contributor

qcgm1978 commented Nov 28, 2023

The PV change diagram does not show the result of capturing, as shown in the figure.

I want to display the change diagram dynamically. It would be strange if capturing did not have any effect.

截屏2023-11-28 11 38 25
@kaorahi
Copy link
Owner

kaorahi commented Nov 28, 2023

That is by design. The current behavior is natural to me as it is the common style in most Go books. But if you like... (on c9a6377)

--- a/src/draw_goban.js
+++ b/src/draw_goban.js
@@ -141,6 +141,9 @@ function draw_goban_with_variation(canvas, suggest, opts) {
           suggest === (R.suggest[0] || {})
     const displayed_stones = copy_stones_for_display(opts.stones)
     const bturn = opts.stones ? opts.bturn : R.bturn
+    const stone2move = (s, i, j) => s.stone && {move: idx2move(i, j), is_black: s.black}
+    const fake_history = aa_map(displayed_stones, stone2move).flat().filter(identity)
+    const vgame = require('./game.js').create_game(fake_history)
     variation.forEach((move, k) => {
         const b = xor(bturn, k % 2 === 1), w = !b
         const {pvVisits, pvEdgeVisits, uptodate_len} = suggest
@@ -156,7 +159,10 @@ function draw_goban_with_variation(canvas, suggest, opts) {
             ...(supplementary_info || {}),
         }
         merge_stone_at(move, displayed_stones, pv_stone)
+        vgame.push({move, is_black: b})
     })
+    const vstone = vgame.current_stones()
+    aa_each(displayed_stones, (s, i, j) => {s.stone = vstone[i][j].stone})
     const new_pv_move = suggested_variation_p &&
           (suggest.new_pv || [])[suggest.uptodate_len]
     new_pv_move && merge_stone_at(new_pv_move, displayed_stones, {new_pv_p: true})

To comment in advance, I will NEVER implement the animation of the principal variation. In my opinion, it is useless because long variations are quite unreliable. Instead, if you want to watch the variation move by move, actually play it by pressing the Enter key repeatedly to get a more reliable sequence. You will notice that the result is often different from the original principal variation.

@qcgm1978
Copy link
Contributor Author

qcgm1978 commented Nov 29, 2023

You're right, but I need to directly modify the variation inside the draw_goban_with_variation function to implement the animation effect. I tried it and it worked as the following code snippet and video. In my opinion, this will allow me to see the AI's thought process and how it improves its moves.:

function draw_goban_with_variation(canvas, suggest, opts) {
    ...
    const stone2move = (s, i, j) => s.stone && { move: idx2move(i, j), is_black: s.black }
    const fake_history = aa_map(displayed_stones, stone2move).flat().filter(identity)
    const vgame = require('./game.js').create_game(fake_history)
    // different move_count has different pv
    if (!R[R.move_count]) {
        R[R.move_count] = {
            variation,
            pv_len: 0
        }
    } else {
        const current_variation = R[R.move_count].variation
        let i = 0
        // avoid drawing the same pv part
        for (i; i < current_variation.length; i++) {
            if (current_variation[i] !== variation[i]) {
                break;
            }
        }
        R[R.move_count] = {
            variation,
            pv_len: R[R.move_count].pv_len < i ? R[R.move_count].pv_len : i
        }
    }
    if (!opts.var_end) {
        if (R.pv_timeout) {
            opts.var_end = R[R.move_count].pv_len
        } else {
            R[R.move_count].pv_len++
            opts.var_end = R[R.move_count].pv_len
            R.pv_timeout = true
            const timeout = 500
            setTimeout(() => {
                R.pv_timeout = false
            }, timeout)
        }
    }
    variation = variation.slice(0, opts.var_end ||
        variation.length
    )
    variation.forEach((move, k) => {
        ...
        vgame.push({ move, is_black: b })
    })
    const vstone = vgame.current_stones()
    aa_each(displayed_stones, (s, i, j) => { s.stone = vstone[i][j].stone })
    ...
2023-11-29.21.15.25.mov

@kaorahi
Copy link
Owner

kaorahi commented Nov 29, 2023

Wow! I've never seen such a fun visualization of the search progress. It looks as if the AI is pondering various options and feeling undecided, just like a human. I'd like to keep this issue open, as other users might also find your movie interesting.

@kaorahi kaorahi reopened this Nov 29, 2023
@kaorahi kaorahi changed the title The PV board does not show the result of capturing Search progress visualization (evolving from 'PV board capture results' discussion) Nov 29, 2023
@kaorahi
Copy link
Owner

kaorahi commented Nov 29, 2023

I've been dreaming of displaying the killer move in my GUI for a long time --- the move whose discovery prompts the AI to change its previous opinion in the search process. But it seems it might require some tweaks to the engine itself and hasn't been realized yet...

@qcgm1978
Copy link
Contributor Author

It is worth considering displaying multiple PV charts simultaneously. This has the following advantages:

  • Users can see multiple variation charts at the same time.
  • Users can intuitively see the competitive relationship between different PVs through subsequent changes, such as the order and size of the PV charts.

I have completed the first step, which is to display multiple PVs simultaneously. After clicking on a PV, it can be displayed in original canvas. The next step is to consider adjusting the order and size based on some criteria, such as win rate.

If specific data can be recorded, it will be possible to see which step of a change affected the win rate of a PV. This is what you mentioned as the "killer move." The demo video and core code as the following:

2024-02-15.16.15.18.mp4
const draw_pv = with_opts((...args) => {
    ...
    for (let i = 0; i < pv_num; i++) {
        const c = document.querySelector(`#sub_goban_container_${i}`)
        const arg = { ...args[1], ind: i }
        draw(c, arg)
    }
}, subgoban_mouse)

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

No branches or pull requests

2 participants