Skip to content

Commit

Permalink
implements 'perfttest' command
Browse files Browse the repository at this point in the history
  • Loading branch information
vinymeuh committed May 11, 2024
1 parent d4ef85a commit 73f45a0
Show file tree
Hide file tree
Showing 14 changed files with 291 additions and 281 deletions.
2 changes: 1 addition & 1 deletion cmd/hifumi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func main() {
if len(os.Args) >= 2 {
switch os.Args[1] {
case "perfttest":
fmt.Println("perfttest")
engine.Perfttest(os.Args[2:])
return
case "pprof":
prefix := fmt.Sprintf("hifumi-%s-%s-", engine.EngineVersion, time.Now().Format("2006-01-02T150405"))
Expand Down
78 changes: 0 additions & 78 deletions engine/perft.go

This file was deleted.

20 changes: 20 additions & 0 deletions engine/perfttest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package engine

import (
"fmt"
"os"
"strings"

"github.com/vinymeuh/hifumi/shogi"
"github.com/vinymeuh/hifumi/shogi/perft"
)

func Perfttest(args []string) {
if len(args) == 0 {
fmt.Fprintln(os.Stderr, "Usage: hifumi perfttest startpos")
os.Exit(1)
}
position, _ := shogi.NewPositionFromSfen(strings.Join(args, " "))
result := perft.Compute(position, 1)
fmt.Println(result)
}
13 changes: 7 additions & 6 deletions engine/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math/rand"
"time"

"github.com/vinymeuh/hifumi/shogi"
"github.com/vinymeuh/hifumi/shogi/movegen"
)

Expand All @@ -30,7 +31,7 @@ func newSeachConstraints() searchConstraints {
}

type principalVariation struct {
line [maxSearchDepth]movegen.Move
line [maxSearchDepth]shogi.Move
}

func think(constraints searchConstraints) {
Expand Down Expand Up @@ -84,19 +85,19 @@ func iFeelLucky(ctx context.Context, constraints searchConstraints, done chan st
var moves movegen.MoveList
movegen.GenerateAllMoves(enginePosition, &moves)

var m movegen.Move
var m shogi.Move
for {
n := rand.Intn(moves.Count)
m = moves.Moves[n]
moveIsValid := movegen.DoMove(enginePosition, m)
movegen.UndoMove(enginePosition, m)
if moveIsValid {
enginePosition.DoMove(m)
enginePosition.UndoMove(m)
if len(movegen.Checkers(enginePosition, enginePosition.Side)) == 0 {
break
}
moves.Moves[n] = moves.Moves[moves.Count-1]
moves.Count--
if moves.Count == 0 {
m = movegen.Move(0)
m = shogi.Move(0)
break
}
}
Expand Down
11 changes: 6 additions & 5 deletions engine/usiloop.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/vinymeuh/hifumi/shogi"
"github.com/vinymeuh/hifumi/shogi/movegen"
"github.com/vinymeuh/hifumi/shogi/perft"
)

const (
Expand All @@ -36,7 +37,7 @@ var (
pv principalVariation
}{
stopRequested: nil,
pv: principalVariation{line: [1]movegen.Move{0}},
pv: principalVariation{line: [1]shogi.Move{0}},
}

enginePosition *shogi.Position
Expand Down Expand Up @@ -252,7 +253,7 @@ func goHandler(args []string) {
func perftHandler(args []string, divide bool) {
depth, _ := strconv.Atoi(args[1])

result := Perft(enginePosition, depth)
result := perft.Compute(enginePosition, depth)
moves := make([]string, 0, result.MovesCount)
for m := range result.Moves {
moves = append(moves, m.String())
Expand Down Expand Up @@ -317,15 +318,15 @@ func displayHandler() {

// applyUsiMove updates Position based on provided USI move string.
// Move must be valid otherwise returns an error.
func applyUsiMove(pos *shogi.Position, str string) (movegen.Move, error) {
func applyUsiMove(pos *shogi.Position, str string) (shogi.Move, error) {
var list movegen.MoveList
movegen.GenerateAllMoves(pos, &list)
for i := 0; i < list.Count; i++ {
m := list.Moves[i]
if m.String() == str {
movegen.DoMove(pos, m)
pos.DoMove(m)
return m, nil
}
}
return movegen.Move(0), fmt.Errorf("invalid move")
return shogi.Move(0), fmt.Errorf("invalid move")
}
79 changes: 79 additions & 0 deletions shogi/move.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: 2023 VinyMeuh
// SPDX-License-Identifier: MIT
package shogi

import (
"strings"
)

// MoveFlags represents the type of a Shogi Move.
const (
MoveFlagDrop uint = 0b0001 // Drop: The move involves dropping a piece onto the board.
MoveFlagMove uint = 0b0010 // Movement: The move involves moving a piece on the board.
MoveFlagPromotion uint = 0b0100 // Promotion: The moving piece will be promoted.
MoveFlagCapture uint = 0b1000 // Capture: The move will result capturing an opponent's piece.
)

// Move is the type to record information about a Shogi move. A Move can be
// applied to a Gamestate to evolve it to a new state. Valid Moves are generated
// from a Gamestate using movegen.
//
// Move is implemented as a bitset with the following structure:
//
// Piece 6 bits || To 8 bits || From 8 bits || MoveFlags 4 bits
//
// For a Drop, Piece is the dropped piece.
// For a Capture, Piece is the captured piece.
type Move uint

// NewMove creates a new Move with the provided MoveFlags, From, To, and Piece.
func NewMove(flags uint, from uint8, to uint8, piece Piece) Move {
m := Move(flags&0x0F) << 0
m |= Move(from&0xFF) << 4
m |= Move(to&0xFF) << 12
m |= Move(piece&0x3F) << 20
return m
}

// flags returns the MoveFlags part of the Move.
func (m Move) flags() uint {
return uint(m & 0x0F)
}

// From returns the from part of the Move.
func (m Move) From() uint8 {
return uint8((m >> 4) & 0xFF)
}

// To returns the To part of the Move.
func (m Move) To() uint8 {
return uint8((m >> 12) & 0xFF)
}

// Piece returns the Piece part of the Move.
func (m Move) Piece() Piece {
return Piece(uint((m >> 20) & 0x3F))
}

// destructure returns the four parts of the Move.
func (m Move) destructure() (uint, uint8, uint8, Piece) {
flags := m.flags()
from := m.From()
to := m.To()
piece := m.Piece()
return flags, from, to, piece
}

// String returns the move as a USI strinp.
func (m Move) String() string {
flags := m.flags()
switch flags {
case MoveFlagDrop:
return strings.ToUpper(m.Piece().String()) + "*" + SquareString(m.To())
default:
if flags&MoveFlagPromotion == MoveFlagPromotion {
return SquareString(m.From()) + SquareString(m.To()) + "+"
}
return SquareString(m.From()) + SquareString(m.To())
}
}
21 changes: 11 additions & 10 deletions shogi/movegen/attacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import (
"github.com/vinymeuh/hifumi/shogi/bitboard"
)

func Attackers(gs *shogi.Position, sq uint8) []uint8 {
myside := gs.Board[sq].Color()
gs.Side = myside.Opponent()
func Attackers(position *shogi.Position, sq uint8) []uint8 {
initialSide := position.Side
myside := position.Board[sq].Color()
position.Side = myside.Opponent()

var moves MoveList
GenerateAllMoves(gs, &moves)
GenerateAllMoves(position, &moves)
attackersMap := make(map[uint8]struct{}, moves.Count)

for i := 0; i < moves.Count; i++ {
Expand All @@ -26,20 +27,20 @@ func Attackers(gs *shogi.Position, sq uint8) []uint8 {
attackers = append(attackers, k)
}

gs.Side = myside
position.Side = initialSide
return attackers
}

func Checkers(gs *shogi.Position, side shogi.Color) []uint8 {
func Checkers(position *shogi.Position, defender shogi.Color) []uint8 {
var bbking bitboard.Bitboard
if side == shogi.Black {
bbking = gs.BBbyPiece[shogi.BlackKing]
if defender == shogi.Black {
bbking = position.BBbyPiece[shogi.BlackKing]
} else {
bbking = gs.BBbyPiece[shogi.WhiteKing]
bbking = position.BBbyPiece[shogi.WhiteKing]
}
if bbking == bitboard.Zero { // don't crash if no king
return []uint8{}
}
squares := Attackers(gs, uint8(bbking.Lsb()))
squares := Attackers(position, uint8(bbking.Lsb()))
return squares
}
2 changes: 1 addition & 1 deletion shogi/movegen/drops.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func generateDrops(gs *shogi.Position, list *MoveList) {
func addDrops(p shogi.Piece, emptySquares bitboard.Bitboard, list *MoveList) {
for emptySquares != bitboard.Zero {
to := uint8(emptySquares.Lsb())
list.Push(NewMove(MoveFlagDrop, 0, to, p))
list.Push(shogi.NewMove(shogi.MoveFlagDrop, 0, to, p))
emptySquares = emptySquares.Clear(uint(to))
}
}
Expand Down
Loading

0 comments on commit 73f45a0

Please sign in to comment.