mirror of
https://github.com/maaslalani/gambit.git
synced 2024-11-24 08:22:12 +02:00
holy shit
This commit is contained in:
parent
139ce2b1a1
commit
c3744d422c
@ -1,29 +0,0 @@
|
||||
package board
|
||||
|
||||
import (
|
||||
"github.com/maaslalani/gambit/piece"
|
||||
"github.com/maaslalani/gambit/position"
|
||||
)
|
||||
|
||||
type Board struct {
|
||||
// The board is represented as a 2D array of cells.
|
||||
// The first index is the row, the second is the column.
|
||||
Grid [8][8]piece.Piece
|
||||
Reversed bool
|
||||
Selected position.Position
|
||||
Turn piece.Color
|
||||
}
|
||||
|
||||
func New() Board {
|
||||
ep := piece.Empty()
|
||||
er := [8]piece.Piece{ep, ep, ep, ep, ep, ep, ep, ep}
|
||||
return Board{
|
||||
Grid: [8][8]piece.Piece{er, er, er, er, er, er, er, er},
|
||||
Turn: piece.White,
|
||||
Selected: position.NoPosition,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Board) At(p position.Position) piece.Piece {
|
||||
return b.Grid[p.Row][p.Col]
|
||||
}
|
121
board/fen.go
121
board/fen.go
@ -1,121 +0,0 @@
|
||||
package board
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/maaslalani/gambit/piece"
|
||||
)
|
||||
|
||||
// FromFen parses a FEN string and returns a Board with the corresponding
|
||||
// attributes and pieces
|
||||
func FromFen(fen string) (Board, error) {
|
||||
var b Board = New()
|
||||
|
||||
// Split the FEN string into its component parts
|
||||
parts := strings.Split(fen, " ")
|
||||
|
||||
// 1. Piece placement (from White's perspective). Each rank
|
||||
// is described, starting with rank 8 and ending with rank 1;
|
||||
// within each rank, the contents of each square are described
|
||||
// from file "a" through file "h". Following the Standard
|
||||
// Algebraic Notation (SAN), each piece is identified by a
|
||||
// single letter taken from the standard English names (pawn =
|
||||
// "P", knight = "N", bishop = "B", rook = "R", queen = "Q" and
|
||||
// king = "K"). White pieces are designated using upper-case
|
||||
// letters ("PNBRQK") while black pieces use lowercase
|
||||
// ("pnbrqk"). Empty squares are noted using digits 1 through 8
|
||||
// (the number of empty squares), and "/" separates ranks.
|
||||
ranks := strings.Split(parts[0], "/")
|
||||
for r, rank := range ranks {
|
||||
col := 0
|
||||
for _, char := range rank {
|
||||
if char >= '1' && char <= '8' {
|
||||
col += int(char - '0')
|
||||
continue
|
||||
}
|
||||
p := piece.FromFen(string(char))
|
||||
b.Grid[7-r][col] = p
|
||||
col += 1
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Active color.
|
||||
// "w" means White moves next, "b" means Black moves next.
|
||||
b.Turn = piece.Color(parts[1])
|
||||
|
||||
// 3. Castling availability.
|
||||
// If neither side can castle, this is "-". Otherwise, this has one or more
|
||||
// letters: "K" (White can castle kingside), "Q" (White can castle queenside),
|
||||
// "k" (Black can castle kingside), and/or "q" (Black can castle queenside). A
|
||||
// move that temporarily prevents castling does not negate this notation.
|
||||
|
||||
// 4. En passant target square in algebraic notation.
|
||||
// If there's no en passant target square, this is "-". If a pawn has just
|
||||
// made a two-square move, this is the position "behind" the pawn. This is
|
||||
// recorded regardless of whether there is a pawn in position to make an en
|
||||
// passant capture.
|
||||
|
||||
// 5. Halfmove clock.
|
||||
// The number of halfmoves since the last capture or pawn advance, used for
|
||||
// the fifty-move rule.
|
||||
|
||||
// 6. Fullmove number.
|
||||
// The number of the full move. It starts at 1, and is incremented after
|
||||
// Black's move.
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// ToFen converts a board into a FEN string
|
||||
func (b Board) ToFen() string {
|
||||
var sb strings.Builder
|
||||
// Loop through the entire board and build the FEN string for each rank
|
||||
// The FEN string is built from the bottom up, so we need to reverse the grid
|
||||
for r := len(b.Grid) - 1; r >= 0; r-- {
|
||||
// Track the number of empty squares we have encountered so far before reaching a
|
||||
// non-empty square, dump this count as a replacement for pieces
|
||||
emptyCounter := 0
|
||||
// Loop through each column in the rank and convert it to its FEN equivalent
|
||||
for c := 0; c < len(b.Grid[r]); c++ {
|
||||
p := b.Grid[r][c]
|
||||
if p.Color == piece.NoColor {
|
||||
// Empty square
|
||||
emptyCounter += 1
|
||||
} else {
|
||||
// If we have encountered an empty square, dump the number of
|
||||
// empty squares we have encountered so far
|
||||
if emptyCounter > 0 {
|
||||
sb.WriteString(strconv.Itoa(emptyCounter))
|
||||
emptyCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Display the piece's Fen representation
|
||||
sb.WriteString(p.ToFen())
|
||||
}
|
||||
|
||||
// If we have reached the end of the rank and we have encountered
|
||||
// empty squares dump the number of empty squares
|
||||
if emptyCounter > 0 {
|
||||
sb.WriteString(strconv.Itoa(emptyCounter))
|
||||
emptyCounter = 0
|
||||
}
|
||||
|
||||
if r > 0 {
|
||||
sb.WriteRune('/')
|
||||
}
|
||||
}
|
||||
|
||||
sb.WriteString(" " + string(b.Turn) + " ")
|
||||
|
||||
// TODO: Add castling
|
||||
sb.WriteString("KQkq")
|
||||
|
||||
// TODO: Add En passant target squares
|
||||
sb.WriteString(" - ")
|
||||
|
||||
// TODO: Add halfmove + fullmove clock
|
||||
sb.WriteString("0 1")
|
||||
return sb.String()
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package board_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/maaslalani/gambit/board"
|
||||
. "github.com/maaslalani/gambit/piece"
|
||||
)
|
||||
|
||||
func TestFen(t *testing.T) {
|
||||
fen := "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
||||
grid := [8][8]Piece{
|
||||
{RW, NW, BW, QW, KW, BW, NW, RW},
|
||||
{PW, PW, PW, PW, PW, PW, PW, PW},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{PB, PB, PB, PB, PB, PB, PB, PB},
|
||||
{RB, NB, BB, QB, KB, BB, NB, RB},
|
||||
}
|
||||
b := board.Board{
|
||||
Grid: grid,
|
||||
Turn: White,
|
||||
}
|
||||
|
||||
if b.ToFen() != fen {
|
||||
t.Errorf("ToFen()\nActual = %s\nTarget = %s", b.ToFen(), fen)
|
||||
}
|
||||
|
||||
fromFen, _ := board.FromFen(fen)
|
||||
if fromFen.ToFen() != fen {
|
||||
t.Errorf("FromFen()\nActual = %s\nTarget = %s", fromFen.ToFen(), fen)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFenMoved(t *testing.T) {
|
||||
fen := "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1"
|
||||
grid := [8][8]Piece{
|
||||
{RW, NW, BW, QW, KW, BW, NW, RW},
|
||||
{PW, PW, PW, PW, OO, PW, PW, PW},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{OO, OO, OO, OO, PW, OO, OO, OO},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{OO, OO, OO, OO, OO, OO, OO, OO},
|
||||
{PB, PB, PB, PB, PB, PB, PB, PB},
|
||||
{RB, NB, BB, QB, KB, BB, NB, RB},
|
||||
}
|
||||
b := board.Board{
|
||||
Grid: grid,
|
||||
Turn: White,
|
||||
}
|
||||
|
||||
if b.ToFen() != fen {
|
||||
t.Errorf("ToFen()\nActual = %s\nTarget = %s", b.ToFen(), fen)
|
||||
}
|
||||
|
||||
fromFen, _ := board.FromFen(fen)
|
||||
if fromFen.ToFen() != fen {
|
||||
t.Errorf("FromFen()\nActual = %s\nTarget = %s", fromFen, fen)
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package board
|
||||
|
||||
import (
|
||||
"github.com/maaslalani/gambit/piece"
|
||||
"github.com/maaslalani/gambit/position"
|
||||
"github.com/maaslalani/gambit/squares"
|
||||
)
|
||||
|
||||
type Move struct {
|
||||
From squares.Square
|
||||
To squares.Square
|
||||
}
|
||||
|
||||
func (b *Board) Move(m Move) {
|
||||
f := position.ToPosition(m.From)
|
||||
t := position.ToPosition(m.To)
|
||||
b.Grid[t.Row][t.Col] = b.Grid[f.Row][f.Col]
|
||||
b.Grid[f.Row][f.Col] = piece.Empty()
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package board
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/maaslalani/gambit/squares"
|
||||
)
|
||||
|
||||
func TestMove(t *testing.T) {
|
||||
initial := "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
||||
tests := []struct {
|
||||
board string
|
||||
moves []Move
|
||||
expected string
|
||||
}{
|
||||
{initial, []Move{{E2, E4}}, "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1"},
|
||||
{initial, []Move{{A7, A6}}, "rnbqkbnr/1ppppppp/p7/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"},
|
||||
{initial, []Move{{G1, F3}}, "rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R w KQkq - 0 1"},
|
||||
{initial, []Move{{E2, E4}, {C7, C5}, {G1, F3}}, "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 0 1"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
b, _ := FromFen(tc.board)
|
||||
for _, move := range tc.moves {
|
||||
b.Move(move)
|
||||
}
|
||||
if b.ToFen() != tc.expected {
|
||||
t.Errorf("\nwant %s\ngot %s", tc.expected, b.ToFen())
|
||||
// t.Log(b)
|
||||
}
|
||||
}
|
||||
}
|
80
game/game.go
80
game/game.go
@ -1,27 +1,43 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/maaslalani/gambit/board"
|
||||
dt "github.com/dylhunn/dragontoothmg"
|
||||
"github.com/maaslalani/gambit/piece"
|
||||
"github.com/maaslalani/gambit/position"
|
||||
. "github.com/maaslalani/gambit/squares"
|
||||
)
|
||||
|
||||
type model struct {
|
||||
board board.Board
|
||||
moves []board.Move
|
||||
board dt.Board
|
||||
}
|
||||
|
||||
func Model() tea.Model {
|
||||
b, _ := board.FromFen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
|
||||
board := dt.ParseFen("rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR w KQkq - 0 1")
|
||||
return model{
|
||||
board: b,
|
||||
board: board,
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd { return nil }
|
||||
func (m model) View() string { return m.board.String() }
|
||||
|
||||
func (m model) View() string {
|
||||
var s strings.Builder
|
||||
ranks := strings.Split(strings.Split(m.board.ToFen(), " ")[0], "/")
|
||||
for _, r := range ranks {
|
||||
for _, c := range r {
|
||||
if c >= '1' && c <= '8' {
|
||||
for i := 0; i < int(c-'0'); i++ {
|
||||
s.WriteString(piece.Display[""])
|
||||
}
|
||||
} else {
|
||||
s.WriteString(piece.Display[string(c)])
|
||||
}
|
||||
}
|
||||
s.WriteRune('\n')
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
const (
|
||||
cellHeight = 2
|
||||
@ -36,53 +52,11 @@ const (
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.MouseMsg:
|
||||
col := (msg.X - marginLeft) / cellWidth
|
||||
row := (msg.Y - marginTop) / cellHeight
|
||||
|
||||
if col < 0 || col > maxCol || row < 0 || row > maxRow {
|
||||
m.board.Selected = position.NoPosition
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if !m.board.Reversed {
|
||||
row = maxRow - row
|
||||
}
|
||||
|
||||
if msg.Type != tea.MouseRelease {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if m.board.Selected == position.NoPosition {
|
||||
pos := position.Position{Row: row, Col: col}
|
||||
if m.board.At(pos) == piece.EmptyPiece {
|
||||
return m, nil
|
||||
}
|
||||
m.board.Selected = pos
|
||||
} else {
|
||||
from := Square(m.board.Selected.String())
|
||||
toPos := position.Position{Row: row, Col: col}
|
||||
to := Square(toPos.String())
|
||||
|
||||
// Don't allow moving to the same square
|
||||
if from == to {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Don't allow moving to a square with a piece of the same
|
||||
// color as the selected piece
|
||||
if m.board.At(m.board.Selected).Color == m.board.At(toPos).Color {
|
||||
m.board.Selected = toPos
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Valid move
|
||||
move := board.Move{From: from, To: to}
|
||||
m.moves = append(m.moves, move)
|
||||
m.board.Move(move)
|
||||
m.board.Selected = position.NoPosition
|
||||
}
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case " ":
|
||||
move := m.board.GenerateLegalMoves()[0]
|
||||
m.board.Apply(move)
|
||||
case "ctrl+c", "q":
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -9,6 +9,7 @@ require (
|
||||
|
||||
require (
|
||||
github.com/containerd/console v1.0.2 // indirect
|
||||
github.com/dylhunn/dragontoothmg v0.0.0-20170905201839-b0146de1e275 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -4,6 +4,8 @@ github.com/charmbracelet/lipgloss v0.4.0 h1:768h64EFkGUr8V5yAKV7/Ta0NiVceiPaV+Pp
|
||||
github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM=
|
||||
github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=
|
||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||
github.com/dylhunn/dragontoothmg v0.0.0-20170905201839-b0146de1e275 h1:PDfC81w74XKfP1qDVvKrcL+isYNi7FBunA4zU+eMlME=
|
||||
github.com/dylhunn/dragontoothmg v0.0.0-20170905201839-b0146de1e275/go.mod h1:L6ZI7rasNVYqjj/tpfqYRowKPuSQO71UCBBhPxamiDQ=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
|
121
piece/piece.go
121
piece/piece.go
@ -1,110 +1,17 @@
|
||||
package piece
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/maaslalani/gambit/style"
|
||||
)
|
||||
|
||||
// Color of pieces
|
||||
type Color string
|
||||
|
||||
const (
|
||||
White Color = "w"
|
||||
Black Color = "b"
|
||||
NoColor Color = ""
|
||||
)
|
||||
|
||||
// Types of pieces
|
||||
type Type string
|
||||
|
||||
const (
|
||||
Pawn Type = "P"
|
||||
Knight Type = "N"
|
||||
Bishop Type = "B"
|
||||
Rook Type = "R"
|
||||
Queen Type = "Q"
|
||||
King Type = "K"
|
||||
NoType Type = ""
|
||||
)
|
||||
|
||||
func (t Type) String() string {
|
||||
return string(t)
|
||||
var Display = map[string]string{
|
||||
"": " ",
|
||||
"B": "♗",
|
||||
"K": "♔",
|
||||
"N": "♘",
|
||||
"P": "♙",
|
||||
"Q": "♕",
|
||||
"R": "♖",
|
||||
"b": "♝",
|
||||
"k": "♚",
|
||||
"n": "♞",
|
||||
"p": "♟",
|
||||
"q": "♛",
|
||||
"r": "♜",
|
||||
}
|
||||
|
||||
// Pieces
|
||||
type Piece struct {
|
||||
Type Type
|
||||
Color Color
|
||||
}
|
||||
|
||||
func (p Piece) String() string {
|
||||
return Display[p.Type]
|
||||
}
|
||||
|
||||
func Empty() Piece {
|
||||
return Piece{NoType, NoColor}
|
||||
}
|
||||
|
||||
var Display = map[Type]string{
|
||||
Bishop: "♝",
|
||||
King: "♚",
|
||||
Knight: "♞",
|
||||
Pawn: "♟",
|
||||
Queen: "♛",
|
||||
Rook: "♜",
|
||||
NoType: " ",
|
||||
}
|
||||
|
||||
// ToFen converts a piece into its FEN representation
|
||||
// i.e. White Knight -> "N"
|
||||
// Black Bishop -> "b"
|
||||
// if a piece is empty, it returns an empty string
|
||||
func (p Piece) ToFen() string {
|
||||
t := string(p.Type)
|
||||
if p.Color == Black {
|
||||
return strings.ToLower(t)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// FromFen converts a FEN representation of a piece into a
|
||||
// piece. Reverses ToFen.
|
||||
func FromFen(fen string) Piece {
|
||||
u := strings.ToUpper(fen)
|
||||
t := Type(u)
|
||||
var c Color
|
||||
if u == fen {
|
||||
c = White
|
||||
} else {
|
||||
c = Black
|
||||
}
|
||||
return Piece{Type: t, Color: c}
|
||||
}
|
||||
|
||||
func (p Piece) Style() lipgloss.Style {
|
||||
if p.Color == White {
|
||||
return style.White
|
||||
} else {
|
||||
return style.Black
|
||||
}
|
||||
}
|
||||
|
||||
var EmptyPiece = Piece{NoType, NoColor}
|
||||
|
||||
var (
|
||||
BB = Piece{Bishop, Black}
|
||||
BW = Piece{Bishop, White}
|
||||
KB = Piece{King, Black}
|
||||
KW = Piece{King, White}
|
||||
NB = Piece{Knight, Black}
|
||||
NW = Piece{Knight, White}
|
||||
PB = Piece{Pawn, Black}
|
||||
PW = Piece{Pawn, White}
|
||||
QB = Piece{Queen, Black}
|
||||
QW = Piece{Queen, White}
|
||||
RB = Piece{Rook, Black}
|
||||
RW = Piece{Rook, White}
|
||||
OO = Piece{NoType, NoColor}
|
||||
)
|
||||
|
@ -1,53 +0,0 @@
|
||||
package position
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/maaslalani/gambit/squares"
|
||||
)
|
||||
|
||||
// Position represents a position on the board
|
||||
type Position struct {
|
||||
// Row represents the row number of the cell in the board,
|
||||
// this can easily be converted to a human readable rank
|
||||
Row int // rank
|
||||
// Col represents the column number of the cell in the board,
|
||||
// this can easily be converted to a human readable file
|
||||
Col int // file
|
||||
}
|
||||
|
||||
// String takes the current position and returns a human readable file and
|
||||
// rank in chess notation
|
||||
func (p Position) String() string {
|
||||
return ColumnToFile(p.Col) + RowToRank(p.Row)
|
||||
}
|
||||
|
||||
// ToPosition reads a rank and file number and returns the corresponding
|
||||
// position on the board's grid
|
||||
func ToPosition(s squares.Square) Position {
|
||||
return Position{RankToRow(s[1]), FileToColumn(s[0])}
|
||||
}
|
||||
|
||||
// RowToRank converts a row number to a human readable rank
|
||||
func RowToRank(row int) string {
|
||||
return fmt.Sprintf("%d", row+1)
|
||||
}
|
||||
|
||||
// RankToRow converts a human readable rank number to a board row number
|
||||
func RankToRow(rank byte) int {
|
||||
parsed, _ := strconv.Atoi(string(rank))
|
||||
return parsed - 1
|
||||
}
|
||||
|
||||
// ColumnToFile converts a column number to a human readable file
|
||||
func ColumnToFile(column int) string {
|
||||
return fmt.Sprintf("%c", column+'A')
|
||||
}
|
||||
|
||||
// FileToColumn converts a human readable file to a board column number
|
||||
func FileToColumn(file byte) int {
|
||||
return int(file - 'A')
|
||||
}
|
||||
|
||||
var NoPosition = Position{-1, -1}
|
@ -1,38 +0,0 @@
|
||||
package position
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/maaslalani/gambit/squares"
|
||||
)
|
||||
|
||||
func TestPosition(t *testing.T) {
|
||||
tt := []struct {
|
||||
s Square
|
||||
row int
|
||||
col int
|
||||
}{
|
||||
{A8, 7, 0},
|
||||
{B7, 6, 1},
|
||||
{C6, 5, 2},
|
||||
{D5, 4, 3},
|
||||
{E4, 3, 4},
|
||||
{F3, 2, 5},
|
||||
{G2, 1, 6},
|
||||
{H1, 0, 7},
|
||||
}
|
||||
|
||||
for i, tc := range tt {
|
||||
p := Position{tc.row, tc.col}
|
||||
if p.String() != string(tc.s) {
|
||||
t.Errorf("Test %d: expected %s, got %s", i, tc.s, p.String())
|
||||
}
|
||||
}
|
||||
|
||||
for i, tc := range tt {
|
||||
p := ToPosition(tc.s)
|
||||
if p.Col != tc.col || p.Row != tc.row {
|
||||
t.Errorf("Test %d: expected %s, got %s", i, tc.s, p.String())
|
||||
}
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package squares
|
||||
|
||||
type Square string
|
||||
|
||||
const (
|
||||
A1 Square = "A1"
|
||||
A2 = "A2"
|
||||
A3 = "A3"
|
||||
A4 = "A4"
|
||||
A5 = "A5"
|
||||
A6 = "A6"
|
||||
A7 = "A7"
|
||||
A8 = "A8"
|
||||
B1 = "B1"
|
||||
B2 = "B2"
|
||||
B3 = "B3"
|
||||
B4 = "B4"
|
||||
B5 = "B5"
|
||||
B6 = "B6"
|
||||
B7 = "B7"
|
||||
B8 = "B8"
|
||||
C1 = "C1"
|
||||
C2 = "C2"
|
||||
C3 = "C3"
|
||||
C4 = "C4"
|
||||
C5 = "C5"
|
||||
C6 = "C6"
|
||||
C7 = "C7"
|
||||
C8 = "C8"
|
||||
D1 = "D1"
|
||||
D2 = "D2"
|
||||
D3 = "D3"
|
||||
D4 = "D4"
|
||||
D5 = "D5"
|
||||
D6 = "D6"
|
||||
D7 = "D7"
|
||||
D8 = "D8"
|
||||
E1 = "E1"
|
||||
E2 = "E2"
|
||||
E3 = "E3"
|
||||
E4 = "E4"
|
||||
E5 = "E5"
|
||||
E6 = "E6"
|
||||
E7 = "E7"
|
||||
E8 = "E8"
|
||||
F1 = "F1"
|
||||
F2 = "F2"
|
||||
F3 = "F3"
|
||||
F4 = "F4"
|
||||
F5 = "F5"
|
||||
F6 = "F6"
|
||||
F7 = "F7"
|
||||
F8 = "F8"
|
||||
G1 = "G1"
|
||||
G2 = "G2"
|
||||
G3 = "G3"
|
||||
G4 = "G4"
|
||||
G5 = "G5"
|
||||
G6 = "G6"
|
||||
G7 = "G7"
|
||||
G8 = "G8"
|
||||
H1 = "H1"
|
||||
H2 = "H2"
|
||||
H3 = "H3"
|
||||
H4 = "H4"
|
||||
H5 = "H5"
|
||||
H6 = "H6"
|
||||
H7 = "H7"
|
||||
H8 = "H8"
|
||||
)
|
||||
|
||||
func (s Square) String() string {
|
||||
return string(s)
|
||||
}
|
Loading…
Reference in New Issue
Block a user