Beispiel #1
0
func negamax(b game.Board, depth, alpha, beta int, color game.Color) (int, game.Move) {
	if depth == 0 {
		return scoreBoard(b, color), nullMove
	}

	moves := b.AvailableMoves(color)

	if len(moves) == 0 {
		return math.MinInt32 + 1, nullMove
	}

	var (
		bestScore = math.MinInt32
		bestMove  game.Move
	)

	for _, i := range rand.Perm(len(moves)) {
		val, _ := negamax(b.IfMove(moves[i]), depth-1, -beta, -alpha, color.Other())
		val = -val
		if val > bestScore {
			bestScore = val
			bestMove = moves[i]
		}
		if val > alpha {
			alpha = val
		}
		if alpha >= beta {
			break
		}
	}

	return bestScore, bestMove
}
Beispiel #2
0
func (p httpPlayer) Move(b game.Board) game.Move {

	var move game.Move

	moveCommand := commandToClient{
		Command: "move",
		Args: map[string]interface{}{
			"board": b,
			"moves": b.AvailableMoves(p.Color()),
		},
	}

	if err := p.conn.WriteJSON(moveCommand); err != nil {
		log.Printf("error requesting move: %s", err)
		return move
	}

	var resp commandFromClient
	if err := p.conn.ReadJSON(&resp); err != nil {
		log.Printf("error receiving move: %s", err)
		return move
	}

	if resp.Command != "move" {
		log.Printf("expected move command, got: %s", resp.Command)
		return move
	}

	if err := json.Unmarshal(resp.Args, &move); err != nil {
		log.Printf("failed unmarshaling move: %s (%s)", resp.Command, string(resp.Args))
		return move
	}

	return move
}
Beispiel #3
0
// simple heuristic for board evaluation
func scoreBoard(b game.Board, c game.Color) (score int) {

	var myPieceCount, theirPieceCount int

	for x := 0; x < b.Width(); x++ {
		for y := 0; y < b.Height(); y++ {
			sq, _ := b.Get(game.Position{x, y})
			if sq.PieceColor == c {
				myPieceCount += sq.PieceCount
				if sq.PieceCount == 1 || sq.PieceCount > 4 {
					score--
				}
			} else {
				theirPieceCount += sq.PieceCount
				if sq.PieceCount == 1 || sq.PieceCount > 4 {
					score++
				}
			}
		}
	}

	return score + 5*int(float64(myPieceCount-theirPieceCount)*float64(2*b.Width())/float64(myPieceCount)+0.5)
}
Beispiel #4
0
func (p cliPlayer) Move(b game.Board) game.Move {
	buf := new(bytes.Buffer)

	buf.WriteString(" " + strings.Repeat("-", 5*b.Width()-1) + "\n")

	for y := 0; y < b.Height(); y++ {
		buf.WriteByte('|')
		for x := 0; x < b.Width(); x++ {
			sq, _ := b.Get(game.Position{x, y})
			if sq.PieceCount == 0 {
				buf.WriteString("    ")
			} else {
				var c string
				if sq.PieceColor == game.Black {
					c = "b"
				} else {
					c = "w"
				}

				num := strconv.Itoa(sq.PieceCount)
				if len(num) == 1 {
					buf.WriteString(" " + num + c + " ")
				} else {
					buf.WriteString(num + c + " ")
				}
			}

			buf.WriteByte('|')
		}

		buf.WriteString(" " + strconv.Itoa(y) + "\n")
		buf.WriteString(" " + strings.Repeat("-", 5*b.Width()-1) + "\n")
	}

	buf.WriteString(" ")
	for x := 0; x < b.Width(); x++ {
		fmt.Fprintf(buf, " %2d  ", x)
	}
	buf.WriteString("\n\n")

	clear := exec.Command("clear")
	clear.Stdout = os.Stdout
	clear.Run()

	os.Stdout.Write(buf.Bytes())

	for {
		var (
			move game.Move

			n   int
			err error
		)

		for n < 4 || err != nil {
			fmt.Fprintf(os.Stdout, "Enter move for %s (fromx,fromy tox,toy count): ", p.Name())
			scanner := bufio.NewScanner(os.Stdin)
			scanner.Scan()
			n, err = fmt.Sscanf(scanner.Text(), "%d,%d %d,%d %d",
				&move.From.X,
				&move.From.Y,
				&move.To.X,
				&move.To.Y,
				&move.PieceCount,
			)
		}

		available := b.AvailableMoves(p.Color())
		for _, m := range available {
			if move == m {
				return move
			}
		}

		fmt.Fprintf(os.Stdout, "Move %+v is not legal!\n", move)
	}
}
Beispiel #5
0
func (p randomPlayer) Move(b game.Board) game.Move {
	moves := b.AvailableMoves(p.Color())
	return moves[rand.Intn(len(moves))]
}