Example #1
0
// Accepts a string such as "pe2-e4" and converts it to the Move struct.
func stringToMove(s string) *engine.Move {
	var move engine.Move
	move.Begin = stringToSquare(s[1:3])
	move.End = stringToSquare(s[4:])
	move.Piece = s[0]
	return &move
}
Example #2
0
// First-level NegaScout search function.
// When called, alpha and beta should be set to the lowest and highest values possible.
func NegaScout(b *engine.Board, depth int, alpha, beta float64) *engine.Move {
	if b.IsOver() != 0 || depth == 0 {
		b.Lastmove.Score = EvalBoard(b)
		return &b.Lastmove
	}
	var move engine.Move

	// not indended for actual use
	orderedmoves := b.AllLegalMoves()

	var score float64
	for i, m := range orderedmoves {
		childboard := b.CopyBoard()
		childboard.Move(m)
		if i != 0 {
			score = -NegaScoutChild(childboard, depth-1, -alpha-1, -alpha)
			if alpha < score && score < beta {
				score = -NegaScoutChild(childboard, depth-1, -beta, -alpha)
			}
		} else {
			score = -NegaScoutChild(childboard, depth-1, -beta, -alpha)
		}
		alpha = math.Max(alpha, score)
		if alpha >= beta {
			move = *m.CopyMove()
			move.Score = alpha
			break
		}
	}
	return &move
}
Example #3
0
// Intended to run as a goroutine.
// Keeps track of the state of a single game, recieving and sending moves through the appropriate channel.
func game() {
	board := &engine.Board{Turn: 1}
	board.SetUpPieces()
	url := fmt.Sprintf("http://localhost%s", PORT)
	cmd := exec.Command("open", url)
	if _, err := cmd.Output(); err != nil {
		panic(err)
	}
	rand.Seed(time.Now().UTC().UnixNano())
	for {
		select {
		case oppmove := <-incmoves:
			for _, p := range board.Board {
				if p.Position.X == oppmove.Begin.X && p.Position.Y == oppmove.Begin.Y {
					oppmove.Piece = p.Name
					break
				}
			}
			board.ForceMove(oppmove)
			if LOG {
				fmt.Println(oppmove.ToString())
				board.PrintBoard()
			}
			var mymove *engine.Move
			if moves, ok := search.Book[board.ToFen()]; ok {
				mymove = stringToMove(moves[rand.Intn(len(moves))])
			} else {
				if m := search.AlphaBeta(board, 4, search.BLACKWIN, search.WHITEWIN); m != nil {
					mymove = m
				} else {
					quit <- 1
					break
				}
			}
			board.ForceMove(mymove)
			outmoves <- mymove
			if LOG {
				fmt.Println(mymove.ToString())
				board.PrintBoard()
			}
		case <-quit:
			board.SetUpPieces()
			board.Turn = 1
		}

	}
}
Example #4
0
// First-level negamax search function.
func NegaMax(b *engine.Board, depth int) *engine.Move {
	if b.IsOver() != 0 || depth == 0 {
		b.Lastmove.Score = EvalBoard(b)
		return &b.Lastmove
	}
	var move engine.Move
	move.Score = LOSS
	for _, m := range b.AllLegalMoves() {
		childboard := b.CopyBoard()
		childboard.Move(m)
		childscore := -NegaMaxChild(childboard, depth-1)
		if childscore > move.Score {
			move = *m.CopyMove()
			move.Score = childscore
			if move.Score == WIN {
				return &move
			}
		}
	}
	return &move
}
Example #5
0
// Standard minmax search with alpha beta pruning.
// Initial call: alpha set to lowest value, beta set to highest.
// Top level returns a move.
func AlphaBeta(b *engine.Board, depth int, alpha, beta float64) *engine.Move {
	if b.IsOver() != 0 || depth == 0 {
		return nil
	}
	var bestmove *engine.Move = nil
	var result float64
	movelist := orderedMoves(b, false)
	if b.Turn == 1 {
		for _, move := range movelist {
			b.ForceMove(move)
			if move.Capture != 0 || b.IsCheck(b.Turn) {
				result = AlphaBetaChild(b, depth-1, alpha, beta, true)
			} else {
				result = AlphaBetaChild(b, depth-1, alpha, beta, false)
			}
			b.UndoMove(move)
			if result > alpha {
				alpha = result
				bestmove = move
				bestmove.Score = alpha
			}
			if alpha >= beta {
				bestmove = move
				bestmove.Score = alpha
				return bestmove
			}
		}
		if bestmove == nil {
			return b.AllLegalMoves()[0]
		}
		return bestmove
	} else {
		for _, move := range movelist {
			b.ForceMove(move)
			if move.Capture != 0 || b.IsCheck(b.Turn) {
				result = AlphaBetaChild(b, depth-1, alpha, beta, true)
			} else {
				result = AlphaBetaChild(b, depth-1, alpha, beta, false)
			}
			if LOG {
				fmt.Println(move.ToString(), result)
			}
			b.UndoMove(move)
			if result < beta {
				beta = result
				bestmove = move
				bestmove.Score = beta
			}
			if beta <= alpha {
				bestmove = move
				bestmove.Score = beta
				return bestmove
			}
		}
		if bestmove == nil {
			return b.AllLegalMoves()[0]
		}
		return bestmove
	}
	if bestmove == nil {
		return b.AllLegalMoves()[0]
	}
	return bestmove
}