Skip to content

Commit

Permalink
Merge pull request #81 from mick4711/chess-moh
Browse files Browse the repository at this point in the history
Faster implementation using math.Abs and switch
  • Loading branch information
plutov authored Oct 20, 2024
2 parents fd950fa + e665e81 commit a52e6b1
Showing 1 changed file with 41 additions and 24 deletions.
65 changes: 41 additions & 24 deletions chess/chess.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,55 @@
package chess

import "errors"
import (
"errors"
"math"
)

// CanKnightAttack checks if two knights on specified positions can attack each other
var invalidSquareErr = errors.New("invalid square")

Check failure on line 8 in chess/chess.go

View workflow job for this annotation

GitHub Actions / lint

error var invalidSquareErr should have name of the form errFoo (ST1012)

// Knights can attack when seperated by 2 squares in one direction and 1 square in the other direction.
// Horizontal axis is called 'file' labelled from 'a' to 'f'
// Forward axis is called 'rank' labelled from 1 to 8
func CanKnightAttack(white, black string) (bool, error) {
// Do initial validation
if len(white) < 2 || len(black) < 2 {
return false, errors.New("args too short")
// square must have 2 characters
if len(white) != 2 || len(black) != 2 {
return true, invalidSquareErr
}

// Check if pieces are on board
if white[0]-'a' > 7 || white[1]-'1' > 7 {
return false, errors.New("invalid white position")
// cannot be on the same square
if white == black {
return false, invalidSquareErr
}
if black[0]-'a' > 7 || black[1]-'1' > 7 {
return false, errors.New("invalid black position")

// assign integer values (1 - 8) to file letters and rank digits
wFile := int(white[0] - 'a' + 1)
if wFile < 1 || wFile > 8 {
return false, invalidSquareErr
}

// Calculate distance between knights in each axis
d0 := abs(int(white[0]) - int(black[0]))
d1 := abs(int(white[1]) - int(black[1]))
bFile := int(black[0] - 'a' + 1)
if bFile < 1 || bFile > 8 {
return false, invalidSquareErr
}

// If the difference is 1 on one axis and 2 on the other we're happy
if (d0 == 1 && d1 == 2) || (d0 == 2 && d1 == 1) {
return true, nil
} else if d0 == 0 && d1 == 0 {
return false, errors.New("you cannot stack them you silly")
wRank := int(white[1] - '1' + 1)
if wRank < 1 || wRank > 8 {
return false, invalidSquareErr
}
return false, nil
}

func abs(x int) int {
if x < 0 {
return -x
bRank := int(black[1] - '1' + 1)
if bRank < 1 || bRank > 8 {
return false, invalidSquareErr
}
return x

// check file and rank relative positions
switch int(math.Abs(float64(wFile - bFile))) {
case 1:
return int(math.Abs(float64(wRank-bRank))) == 2, nil
case 2:
return int(math.Abs(float64(wRank-bRank))) == 1, nil
}

// white and black valid but not in knight range of each other
return false, nil
}

0 comments on commit a52e6b1

Please sign in to comment.