diff --git a/.gitignore b/.gitignore index cf485c6..ac291c5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,5 @@ games/*.pgn games/archive/*.pgn .env dist/* -configs/chesspal.dev.yaml +configs/chesspal.*.yaml github_token \ No newline at end of file diff --git a/README.md b/README.md index ed2723a..88e8aae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Chesspal -Chesspal is a responsive web server for [USB DGT e-Boards](https://digitalgametechnology.com/products/home-use-e-boards). Its core features are to record chess games and play against configurable AIs. +Chesspal is a responsive webserver for [USB DGT e-Boards](https://digitalgametechnology.com/products/home-use-e-boards). Its core features are to record chess games and play against configurable AIs. Special thanks to: - @notnil ([https://github.com/notnil/chess](https://github.com/notnil/chess)) for an amazing golang based chess package that is used as a basis @@ -53,7 +53,7 @@ make release ## Raspberry pi setup The makefile ships with targets to easily setup a fresh Raspian installation. However, the arm binaries can be used for manual installation as well. -To setup a fresh Raspberry pi using makefile targets, add a `.env` based on `.env.example`. A working `golang` and `npm` setup is required. Then you can run the following commands: +To setup a fresh Raspberry pi using makefile targets, add a `.env` based on `.env.example`. Further, create a config file `configs/chesspal.raspi.yaml`. A working `golang` and `npm` setup is required. Then you can run the following commands: ```bash make release # to generate a new release bundle locally diff --git a/cmd/chesspal/main.go b/cmd/chesspal/main.go index 39f6f23..ab3bce2 100644 --- a/cmd/chesspal/main.go +++ b/cmd/chesspal/main.go @@ -52,8 +52,8 @@ type StartOptions struct { } type Player struct { - Name string `json:"name"` - Type int `json:"type"` + IsHuman bool `json:"isHuman"` + Type int `json:"type"` } type Config struct { @@ -64,10 +64,14 @@ type Config struct { DgtPort string `yaml:"dgtPort"` Engines map[string]string `yaml:"engines"` Bots []player.BotOptions `yaml:"bots"` + Humans []Human `yaml:"humans"` Eval Eval `yaml:"eval"` RClone Rclone `yaml:"rclone"` } +type Human struct { + Name string `yaml:"name" json:"name"` +} type Rclone struct { Remote string `yaml:"remote"` Games bool `yaml:"games"` @@ -88,7 +92,8 @@ var engine *player.DGTEngine var currentBoard chess.Board type WSResponse struct { - Bots []player.BotOptions `json:"bots"` + Bots []player.BotOptions `json:"bots"` + Humans []Human `json:"humans"` } type GameHistory struct { @@ -237,7 +242,7 @@ func main() { } defer ws.Close() - if err := ws.WriteJSON(WSResponse{Bots: config.Bots}); !errors.Is(err, nil) { + if err := ws.WriteJSON(WSResponse{Bots: config.Bots, Humans: config.Humans}); !errors.Is(err, nil) { log.Printf("error occurred: %v", err) } @@ -355,19 +360,25 @@ func startGame(msg *Message, ui *ui.WSUI, cfg Config, ws *websocket.Conn) { engine.Reset() engine.SetUpsideDown(msg.Options.UpsideDown) + log.Printf("Black: %+v, White: %+v", msg.Options.Black, msg.Options.White) + var white, black game.Player - if msg.Options.Black.Type == 0 { - black = player.NewDGTPlayer(msg.Options.Black.Name, engine) + if msg.Options.Black.IsHuman { + i := msg.Options.Black.Type + human := cfg.Humans[i] + black = player.NewDGTPlayer(human.Name, engine) } else { - i := msg.Options.Black.Type - 1 + i := msg.Options.Black.Type options := cfg.Bots[i] options.Path = cfg.Engines[options.Engine] black = player.NewUCIPlayer(options) } - if msg.Options.White.Type == 0 { - white = player.NewDGTPlayer(msg.Options.White.Name, engine) + if msg.Options.White.IsHuman { + i := msg.Options.White.Type + human := cfg.Humans[i] + white = player.NewDGTPlayer(human.Name, engine) } else { - i := msg.Options.White.Type - 1 + i := msg.Options.White.Type options := cfg.Bots[i] options.Path = cfg.Engines[options.Engine] white = player.NewUCIPlayer(options) diff --git a/configs/chesspal.yaml b/configs/chesspal.yaml index 829aaf1..5212cfa 100644 --- a/configs/chesspal.yaml +++ b/configs/chesspal.yaml @@ -8,6 +8,9 @@ rclone: engines: stockfish_12: /usr/games/stockfish fairy_stockfish: usr/local/bin/stockfish +humans: + - name: White + - name: Black bots: - name: Adrian (fairy 400) engine: fairy_stockfish diff --git a/makefile b/makefile index c918890..498f1b7 100644 --- a/makefile +++ b/makefile @@ -35,15 +35,16 @@ raspi-install-chesspal: && mkdir ~/chesspal \ && mkdir -p ~/games/archive \ && tar -xf /tmp/$(ARM_RELEASE) -C ~/chesspal \ - && sudo update-rc.d $(INIT_SCRIPT) defaults \ - && sudo shutdown -r 0") + && sudo update-rc.d $(INIT_SCRIPT) defaults") + $(call ssh-copy,configs/chesspal.raspi.yaml,/home/pi/chesspal/configs/chesspal.yaml) + $(call ssh-cmd,"sudo shutdown -r 0") raspi-restart-chesspal: $(call ssh-cmd,"sudo service $(INIT_SCRIPT) stop") $(call ssh-cmd,"sudo service $(INIT_SCRIPT) start") raspi-apply-config: - $(call ssh-copy,configs/chesspal.yaml,/home/pi/chesspal/configs/chesspal.yaml) + $(call ssh-copy,configs/chesspal.raspi.yaml,/home/pi/chesspal/configs/chesspal.yaml) $(call ssh-cmd,"sudo shutdown -r 0") raspi-logs-follow: diff --git a/web/vue-frontend/src/App.vue b/web/vue-frontend/src/App.vue index bc42788..a0ede10 100644 --- a/web/vue-frontend/src/App.vue +++ b/web/vue-frontend/src/App.vue @@ -51,6 +51,8 @@ :fen="fen" :outcome="outcome" :pgn="pgn" + :black="black.name" + :white="white.name" class="my-4" /> @@ -82,7 +84,6 @@ > - - - - - - - - Start game - - - - - + + + New game + + + + + + + + + + Start game + + + + + + +
@@ -207,13 +216,13 @@ export default { pawn: 50.0, turn: "w", black: { - name: "black", mode: 0, + isHuman: true, speak: false, }, white: { - name: "white", mode: 0, + isHuman: true, speak: false, }, evalMode: 0, @@ -221,9 +230,23 @@ export default { fen: "r5nr/ppk2pp1/7p/2Bp1b2/8/7P/PPP1PPP1/RN2KB1R", outcome: "*", bots: [], + humans: [], }), methods: { + setPlayer: function(color, event) { + console.log(event.name, event.isHuman, event.value) + if (color == "black") { + this.black.name = event.name + this.black.isHuman = event.isHuman + this.black.mode = event.mode + } + if (color == "white") { + this.white.name = event.name + this.white.isHuman = event.isHuman + this.white.mode = event.mode + } + }, toggleDarkTheme() { this.$vuetify.theme.dark = !this.$vuetify.theme.dark; }, @@ -268,10 +291,12 @@ export default { white: { name: this.white.name, type: Number(this.white.mode), + isHuman: this.white.isHuman, }, black: { name: this.black.name, type: Number(this.black.mode), + isHuman: this.black.isHuman, }, evalMode: 1, //always use eval but only show based on ui // Number(this.evalMode), upsideDown: Boolean(this.upsideDown), @@ -312,12 +337,12 @@ export default { }, mounted() { - if (localStorage.white) { - this.white.name = localStorage.white; - } - if (localStorage.black) { - this.black.name = localStorage.black; - } + // if (localStorage.white) { + // this.white.name = localStorage.white; + // } + // if (localStorage.black) { + // this.black.name = localStorage.black; + // } }, watch: { @@ -346,8 +371,10 @@ export default { this.connection.onmessage = function (event) { var data = JSON.parse(event.data); + console.log(data); if (data.bots != null) { that.bots = data.bots; + that.humans = data.humans; return; } diff --git a/web/vue-frontend/src/components/ChessBoard.vue b/web/vue-frontend/src/components/ChessBoard.vue index a609953..61730f0 100644 --- a/web/vue-frontend/src/components/ChessBoard.vue +++ b/web/vue-frontend/src/components/ChessBoard.vue @@ -5,7 +5,10 @@ fas fa-chess-board -
+
+

+ {{ black }} +

+ +

+ {{ white }} +

@@ -59,7 +66,7 @@ export default { name: "ChessBoard", - props: ["svg", "fen", "outcome", "pgn"], + props: ["svg", "fen", "outcome", "pgn", "white", "black"], methods: { boardClass: function () { switch (this.$vuetify.breakpoint.name) { @@ -77,7 +84,7 @@ export default { return "board"; }, importLichess: async function () { - var win = window.open('', '_blank'); + var win = window.open("", "_blank"); const requestOptions = { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, @@ -88,7 +95,7 @@ export default { requestOptions ); const data = await response.json(); - win.location = data.url + win.location = data.url; }, copy: function () { navigator.clipboard.writeText(this.pgn).then( diff --git a/web/vue-frontend/src/components/ChessPlayer.vue b/web/vue-frontend/src/components/ChessPlayer.vue index 8ecbd0b..80fac30 100644 --- a/web/vue-frontend/src/components/ChessPlayer.vue +++ b/web/vue-frontend/src/components/ChessPlayer.vue @@ -1,5 +1,5 @@