-
Notifications
You must be signed in to change notification settings - Fork 2
/
uci.go
136 lines (125 loc) · 2.77 KB
/
uci.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package chess_engine
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type EngineOption uint8
const (
SELDEPTH EngineOption = iota
)
type Engine interface {
SetPosition(*Game)
GetPosition() *Game
AddEvaluator(Evaluator)
Start(engineOutput chan string, maxNodes int, maxDepth int)
SetOption(EngineOption, int)
Stop()
}
type UCI struct {
Name string
Author string
LogFile string
Engine Engine
}
func NewUCI(engineName, author string, engine Engine) *UCI {
return &UCI{
Name: engineName,
Author: author,
LogFile: "/tmp/bsengine.log",
Engine: engine,
}
}
// Reads from the input stream (e.g. stdin) and emits lines
func (uci *UCI) lineReader(reader *bufio.Reader, in chan string) {
for {
text, err := reader.ReadString('\n')
if err != nil {
panic(err)
}
in <- strings.TrimSpace(text)
}
}
func (uci *UCI) Start(reader *bufio.Reader) {
log, err := os.Create(uci.LogFile)
if err != nil {
panic(err)
}
defer log.Close()
input := make(chan string)
engineOutput := make(chan string, 50)
go uci.lineReader(reader, input)
for {
select {
case cmdLine := <-input:
log.Write([]byte(cmdLine))
log.Write([]byte{'\n'})
if cmdLine == "" {
continue
}
cmdParts := strings.Split(cmdLine, " ")
cmd := cmdParts[0]
switch cmd {
case "uci":
fmt.Println("id name " + uci.Name)
fmt.Println("id author " + uci.Author)
fmt.Println("uciok")
break
case "isready":
fmt.Println("readyok")
break
case "quit":
return
case "go":
if cmdParts[1] == "infinite" {
uci.Engine.Start(engineOutput, -1, -1)
} else if cmdParts[1] == "nodes" {
nodes, err := strconv.Atoi(cmdParts[2])
if err != nil {
panic(err)
}
uci.Engine.Start(engineOutput, nodes, -1)
} else if cmdParts[1] == "depth" {
depth, err := strconv.Atoi(cmdParts[2])
if err != nil {
panic(err)
}
uci.Engine.Start(engineOutput, -1, depth)
}
break
case "perft":
depth, err := strconv.Atoi(cmdParts[1])
if err != nil {
panic(err)
}
Perft(uci.Engine.GetPosition(), depth)
case "stop":
uci.Engine.Stop()
break
case "position":
if cmdParts[1] == "fen" {
fenStr := strings.Join(cmdParts[2:], " ")
fen, err := ParseFEN(fenStr)
if err != nil {
log.Write([]byte("Error parsing fen: " + err.Error()))
return
}
uci.Engine.SetPosition(fen)
} else if cmdParts[1] == "startpos" {
fenStr := "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
fen, err := ParseFEN(fenStr)
if err != nil {
log.Write([]byte("Error parsing fen: " + err.Error()))
return
}
uci.Engine.SetPosition(fen)
}
}
case out := <-engineOutput:
log.Write([]byte(">>> " + out + "\n"))
fmt.Println(out)
}
}
}