A Banqi Game Server
- Install Go (version 1.21 or later)
- Modern Go uses modules, so you don't need to set up
$GOPATHor$GOROOTanymore
- Modern Go uses modules, so you don't need to set up
- Install Node.js (for building the React frontend)
- Includes npm, which is needed for the web UI
-
Clone this repository:
git clone https://github.com/arbrown/pao.git cd pao -
Install Go dependencies:
go mod download
-
Create the configuration file:
cp conf/paoSettings.json.sample conf/paoSettings.json
This creates a basic SQLite configuration. You can edit
conf/paoSettings.jsonto customize database settings and encryption keys. -
Build the React frontend:
cd react-app npm install npm run build cd ..
-
Build and run the server:
go run .Or build a binary:
go build -o pao . ./paoThe server will start on port 2015. Go to http://localhost:2015/ in a web browser to see the lobby.
You can install Pao globally using:
go install github.com/arbrown/pao@latestThen run it with:
paoTo contribute changes:
- Fork this repository on GitHub
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/pao.git cd pao - Make your changes and test them
- Submit a pull request to the upstream repository
If no games are currently running, you can join a new game by clicking the button:

Then, another player can join your game and it will begin.

Have fun!

Banqi Game Notation
The game code uses a character-based notation to store and transmit piece information.
Pieces are represented by the letters in the following table
| Piece | Red | Black |
|---|---|---|
| King | k | K |
| Guard | g | G |
| Elephant | e | E |
| Cart | c | C |
| Horse | h | H |
| Pawn | p | P |
| Canon | q | Q |
Uncovered pieces are represented by '?' and empty squares are '.'.
The board is represented as an 8x4 (8 columns, 4 rows) board with coordinates as follows:
| . | A | B | C | D | E | F | G | H |
|---|---|---|---|---|---|---|---|---|
| 1 | ||||||||
| 2 | ||||||||
| 3 | ||||||||
| 4 |
A location is referred to by its letter/number coordinates, for example, A1 or F3.
A ply consists of a piece identifier, a location, an action (moves '>', or becomes '=') followed by a piece identifier, and a location. If a piece was killed in this ply, there is then an 'x' followed by the piece identifier and location of the killed piece.
For example, if a black guard at C2 killed a red pawn at D2, the ply notation would be:
GC2>GD2xpD2
If a player turned up a red cannon at B4, the notation would be:
?B4=qB4
In theory, in some game variants a ply could involve more than one piece (on either side) or multiple moves (as in double-move Banqi.) In this case, multiple pieces (and their locations) are separated by commas (,) and multiple moves are separated by semicolons (;).