Fix parsing repeated moves

This commit is contained in:
Trevor Slocum 2024-11-28 20:47:01 -08:00
parent 2a31ba04d6
commit aa618a9487

View file

@ -98,16 +98,16 @@ func gnubgPosition(g *bgammon.Game) string {
}
func parseMoves(moves []byte) ([4][2]int8, error) {
var c int // Input cursor.
var m [4][2]int8 // Parsed moves.
var mc int // Parsed moves cursor.
// Parse moves separated by spaces.
l := len(moves)
var m [4][2]int8
var mc int
var i int
for i < l {
for c < l {
var moveLength int
for j := i; j < l; j++ {
if moves[j] == ' ' {
for i := c; i < l; i++ {
if moves[i] == ' ' {
break
}
moveLength++
@ -116,20 +116,9 @@ func parseMoves(moves []byte) ([4][2]int8, error) {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: no moves: %s", moves)
}
move := moves[i : i+moveLength]
move := moves[c : c+moveLength]
move = bytes.ReplaceAll(move, []byte("*"), nil)
slash := bytes.IndexRune(move, '/')
if slash == -1 {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: invalid count: %s", moves)
}
nextSlash := bytes.IndexRune(move[slash+1:], '/')
var remaining []byte
if nextSlash != -1 {
remaining = move[slash+nextSlash+2:]
move = move[:slash+nextSlash+1]
}
count := 1
paren := bytes.IndexRune(move, '(')
if paren != -1 {
@ -141,6 +130,17 @@ func parseMoves(moves []byte) ([4][2]int8, error) {
mv := append(move[:paren], move[paren+3:]...)
move = mv
}
slash := bytes.IndexRune(move, '/')
if slash == -1 {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: invalid count: %s", moves)
}
nextSlash := bytes.IndexRune(move[slash+1:], '/')
var remaining []byte
if nextSlash != -1 {
remaining = move[slash+nextSlash+2:]
move = move[:slash+nextSlash+1]
}
from := bgammon.ParseSpace(string(move[:slash]))
if from < 0 || from > 27 {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: invalid from (%s): %s", move[:slash], moves)
@ -150,31 +150,33 @@ func parseMoves(moves []byte) ([4][2]int8, error) {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: invalid to (%s): %s", move[:slash], moves)
}
for j := 0; j < count; j++ {
for i := 0; i < count; i++ {
m[mc][0], m[mc][1] = int8(from), int8(to)
ok := Game.AddLocalMove([]int8{int8(from), int8(to)})
if !ok {
return [4][2]int8{}, fmt.Errorf("failed to add local moves (%d/%d): %s", from, to, moves)
}
mc++
}
if len(remaining) > 0 {
rm, err := parseMoves(append([]byte(strconv.Itoa(int(to))+"/"), remaining...))
if err != nil {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: invalid remaining moves (%s): %s", append([]byte(strconv.Itoa(int(to))+"/"), remaining...), moves)
}
for j := 0; j < 4; j++ {
if rm[j][0] == 0 && rm[j][1] == 0 {
break
if len(remaining) > 0 {
rm, err := parseMoves(append([]byte(strconv.Itoa(int(to))+"/"), remaining...))
if err != nil {
return [4][2]int8{}, fmt.Errorf("failed to parse gnubg moves: invalid remaining moves (%s): %s", append([]byte(strconv.Itoa(int(to))+"/"), remaining...), moves)
}
for j := 0; j < 4; j++ {
if rm[j][0] == 0 && rm[j][1] == 0 {
break
}
m[mc][0], m[mc][1] = int8(rm[j][0]), int8(rm[j][1])
mc++
}
m[mc][0], m[mc][1] = int8(rm[j][0]), int8(rm[j][1])
mc++
}
}
i += moveLength + 1
// Advance to the next move.
c += moveLength + 1
}
// Relocate bear-off moves after moves within the board.
var mb, mo [][2]int8
for j := 0; j < 4; j++ {