Using half-move logic instead of trying to keep track of white/black
manually seems to be a good idea. No guarantees I didn't add extra
bugs, though.
let pv = display_line.pv;
let move_num = find_move_num(display_line.start_fen);
let toplay = find_toplay(display_line.start_fen);
let pv = display_line.pv;
let move_num = find_move_num(display_line.start_fen);
let toplay = find_toplay(display_line.start_fen);
-
- // Truncate PV at the start if needed.
- let start_display_move_num = display_line.start_display_move_num;
- if (start_display_move_num > 0) {
- pv = pv.slice(start_display_move_num);
- let to_add = start_display_move_num;
- if (toplay === 'b') {
- ++move_num;
- toplay = 'w';
- --to_add;
- }
- if (to_add % 2 == 1) {
- toplay = 'b';
- --to_add;
- }
- move_num += to_add / 2;
- if (splicepos !== null && splicepos > 0) {
- --splicepos;
- }
- }
+ let halfmove_num = move_num * 2 + (toplay === 'w' ? 0 : 1); // From two, for simplicity.
let ret = document.createDocumentFragment();
let ret = document.createDocumentFragment();
- let in_tb = false;
- let i = 0;
- if (opt_limit && opt_showlast && pv.length > opt_limit) {
- // Truncate the PV at the beginning (instead of at the end).
- // We assume here that toplay is 'w'. We also assume that if
- // opt_showlast is set, then it is the history, and thus,
- // the UI should be to expand the history.
+
+ // Truncate PV at the start if needed.
+ let to_skip = display_line.start_display_move_num;
+ if (opt_limit && opt_showlast && pv.length - to_skip > opt_limit) {
+ // Explicit (UI-visible) truncation from the start, for the history.
ret.appendChild(document.createTextNode('('));
let link = document.createElement('a');
link.className = 'move';
ret.appendChild(document.createTextNode('('));
let link = document.createElement('a');
link.className = 'move';
link.textContent = '…';
ret.appendChild(link);
ret.appendChild(document.createTextNode(') '));
link.textContent = '…';
ret.appendChild(link);
ret.appendChild(document.createTextNode(') '));
- i = pv.length - opt_limit;
- if (i % 2 == 1) {
- ++i;
+ to_skip = pv.length - opt_limit;
+ to_skip += to_skip % 2; // Make sure it starts on a white move.
+ }
+ if (to_skip > 0) {
+ pv = pv.slice(to_skip);
+ halfmove_num += to_skip;
+ if (splicepos !== null) {
+ splicepos -= to_skip;
+ if (splicepos < 0) {
+ splicepos = 0;
+ }
- move_num += i / 2;
- } else if (toplay == 'b' && pv.length > 0) {
- ret.appendChild(document.createTextNode(move_num + '. … '));
- for (; i < pv.length; ++i) {
+
+ // The initial move number needs to go before any (TB: …) marker.
+ if (halfmove_num % 2 == 1) {
+ // Black move.
+ ret.appendChild(document.createTextNode((halfmove_num - 1) / 2 + '. … '));
+ } else {
+ // White move.
+ ret.appendChild(document.createTextNode(halfmove_num / 2 + '. '));
+ }
+ let in_tb = false;
+ for (let i = 0; i < pv.length; ++i, ++halfmove_num) {
let prefix = '';
if (splicepos === i) {
let prefix = '';
if (splicepos === i) {
- if (toplay == 'b' && i == 0) {
- ++move_num;
- toplay = 'w';
- } else if (toplay == 'w') {
+ if (halfmove_num % 2 == 0 && i != 0) {
if (i > opt_limit && !opt_showlast) {
if (in_tb) {
prefix += ')';
if (i > opt_limit && !opt_showlast) {
if (in_tb) {
prefix += ')';
ret.appendChild(document.createTextNode(prefix + ' (…)'));
return ret;
}
ret.appendChild(document.createTextNode(prefix + ' (…)'));
return ret;
}
- prefix += ' ' + move_num + '. ';
- ++move_num;
- toplay = 'b';
+ prefix += ' ' + (halfmove_num / 2) + '. ';
}
ret.appendChild(document.createTextNode(prefix));
}
ret.appendChild(document.createTextNode(prefix));