diff --git a/assets/1024px-Chess_bdd45.svg.png b/assets/1024px-Chess_bdd45.svg.png deleted file mode 100644 index 1bcc8eb..0000000 Binary files a/assets/1024px-Chess_bdd45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_bdl45.svg.png b/assets/1024px-Chess_bdl45.svg.png deleted file mode 100644 index 56afea9..0000000 Binary files a/assets/1024px-Chess_bdl45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_bld45.svg.png b/assets/1024px-Chess_bld45.svg.png deleted file mode 100644 index 92d84f6..0000000 Binary files a/assets/1024px-Chess_bld45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_bll45.svg.png b/assets/1024px-Chess_bll45.svg.png deleted file mode 100644 index 7790a7b..0000000 Binary files a/assets/1024px-Chess_bll45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_kdd45.svg.png b/assets/1024px-Chess_kdd45.svg.png deleted file mode 100644 index 1637525..0000000 Binary files a/assets/1024px-Chess_kdd45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_kdl45.svg.png b/assets/1024px-Chess_kdl45.svg.png deleted file mode 100644 index 2282999..0000000 Binary files a/assets/1024px-Chess_kdl45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_kdt45.svg.png b/assets/1024px-Chess_kdt45.svg.png new file mode 100644 index 0000000..99bdd4c Binary files /dev/null and b/assets/1024px-Chess_kdt45.svg.png differ diff --git a/assets/1024px-Chess_kld45.svg.png b/assets/1024px-Chess_kld45.svg.png deleted file mode 100644 index e082d76..0000000 Binary files a/assets/1024px-Chess_kld45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_kll45.svg.png b/assets/1024px-Chess_kll45.svg.png deleted file mode 100644 index b0dd66a..0000000 Binary files a/assets/1024px-Chess_kll45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_klt45.svg.png b/assets/1024px-Chess_klt45.svg.png new file mode 100644 index 0000000..8fe1deb Binary files /dev/null and b/assets/1024px-Chess_klt45.svg.png differ diff --git a/assets/1024px-Chess_ndd45.svg.png b/assets/1024px-Chess_ndd45.svg.png deleted file mode 100644 index c0252af..0000000 Binary files a/assets/1024px-Chess_ndd45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_ndl45.svg.png b/assets/1024px-Chess_ndl45.svg.png deleted file mode 100644 index fbcf294..0000000 Binary files a/assets/1024px-Chess_ndl45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_nld45.svg.png b/assets/1024px-Chess_nld45.svg.png deleted file mode 100644 index cd9271f..0000000 Binary files a/assets/1024px-Chess_nld45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_nll45.svg.png b/assets/1024px-Chess_nll45.svg.png deleted file mode 100644 index 48e0785..0000000 Binary files a/assets/1024px-Chess_nll45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_pdd45.svg.png b/assets/1024px-Chess_pdd45.svg.png deleted file mode 100644 index 9d9896f..0000000 Binary files a/assets/1024px-Chess_pdd45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_pdl45.svg.png b/assets/1024px-Chess_pdl45.svg.png deleted file mode 100644 index 7c5e23e..0000000 Binary files a/assets/1024px-Chess_pdl45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_pld45.svg.png b/assets/1024px-Chess_pld45.svg.png deleted file mode 100644 index 2da9ef5..0000000 Binary files a/assets/1024px-Chess_pld45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_pll45.svg.png b/assets/1024px-Chess_pll45.svg.png deleted file mode 100644 index a80ba8f..0000000 Binary files a/assets/1024px-Chess_pll45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_qdd45.svg.png b/assets/1024px-Chess_qdd45.svg.png deleted file mode 100644 index eed2714..0000000 Binary files a/assets/1024px-Chess_qdd45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_qdl45.svg.png b/assets/1024px-Chess_qdl45.svg.png deleted file mode 100644 index f48988e..0000000 Binary files a/assets/1024px-Chess_qdl45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_qld45.svg.png b/assets/1024px-Chess_qld45.svg.png deleted file mode 100644 index 5b1af01..0000000 Binary files a/assets/1024px-Chess_qld45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_qll45.svg.png b/assets/1024px-Chess_qll45.svg.png deleted file mode 100644 index 18f6932..0000000 Binary files a/assets/1024px-Chess_qll45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_rdd45.svg.png b/assets/1024px-Chess_rdd45.svg.png deleted file mode 100644 index fc32915..0000000 Binary files a/assets/1024px-Chess_rdd45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_rdl45.svg.png b/assets/1024px-Chess_rdl45.svg.png deleted file mode 100644 index aa48db8..0000000 Binary files a/assets/1024px-Chess_rdl45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_rld45.svg.png b/assets/1024px-Chess_rld45.svg.png deleted file mode 100644 index deadd58..0000000 Binary files a/assets/1024px-Chess_rld45.svg.png and /dev/null differ diff --git a/assets/1024px-Chess_rll45.svg.png b/assets/1024px-Chess_rll45.svg.png deleted file mode 100644 index a6c96dd..0000000 Binary files a/assets/1024px-Chess_rll45.svg.png and /dev/null differ diff --git a/chess/board.go b/chess/board.go new file mode 100644 index 0000000..ade7ff2 --- /dev/null +++ b/chess/board.go @@ -0,0 +1,153 @@ +package chess + +import ( + "fmt" + "image" + "image/draw" + "image/png" + "log" + "os" +) + +type Board struct { + tiles [8][8]*Piece +} + +func NewBoard() *Board { + board := &Board{} + + board.mustSetPiece(Rook, Light, "a1") + board.mustSetPiece(Knight, Light, "b1") + board.mustSetPiece(Bishop, Light, "c1") + board.mustSetPiece(Queen, Light, "d1") + board.mustSetPiece(King, Light, "e1") + board.mustSetPiece(Bishop, Light, "f1") + board.mustSetPiece(Knight, Light, "g1") + board.mustSetPiece(Rook, Light, "h1") + board.mustSetPiece(Pawn, Light, "a2") + board.mustSetPiece(Pawn, Light, "b2") + board.mustSetPiece(Pawn, Light, "c2") + board.mustSetPiece(Pawn, Light, "d2") + board.mustSetPiece(Pawn, Light, "e2") + board.mustSetPiece(Pawn, Light, "f2") + board.mustSetPiece(Pawn, Light, "g2") + board.mustSetPiece(Pawn, Light, "h2") + + board.mustSetPiece(Rook, Dark, "a8") + board.mustSetPiece(Knight, Dark, "b8") + board.mustSetPiece(Bishop, Dark, "c8") + board.mustSetPiece(Queen, Dark, "d8") + board.mustSetPiece(King, Dark, "e8") + board.mustSetPiece(Bishop, Dark, "f8") + board.mustSetPiece(Knight, Dark, "g8") + board.mustSetPiece(Rook, Dark, "h8") + board.mustSetPiece(Pawn, Dark, "a7") + board.mustSetPiece(Pawn, Dark, "b7") + board.mustSetPiece(Pawn, Dark, "c7") + board.mustSetPiece(Pawn, Dark, "d7") + board.mustSetPiece(Pawn, Dark, "e7") + board.mustSetPiece(Pawn, Dark, "f7") + board.mustSetPiece(Pawn, Dark, "g7") + board.mustSetPiece(Pawn, Dark, "h7") + + return board +} + +func (b *Board) Save(filename string) error { + var ( + file *os.File + img *image.RGBA + piece *Piece + bg *image.Uniform + rect image.Rectangle + p = image.Point{0, 0} + err error + ) + + if file, err = os.Create(filename); err != nil { + return err + } + defer file.Close() + + img = image.NewRGBA(image.Rect(0, 0, 1024, 1024)) + + for yi := 0; yi < 8; yi++ { + for xi := 0; xi < 8; xi++ { + rect = image.Rect(xi*128, yi*128, (xi*128)+128, (yi*128)+128) + bg = image.NewUniform(getTileColor(xi, yi)) + draw.Draw(img, rect, bg, p, draw.Src) + + piece = b.tiles[xi][yi] + if piece != nil { + draw.Draw(img, rect, piece.Image, p, draw.Over) + } + } + } + + return png.Encode(file, img) +} + +func (b *Board) SetPiece(name PieceName, color Color, position string) error { + var ( + piece *Piece + x int + y int + err error + ) + + if len(position) != 2 { + return fmt.Errorf("invalid position: %s", position) + } + + if piece, err = NewPiece(name, color); err != nil { + return err + } + + if x, y, err = getXY(position); err != nil { + return err + } + + b.tiles[x][y] = piece + + return nil +} + +func (b *Board) mustSetPiece(name PieceName, color Color, position string) { + if err := b.SetPiece(name, color, position); err != nil { + log.Fatalf("cannot set piece %s: %v", name, err) + } +} + +func getXY(position string) (int, int, error) { + var ( + posX rune + posY rune + x int + y int + ) + runes := []rune(position) + posX = runes[0] + posY = runes[1] + + if posX < 'a' && posX > 'h' { + return -1, -1, fmt.Errorf("invalid posX: %s", position) + } + + if posY < '1' && posY > '8' { + return -1, -1, fmt.Errorf("invalid posY: %s", position) + } + + // image origin (0,0) is at top-left corner (a8) + x = int(posX - 'a') + y = int('8' - posY) + + return x, y, nil +} + +func getTileColor(x, y int) Color { + if x%2 == y%2 { + return Light + } else { + return Dark + } +} diff --git a/chess/piece.go b/chess/piece.go new file mode 100644 index 0000000..d3ce93b --- /dev/null +++ b/chess/piece.go @@ -0,0 +1,73 @@ +package chess + +import ( + "fmt" + "image" + "image/color" + "image/png" + "os" + + "golang.org/x/image/draw" +) + +type Piece struct { + Name PieceName + Color color.Color + Image image.Image +} + +type PieceName string + +const ( + Pawn PieceName = "p" + Knight PieceName = "n" + Bishop PieceName = "b" + Rook PieceName = "r" + Queen PieceName = "q" + King PieceName = "k" +) + +type Color color.Color + +var ( + Light Color = color.RGBA{240, 217, 181, 255} + Dark Color = color.RGBA{181, 136, 99, 255} +) + +func NewPiece(name PieceName, color Color) (*Piece, error) { + var ( + colorSuffix string + path string + file *os.File + img image.Image + dst *image.RGBA + err error + ) + + colorSuffix = "l" + if color == Light { + colorSuffix = "l" + } else if color == Dark { + colorSuffix = "d" + } else { + return nil, fmt.Errorf("invalid color: %v", color) + } + + path = fmt.Sprintf("assets/1024px-Chess_%s%st45.svg.png", name, colorSuffix) + + if file, err = os.Open(path); err != nil { + return nil, err + } + defer file.Close() + + if img, err = png.Decode(file); err != nil { + return nil, err + } + + // source image for each piece is 1024x1024 and board is 8x8 + // so we need to scale each piece down to 128x128 (1024/8) + dst = image.NewRGBA(image.Rect(0, 0, 128, 128)) + draw.CatmullRom.Scale(dst, dst.Rect, img, img.Bounds(), draw.Over, nil) + + return &Piece{Name: name, Color: color, Image: dst}, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..6023b10 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/ekzyis/sn-chess + +go 1.23.0 + +require golang.org/x/image v0.20.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..135955a --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw= +golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..9c39b94 --- /dev/null +++ b/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "github.com/ekzyis/sn-chess/chess" +) + +func main() { + var ( + b = chess.NewBoard() + ) + + b.Save("board.png") +}