Commit 3bce22aa authored by Derek Schaab's avatar Derek Schaab

Initial commit

parents
# common suffix for cpu/memory profile files
*.prof
# vim swap files
*.swp
# binaries output by go test profiler
*.test
{
"Disable": [
"gocyclo"
],
"Enable": [
"gofmt",
"gosimple",
"misspell",
"unparam",
"unused",
"staticcheck"
],
"Exclude": [
"static.go"
]
}
MIT License
Copyright (c) 2017 Eight Squared Software LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# chessboard
A [Go](https://golang.org) library for rendering chess positions described by [package chess](https://gitlab.com/eightsquared/chess) as images.
## Dependencies
This package does not currently use dependency management, so you may need to manually `go get` all dependencies prior to building.
- [gitlab.com/eightsquared/chess](https://gitlab.com/eightsquared/chess)
- [github.com/golang/freetype](https://github.com/golang/freetype)
- [golang.org/x/image/draw](https://github.com/golang/image)
- [golang.org/x/image/math/fixed](https://github.com/golang/image)
## Documentation
[![API Reference](https://godoc.org/gitlab.com/eightsquared/chessboard?status.svg)](https://godoc.org/gitlab.com/eightsquared/chessboard)
## Installation
```
go get -u gitlab.com/eightsquared/chessboard
```
## License
[MIT](LICENSE)
package chessboard
import (
"io"
"gitlab.com/eightsquared/chess"
)
func WriteASCII(w io.Writer, g chess.Game, o Options) (err error) {
dst := &asciiWriter{w: w}
for s := chess.First; s <= chess.Last; s++ {
f := s.File()
if s == chess.A8 {
dst.write(asciiTopRow)
dst.writeByte(byte(g.ToMove.Color().Rune()))
dst.write(newline)
} else if f == 'a' {
dst.write(asciiInterRow)
dst.write(newline)
}
if f == 'a' {
dst.writeByte(byte(s.Rank()))
} else {
dst.write(asciiSingleVertical)
}
p := g.Board[s]
if (p.Is(chess.WhiteKing) && g.Castling.Allows(chess.WhiteQueenside)) ||
(p.Is(chess.BlackKing) && g.Castling.Allows(chess.BlackQueenside)) {
dst.write(leftBracket)
} else {
dst.write(space)
}
dst.writeByte(byte(g.Board[s].Rune()))
if (p.Is(chess.WhiteKing) && g.Castling.Allows(chess.WhiteKingside)) ||
(p.Is(chess.BlackKing) && g.Castling.Allows(chess.BlackKingside)) {
dst.write(rightBracket)
} else {
dst.write(space)
}
if f == 'h' {
dst.write(asciiDoubleVertical)
dst.write(newline)
}
}
dst.write(asciiBottomRow)
dst.write(newline)
err = dst.err
return
}
type asciiWriter struct {
w io.Writer
err error
single []byte
}
var (
asciiTopRow = []byte("╔═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══")
asciiInterRow = []byte("╟───┼───┼───┼───┼───┼───┼───┼───╢")
asciiBottomRow = []byte("╚═a═╧═b═╧═c═╧═d═╧═e═╧═f═╧═g═╧═h═╝")
asciiSingleVertical = []byte("│")
asciiDoubleVertical = []byte("║")
space = []byte(" ")
newline = []byte("\n")
leftBracket = []byte("<")
rightBracket = []byte(">")
)
func (w *asciiWriter) write(b []byte) {
if w.err != nil {
return
}
_, w.err = w.w.Write(b)
}
func (w *asciiWriter) writeByte(b byte) {
if w.err != nil {
return
}
if w.single == nil {
w.single = make([]byte, 1)
}
w.single[0] = b
_, w.err = w.w.Write(w.single)
}
package chessboard
import (
"io/ioutil"
"testing"
"gitlab.com/eightsquared/chess"
)
func BenchmarkWriteASCII(b *testing.B) {
positions := make([]chess.Game, 1e5)
for i := range positions {
positions[i] = chess.RandomGame(i)
}
options := Defaults
b.Run("bench", func(b *testing.B) {
var err error
for i := 0; i < b.N; i++ {
err = WriteASCII(ioutil.Discard, positions[i%len(positions)], options)
if err != nil {
b.Fatal(err)
}
}
})
}
/*
Package chessboard provides functions to render a chess position as an image.
To use this package, you will probably also need the chess package
(https://gitlab.com/eightsquared/chess) to describe games. For example,
supposing you have the following board:
// White to mate in one move.
g := chess.Game{
Board: chess.Board{
chess.E8: chess.BlackBishop,
chess.F8: chess.BlackKing,
chess.A7: chess.BlackPawn,
chess.B7: chess.BlackPawn,
chess.C7: chess.BlackPawn,
chess.G7: chess.BlackPawn,
chess.C6: chess.BlackKnight,
chess.D6: chess.BlackPawn,
chess.H6: chess.BlackPawn,
chess.C5: chess.BlackBishop,
chess.C4: chess.WhiteBishop,
chess.F4: chess.WhiteBishop,
chess.G4: chess.BlackKnight,
chess.H4: chess.BlackQueen,
chess.C3: chess.WhiteKnight,
chess.A2: chess.WhitePawn,
chess.B2: chess.WhitePawn,
chess.G2: chess.WhitePawn,
chess.H2: chess.WhitePawn,
chess.E1: chess.WhiteRook,
chess.F1: chess.WhiteRook,
chess.H1: chess.WhiteKing,
},
ToMove: chess.White,
}
You can write an ASCII-art visualization of this position to standard output as
follows:
err := chessboard.WriteSVG(os.Stdout, chessboard.Defaults)
// Output:
//
// ╔═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══w
// 8 │ │ │ │ b │ k │ │ ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 7 p │ p │ p │ │ │ │ p │ ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 6 │ │ n │ p │ │ │ │ p ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 5 │ │ b │ │ │ │ │ ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 4 │ │ B │ │ │ B │ n │ q ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 3 │ │ N │ │ │ │ │ ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 2 P │ P │ │ │ │ │ P │ P ║
// ╟───┼───┼───┼───┼───┼───┼───┼───╢
// 1 │ │ │ │ R │ R │ │ K ║
// ╚═a═╧═b═╧═c═╧═d═╧═e═╧═f═╧═g═╧═h═╝
In addition to ASCII output, this package supports rendering to SVG (fast) and
PNG (much slower due to raster scaling operations).
*/
package chessboard
package chessboard
//go:generate esc -o=static.go -pkg=chessboard -private res
import (
"bytes"
"fmt"
"image"
"image/png"
"strings"
"github.com/golang/freetype"
"github.com/golang/freetype/truetype"
"gitlab.com/eightsquared/chess"
)
var (
pieceImages pieceImageCache
pieceVectors pieceVectorCache
pieceStyles = []style{merida}
pieceSizes = []size{small, medium, large, xlarge}
pieceNames = map[chess.Piece]string{
chess.WhitePawn: "white_pawn",
chess.WhiteKnight: "white_knight",
chess.WhiteBishop: "white_bishop",
chess.WhiteRook: "white_rook",
chess.WhiteQueen: "white_queen",
chess.WhiteKing: "white_king",
chess.BlackPawn: "black_pawn",
chess.BlackKnight: "black_knight",
chess.BlackBishop: "black_bishop",
chess.BlackRook: "black_rook",
chess.BlackQueen: "black_queen",
chess.BlackKing: "black_king",
}
fonts map[font]*truetype.Font
)
func init() {
pieceImages = buildImageCache()
pieceVectors = buildVectorCache()
fonts = map[font]*truetype.Font{
firaSans: loadFont("FiraSans-Regular"),
}
}
func buildImageCache() pieceImageCache {
cache := make(pieceImageCache)
for _, style := range pieceStyles {
cache[style] = make(map[chess.Piece]map[size]image.Image)
for piece, name := range pieceNames {
cache[style][piece] = make(map[size]image.Image)
for _, size := range pieceSizes {
f := fmt.Sprintf("/res/%s/png/%s_%d.png", style, name, size)
b := _escFSMustByte(false, f)
var err error
cache[style][piece][size], err = png.Decode(bytes.NewReader(b))
if err != nil {
panic(fmt.Errorf("error building image cache: %v", err))
}
}
}
}
return cache
}
func buildVectorCache() pieceVectorCache {
cache := make(pieceVectorCache)
for _, style := range pieceStyles {
cache[style] = make(map[chess.Piece][]byte)
for piece, name := range pieceNames {
f := fmt.Sprintf("/res/%s/svg/%s.svg", style, name)
s := strings.TrimSpace(_escFSMustString(false, f))
s = s[87 : len(s)-6] // eliminate opening and closing <svg> tag
cache[style][piece] = []byte(s)
}
}
return cache
}
func loadFont(name string) *truetype.Font {
b := _escFSMustByte(false, fmt.Sprintf("/res/font/%s.ttf", name))
f, err := freetype.ParseFont(b)
if err != nil {
panic(fmt.Errorf("error loading font %s: %v", name, err))
}
return f
}
package chessboard
import (
"image"
"image/png"
"io"
"math"
"github.com/golang/freetype"
"golang.org/x/image/draw"
"golang.org/x/image/math/fixed"
"gitlab.com/eightsquared/chess"
)
// WritePNG renders a visual representation of the game g to w in PNG format.
func WritePNG(w io.Writer, g chess.Game, o Options) (err error) {
boardSize := o.Size & (^7)
if boardSize < MinImageSize {
boardSize = MinImageSize
} else if boardSize > MaxImageSize {
boardSize = MaxImageSize
}
rowSize := boardSize >> 3
pieceSize := pieceSizes[len(pieceSizes)-1]
for i := len(pieceSizes) - 2; i >= 0 && int(pieceSizes[i]) > rowSize; i-- {
pieceSize = pieceSizes[i]
}
dstBounds := image.Rectangle{Max: image.Point{boardSize, boardSize}}
squareBounds := image.Rectangle{Max: image.Point{rowSize, rowSize}}
dst := image.NewRGBA(dstBounds)
var light, dark image.Image
light = image.NewUniform(o.Light)
dark = image.NewUniform(o.Dark)
ctx := freetype.NewContext()
ctx.SetDst(dst)
ctx.SetFont(fonts[firaSans])
ctx.SetFontSize(math.Min(MaxFontSize, float64(rowSize)/3.5))
ctx.SetClip(dst.Bounds())
scaledPieceCache := make(map[chess.Piece]*image.RGBA)
var pieceCounts [256]uint8
pieceSet := pieceImages[merida]
for square := chess.First; square <= chess.Last; square++ {
piece := g.Board[square]
if piece == chess.Empty {
continue
}
pieceCounts[piece]++
if pieceCounts[piece] == 2 {
g := pieceSet[piece][pieceSize]
scaled := image.NewRGBA(squareBounds)
draw.ApproxBiLinear.Scale(scaled, scaled.Bounds(), g, g.Bounds(), draw.Src, nil)
scaledPieceCache[piece] = scaled
}
}
for square := chess.First; square <= chess.Last; square++ {
file, rank := square.File(), square.Rank()
x, y := int(file-'a')*rowSize, int('8'-rank)*rowSize
dr := image.Rectangle{image.Point{x, y}, image.Point{x + rowSize, y + rowSize}}
if square.Light() {
draw.Draw(dst, dr, light, image.Point{}, draw.Src)
} else {
draw.Draw(dst, dr, dark, image.Point{}, draw.Src)
}
if file == 'a' || rank == '1' {
fx, fy := x+(rowSize>>4), y+rowSize-(rowSize>>4)
var s string
if file == 'a' && rank > '1' {
s = string(rank)
} else if file > 'a' && rank == '1' {
s = string(file)
} else {
s = string([]byte{byte(file), byte(rank)})
}
if square.Light() {
ctx.SetSrc(dark)
} else {
ctx.SetSrc(light)
}
p := fixed.Point26_6{X: fixed.Int26_6(fx << 6), Y: fixed.Int26_6(fy << 6)}
if _, err = ctx.DrawString(s, p); err != nil {
return
}
}
if piece := g.Board[square]; piece != chess.Empty {
if cached := scaledPieceCache[piece]; cached != nil {
draw.Draw(dst, dr, cached, image.Point{}, draw.Over)
} else {
sourceImage := pieceSet[piece][pieceSize]
draw.ApproxBiLinear.Scale(dst, dr, sourceImage, sourceImage.Bounds(), draw.Over, nil)
}
}
}
err = png.Encode(w, dst)
return
}
package chessboard
import (
"fmt"
"io/ioutil"
"testing"
"gitlab.com/eightsquared/chess"
)
func BenchmarkWritePNG(b *testing.B) {
positions := make([]chess.Game, 1e5)
for i := range positions {
positions[i] = chess.RandomGame(i)
}
cases := []struct {
size int
}{
{500},
{250},
}
test := func(i int) func(*testing.B) {
size := cases[i].size
options := Defaults
options.Size = size
return func(b *testing.B) {
var err error
for i := 0; i < b.N; i++ {
err = WritePNG(ioutil.Discard, positions[i%len(positions)], options)
if err != nil {
b.Fatal(err)
}
}
}
}
for i, c := range cases {
b.Run(fmt.Sprintf("%dpx", c.size), test(i))
}
}
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><g><path d="M256.125 413.875q-3.5 14.25-8.5 19.75t-13.25 11.5q-9 6.25-21.25 10.75-12.25 4.25-27.25 2l-70.25-9.75q-4.25-.5-7.75 0-3.25.5-6.25.5-5.25 0-13.5 2.5-8 2.25-12.5 6.75l-24.25-39.75q4.5-5 8-7t8.25-4.25q14.5-6.75 31-8.25 7-.5 13.75-.25t14-.5q13.5 2.25 27 4.25 13.75 1.75 27.5 3.75 15 0 20.25-3 2.75-1.5 8.75-5.5t12-11.75q-13.25-1.5-27-5-13.75-3.75-24.25-7.75l26-64.5q-19.5-11.25-27.25-18-7.75-7-12.25-16-6.5-11.5-8.5-22.25-1.75-10.75-1.5-19.25.25-15 7-33 7-18.25 26-32.5 15.75-12 30.75-24.75t29.75-29.75q-18.5-9.5-18.5-30.25 0-14 9.75-24 10-10 24.25-10 14 0 24 10t10 24q0 20.5-18.5 30.25 14.5 17 29.25 29.75 15 12.75 31.25 24.75 18.75 14.25 25.5 32.5 6.75 18 7.25 33 0 8.5-1.75 19.25t-8 22.25q-5 9-12.75 16-7.5 6.75-26.75 18l26 64.5q-11 4-24.75 7.75-13.75 3.5-26.5 5 5.75 7.75 11.75 11.75t9 5.5q5.25 3 20.25 3 13.5-2 27-3.75 13.75-2 27.5-4.25 6.75.75 13.5.5 7-.25 14.25.25 16 1.5 31 8.25 4.5 2.25 8 4.25 3.75 2 8.25 7l-24.5 39.75q-4.5-4.5-12.75-6.75-8-2.5-13-2.5-3.25 0-6.75-.5-3.25-.5-7.5 0l-70 9.75q-15 2.25-28-2-12.75-4.25-21-11.25-8.25-6.75-13.25-11.5-4.75-5-8-19.25z"/><path d="M322.625 366.375l-10.5-25.5q-25.5-5.5-56-5.5-30.25 0-55.5 5.5l-10.5 25.25q31-7.75 66-7.75 34.5 0 66.5 8zM301.625 314.875l-7.25-17.5v-6.75q-19-2.75-38.25-2.75-18.75 0-38 2.75l-.25 6.75-6.75 17.5q21.25-3.75 45-3.75 24 0 45.5 3.75zM292.875 409.375q-10-7.5-20-23.75h-8q0 12.25 5.75 23.75zM241.375 409.375q5.75-12.25 5.75-23.75h-8q-9.75 16-20.25 23.75zM246.875 227.875v21.25q0 9.25 9.25 9.25t9.25-9.25v-21.5h22.5q8.75 0 8.75-9t-8.75-9h-22.5v-22.5q0-9.25-9.25-9.25t-9.25 9.25v22.5h-22q-8.75 0-8.75 9t8.75 9z" fill="#fff"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><g><path d="M114.13 381.375l-8.06-46.75q-.243 0-.732-1-1.22-1.75-7.081-4.5-5.617-3-13.187-10-10.745-9.25-16.85-15-5.86-5.75-10.744-12.5-14.897-21-16.606-50.75-2.442-28.75 22.71-57.25 25.397-28.5 68.62-26.75 16.117 1 37.85 8 7.082 3 14.408 6 7.57 2.75 14.896 5.75 3.907 2 6.838 4-1.221-5.25-1.221-10.5 0-19.5 13.43-33.25 13.676-13.75 32.723-14 19.048 0 32.478 14 13.431 13.75 13.431 33 0 4-.976 10.5 3.418-2.25 6.593-3.75 11.233-5 29.548-11.75 21-7.25 37.85-8.25 43.223-2 68.376 26.75 24.664 28.5 22.954 57.25-1.953 29.75-16.85 50.75-4.883 6.75-10.988 12.75-6.105 5.75-16.362 14.75-8.058 7-13.675 10-5.616 2.75-6.593 4.5-.244.5-.488.75t-.244.5l-7.815 47 16.117 61.75q-12.21 11.25-54.7 18.5t-98.167 7.25q-56.654 0-99.633-7.5-42.979-7.75-53.968-19.25z"/><path d="M259.915 315.125q42.002.75 68.864 4.25 26.862 3.5 48.351 8.25 13.43-13.5 29.792-25.75 16.361-12.25 22.955-21 11.721-16.25 11.721-40.5 0-22.25-10.5-37.25-18.803-28.25-57.387-28.25-22.466 0-46.886 10-22.222 9-32.234 19.5-20.756 20.5-30.28 54-3.663 11.5-4.152 29.25-.244 17.75-.244 27.5z" fill="#fff"/><path d="M277.742 295.625q0-7.25 1.465-20.5 1.71-13.5 5.128-21 9.035-20.25 25.885-37.5 4.884-5 21.001-13.5 15.873-8 33.943-8 13.675 0 27.106 5 13.675 4.75 20.513 14.75 6.105 8.5 6.105 27.5 0 15-11.966 28-7.814 8.25-16.85 16.75-9.035 8.25-17.337 19.5-14.164-5-39.56-7.75-25.153-2.75-55.433-3.25z"/><path d="M371.758 358.375q-44.933-12.75-119.657-12.75-75.213 0-121.122 13l3.663 25.25q46.153-12.25 117.459-12.25 71.061 0 115.75 12zM378.107 433.125l-7.326-29.5q-47.619-11.25-119.657-11.25-71.306 0-119.168 11.25l-7.815 29.75q46.398-14.5 127.227-14.5 38.828 0 72.039 4 33.21 4 54.7 10.25zM242.333 314.875q0-10-.488-27.5-.489-17.75-3.663-29.5-10.012-33.5-30.28-54-10.501-10.5-32.235-19.5-24.908-10-47.13-10-38.583 0-57.142 28.25-10.5 15-10.5 37.5 0 24.5 11.72 40.25 6.106 9 23.444 22.25t29.303 24.5q21.246-4.75 47.863-8.25 26.862-3.5 69.108-4zM251.124 252.125q1.71-7 2.93-9.75 2.443-9.75 5.617-16.5 1.465-4.25 4.151-9.75 2.93-5.75 6.105-13 1.954-4.25 4.152-10.25 2.198-6.25 4.395-12.25 1.954-5 1.954-10.75 0-12.25-8.547-20.75-8.547-8.75-20.757-8.75-29.06 0-29.06 29.75 0 5.75 1.954 10.75 5.373 16.25 8.303 22.5 3.175 7.25 5.86 13 2.687 5.5 4.64 9.75 3.175 8.25 5.373 16.5.488 1.5 2.93 9.5z" fill="#fff"/><path d="M259.671 122.125h-17.338v-32.75h-20.268q-8.303 0-8.303-8.25v-.25q0-8.25 8.303-8.25h20.268v-21.25q0-8.75 8.791-8.75 8.547 0 8.547 8.75v21.25h21.001q8.059 0 8.059 8.25v.25q0 8.25-8.059 8.25l-20.757.25zM223.774 295.625q-30.525.5-55.921 3.25-25.153 2.75-39.072 7.75-7.326-9.25-17.094-18.5-9.523-9.5-16.85-17.75-12.21-12.75-12.21-28 0-18.75 6.106-27.5 6.593-10 20.268-14.75 13.675-5 27.595-5 17.582 0 33.699 8 15.873 8.5 21 13.5 16.606 17.25 25.886 37.5 3.174 7.5 4.64 21 1.709 13.25 1.953 20.5zM251.124 209.375q-.488-2.5-1.22-4.25-1.466-5-2.443-7.25-.732-1.75-1.953-4.25-1.221-2.75-2.442-5.75-.733-1.75-1.954-4.5-.977-3-1.71-5.5-.732-2.25-.732-4.75 0-13.25 12.454-13.25 12.943 0 12.943 13 0 3.25-.977 4.75-3.419 9.5-3.663 10.25-3.663 7.5-4.64 9.75-1.71 4-2.198 7.25-.732 1.5-.976 2.75-.245 1-.489 1.75z"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><g><path d="M269.875 87.625q39.25 2.5 72.75 20.25t57 45.5q16.5 19.5 31 47 14.75 27.5 23.5 58.25 10 35.75 12.5 75.25 2.75 39.25 2.75 72.75v54.5h-307.5q-2.25 0-2.25-12.25.25-12.25 1.75-19.75 1-6 4.75-17t12.5-26.75q4-8 19-23.25 15-15.5 34.5-35.75 11.25-11.5 17.5-29 6.5-17.5 5.5-31.75-9.25 7.5-20.25 12.25-53 19-76.75 55-1.75 2.25-11.25 20.25-5 9.5-8.5 13-4.75 4.75-13.75 5.25-14 .75-21.75-13.5-10.5 3-18.75 2.5-14-5.25-20.25-11.25-12.75-12.75-16.75-25.5-3.75-12.75-3.75-27.5 0-21 26-55.5 30.5-39.75 32.5-60.5 0-9 1.75-20.25 1.5-7.75 6.25-15 3.25-5 4.25-6.75 1.25-2 4.25-5.75 2.25-3 3.75-4.5 1.5-1.75 3.75-4.5 2.75-3.25 7-7.5-13.25-36.5-10.75-75.25 49.75 17.75 83.5 55.75 8.25-28.25 32.5-45.75 20 14 31.75 37z"/><path d="M122.625 341.125q1-2.25 3.25-6.75 4.25-10.5 4.25-12.5-.5-7-7.25-7-5 0-11.75 14.25-1 2-3 3.5-6.75 7 2 11.75 8 4.75 12.5-3.25zM270.125 248.375q17.5-23 17.25-51.25-1-8.25-9.5-8.25-11.5 0-9 8.5.75 13.75-2.75 22.75-5.75 14.25-12.75 21.25-3.75 7.5 4.5 11 8 3.75 12.25-4zM204.875 126.375q-1.25-9 .5-19.5-15 3-28.25 14-8 4.25-3.75 11.75 4.25 7.75 11.75 2.5 5.25-2.75 9.5-5 4.5-2.5 10.25-3.75zM439.125 443.375q-.25 0 .5-13.5.75-13.75.75-29.5.25-31.25 0-64.5-.25-33.5-9-66.75-8.5-32-18.75-54.5-10.25-22.75-22.25-39.25-18-27-49-45.75t-64.75-24.5q1 5.75.5 11.75-.25 6 .25 11.5 24.25 8.25 45.75 20.5t31.5 26.5q12 16.5 22.25 39.25 10.25 22.5 18.75 54.5 8.5 33.25 8.75 66.75.25 33.25.25 64.5 0 15.75-.75 29.5-.75 13.5 0 13.5zM101.125 296.625q7.25-5 1.5-12-6-5.75-13.25-1-15.25 10-16.25 26.25.25 8.25 9.75 7.75 9-.75 8.75-9.25 2-8 9.5-11.75zM164.125 172.125l5.5-2.75q7.5-3 4.75-11-3-7.5-11.5-5-29.5 10.75-40.75 39.5-1.75 8.25 6 11.25 7.75 2.5 10.5-5.5 2-4.25 3-5.5 2.75 2.25 7.25 3 15.25 2.5 17.75-13.5.75-5.5-2.5-10.5z" fill="#fff"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path d="M256.125 460.625h-135q-10-25-10-52.25 0-46.25 26.25-83t67.5-52.5q-17.75-8.25-29-24.75-11-16.75-11-37.75 0-26.25 17.5-45.5t43-22.25q-20.25-15.25-20.25-40.25 0-21 14.75-36 15-15 36.25-15 21 0 36 15t15 36q0 25-20.25 40.25 25.5 3 43 22.25t17.5 45.5q0 21-11.5 37.75-11.25 16.5-28.75 24.75 41.25 15.75 67.5 52.5t26.25 83q0 27-9.75 52.25z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><g><path d="M410.125 441.125q-12.25 10.75-55 18t-98.5 7.25q-56.75 0-99.75-7.5t-54.25-18.75l15.75-60-7-39.25-22-38.25-21.25-155.5 12.25-4.75 68.5 115.5 1.5-137.5 17-3 52.25 138.25 28-148.75h17.25l28 148.25 51.75-137.75 17.25 3 1.5 137.5 68.75-115.75 11.75 5.5-20.75 154.75-22.25 38.25-7 39.75z"/><path d="M397.125 313.625q-20.75-7.5-58.5-12.25-37.5-5-83-5-44.5 0-81.5 4.75-37 4.5-58.25 12l12.5 22.75q21-6.25 54.5-9t73.25-2.75q39.75 0 73.5 2.75t54.75 9.25z" fill="#fff"/><path d="M453.625 146.625q-14.25 0-24.25-9.75-10-10-10-24.25 0-14 10-24 10-10.25 24.25-10.25 14 0 24 10.25 10 10 10 24 0 14.25-10 24.25-10 9.75-24 9.75zM59.125 146.625q-14.25 0-24.25-9.75-9.75-10-9.75-24.25 0-14 9.75-24 10-10.25 24.25-10.25t24.25 10.25q10 10 10 24 0 14.25-10 24.25-10 9.75-24.25 9.75zM361.125 119.125q-14.25 0-24.25-9.75-9.75-10-9.75-24.25 0-14 9.75-24 10-10 24.25-10t24.25 10q10 10 10 24 0 14.25-10 24.25-10 9.75-24.25 9.75zM151.125 119.125q-14.25 0-24.25-9.75-10-10-10-24.25 0-14 10-24t24.25-10q14 0 24 10t10 24q0 14.25-10 24.25-10 9.75-24 9.75z"/><path d="M386.125 433.125l-7.5-29.5q-48.75-11.25-122.5-11.25-73 0-122 11.25l-8 29.75q47.5-14.5 130.25-14.5 39.75 0 73.75 4t56 10.25zM379.625 358.375q-46-12.75-122.5-12.75-77 0-124 13l3.75 25.25q47.25-12.25 120.25-12.25 72.75 0 118.5 12z" fill="#fff"/><path d="M256.125 106.625q-14.25 0-24.25-10-9.75-10-9.75-24.25 0-14 9.75-24 10-10 24.25-10 14 0 24 10 10.25 10 10.25 24 0 14.25-10.25 24.25-10 10-24 10z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><g><path d="M288.375 85.375h42.5v-34.25h68.5v93.75l-55.5 42.75v119.5l42.5 42.5v51.25h38.25v59.75H83.375v-59.75h38.25v-51.25l42.75-42.5v-119.5l-55.5-42.75v-93.75h68.25v34.25h42.75v-34.25h68.5z"/><path d="M139.125 396.875v25.5h230v-25.5zM254.125 123.875h-128v11.5l18.25 13.75h219.75l17.75-13.75v-11.5zM254.125 166.125h-87.5l15 11.75v14.25h145v-14.25l15-11.75zM254.125 302.625h-72.5v11.5l-15 14.5h175l-15-14.5v-11.5zM254.125 345.625h-103.5l-11.5 10.75v14.5h230v-14.5l-11.5-10.75z" fill="#fff"/></g></svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 512 512"
version="1.1"
id="svg8"
sodipodi:docname="black_bishop.svg"
inkscape:version="0.92.1 r15371">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.2910156"
inkscape:cx="256"
inkscape:cy="256"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="true"
inkscape:window-width="1329"
inkscape:window-height="843"
inkscape:window-x="263"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Chess Merida';-inkscape-font-specification:'Chess Merida';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:12.80000591"
d="m 256.12498,575.40842 q -3.49999,14.25005 -8.49997,19.75002 -5.00001,5.50001 -13.25001,11.50002 -9,6.25002 -21.25,10.75 -12.25,4.25001 -27.25,2.00002 l -70.25,-9.75002 q -4.25,-0.5 -7.75,0 -3.25,0.49999 -6.25,0.49999 -5.250002,0 -13.5,2.50001 -8.000002,2.24999 -12.500002,6.75002 L 51.375,579.65843 q 4.499996,-4.99998 7.999998,-6.99999 3.500001,-2.00002 8.249998,-4.25001 14.500004,-6.75002 31.000001,-8.25 7.000003,-0.49999 13.750003,-0.24983 6.75,0.24983 14,-0.49999 13.5,2.24999 27,4.25001 13.75,1.75 27.5,3.75001 15,0 20.25,-3 2.75,-1.50002 8.75,-5.50001 6,-4 12,-11.75004 -13.25,-1.49998 -27,-4.99998 -13.75,-3.75001 -24.25,-7.75 l 26,-64.50008 q -19.5,-11.25 -27.25,-18.00002 -7.75,-6.99999 -12.25,-16 -6.5,-11.50002 -8.5,-22.25002 -1.75,-10.75001 -1.5,-19.25002 0.25001,-15.00002 7,-33.00004 7,-18.24999 26,-32.49999 15.75,-12.00002 30.75,-24.75004 15,-12.75002 29.74999,-29.75005 -18.49999,-9.5 -18.49999,-30.25 0,-14.00003 9.75,-24.00003 9.99999,-9.99999 24.24998,-9.99999 14.00001,0 24,9.99999 10.00003,10 10.00003,24.00003 0,20.50002 -18.5,30.25 14.49997,17.00003 29.25,29.75005 15,12.75002 31.25,24.75004 18.74997,14.25 25.49998,32.49999 6.75001,18.00002 7.25001,33.00004 0,8.50001 -1.75,19.25002 -1.75,10.75 -8.00001,22.25002 -4.99998,9.00001 -12.74998,16 -7.50002,6.75002 -26.75002,18.00002 L 341.625,534.4086 q -11.00001,3.99999 -24.75001,7.75 -13.74999,3.5 -26.5,4.99998 5.75002,7.75004 11.75002,11.75004 6,3.99999 9,5.50001 5.24999,3 20.24999,3 13.49998,-2.00001 27,-3.75001 13.75,-2.00002 27.5,-4.25001 6.75001,0.75001 13.49998,0.49999 7.00002,-0.24982 14.25003,0.24983 15.99999,1.49998 30.99999,8.25 4.49998,2.24999 8.00001,4.25001 3.74997,2.00001 8.24999,6.99999 l -24.49999,39.75005 q -4.50002,-4.50003 -12.75001,-6.75002 -8.00002,-2.50001 -12.99999,-2.50001 -3.25002,0 -6.75001,-0.49999 -3.25002,-0.5 -7.50002,0 l -69.99999,9.75002 q -15,2.24999 -27.99999,-2.00002 -12.75001,-4.25 -21,-11.25 -8.24999,-6.75001 -13.25001,-11.50002 -4.74999,-4.99997 -8.00001,-19.25002 z"
id="path4553"
inkscape:connector-curvature="0" />
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Chess Merida';-inkscape-font-specification:'Chess Merida';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:12.80000591"
d="M 322.62502,527.90841 312.125,502.40837 q -25.50002,-5.50001 -56.00002,-5.50001 -30.24998,0 -55.49998,5.50001 l -10.5,25.25002 q 31,-7.75 65.99998,-7.75 34.50002,0 66.50004,8.00002 z"
id="path4561"
inkscape:connector-curvature="0" />
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Chess Merida';-inkscape-font-specification:'Chess Merida';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:12.80000591"
d="m 301.62501,476.40837 -7.25,-17.50002 v -6.75002 q -19.00002,-2.74999 -38.25003,-2.74999 -18.74997,0 -37.99998,2.74999 l -0.25002,6.75002 -6.75,17.50002 q 21.25,-3.75001 45,-3.75001 24,0 45.5,3.75001 z"
id="path4559"
inkscape:connector-curvature="0" />
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Chess Merida';-inkscape-font-specification:'Chess Merida';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:12.80000591"
d="M 292.87499,570.90844 Q 282.875,563.40841 272.87502,547.15839 H 264.875 q 0,12.25003 5.74999,23.75005 z"
id="path4557"
inkscape:connector-curvature="0" />
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Chess Merida';-inkscape-font-specification:'Chess Merida';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:12.80000591"
d="m 241.375,570.90844 q 5.74998,-12.25003 5.74998,-23.75005 h -7.99997 Q 229.375,563.15843 218.875,570.90844 Z"
id="path4555"
inkscape:connector-curvature="0" />
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Chess Merida';-inkscape-font-specification:'Chess Merida';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:12.80000591"
d="m 246.875,389.40829 v 21.25 q 0,9.25002 9.24998,9.25002 v 0 q 9.25002,0 9.25002,-9.25002 v -21.50002 h 22.50002 q 8.74998,0 8.74998,-9.00001 v 0 q 0,-9.00001 -8.74998,-9.00001 H 265.375 v -22.5 q 0,-9.25002 -9.25002,-9.25002 v 0 q -9.24998,0 -9.24998,9.25002 v 22.5 h -22 q -8.75,0 -8.75,9.00001 v 0 q 0,9.00001 8.75,9.00001 z"
id="path4547"
inkscape:connector-curvature="0" />
</g>