You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

#### 179 lines 3.8 KiB Raw Normal View History Unescape Escape

 2 years ago `package main` ```// FIXME ``` ```// Working: ``` ```// - Moving ``` ```// - Approach captures ``` ```// - Withdrawl captures ``` ```// - Choosing randomly from moves with equal points ``` ```// Broken: ``` ```// - Continuations moves ``` ``` ``` `import (` ` "fmt"` ` "math/rand"` `)` ``` ``` `var weakDirs = []dir{{0,-1}, {0,1}, {1,0}, {-1,0}} ` `var strongDirs = []dir{{-1,-1}, {-1,1}, {1,1}, {1,-1}}` ``` ``` `type point struct {` ` row int` ` col int` `}` ``` ``` ``` ``` `type score struct {` ` d dir` ` attacking bool` ` continuation bool` ` deadCount int` ` approach bool` `}` ``` ``` ``` ``` `func (s score) points() int {` ` count := 0` ` if s.continuation {` ` count += 3` ` }` ` return count + s.deadCount` `}` ``` ``` `type place struct {` ` row int` ` col int` ` strong bool` ` s []score` ` maxPts int` ` bestScore []int` `}` ``` ``` `func (p *place) FindBestDir() {` ` if len(p.s) == 0 {` ` return` ` }` ` for i, s := range p.s {` ` if s.points() > p.maxPts {` ` p.maxPts = s.points()` ` p.bestScore = []int{i}` ` } else if s.points() == p.maxPts {` ` p.bestScore = append(p.bestScore, i)` ` }` ` }` `}` ``` ``` `func ScoreContinuation(m move, g *Game, blacklist []point) (move, bool, error) {` ` p := place{m.toRow, m.toCol, g.board[m.toRow][m.toCol].strong, make([]score, 0, 8), 0, make([]int, 0, 7)}` ` p.Score(g)` ` outer: for _, s := range p.s {` ` if s.points() > 0 {` ` newPt := point{m.toRow+s.d.rowOff, m.toCol+s.d.colOff}` ` for _, bl := range blacklist {` ` if newPt.row == bl.row && newPt.col == bl.col {` ` continue outer` ` }` ` }` ` return move{m.toRow, m.toCol, newPt.row, newPt.col}, s.approach, nil` ` }` ` }` ` return move{}, false, fmt.Errorf("No valid continuation")` `}` ``` ``` `func (p *place) Score(g *Game) {` ` dirs := make([]dir, 0, 8)` ` dirs = append(dirs, weakDirs...)` ` if p.strong {` ` dirs = append(dirs, strongDirs...)` ` }` ``` ``` ` for _, d := range dirs {` ` m := move{p.row, p.col, p.row + d.rowOff, p.col + d.colOff}` ` err := g.ValidateMove(m)` ` if err != nil {` ``` // This is not a valid move ``` ` continue` ` }` ``` ``` ``` // Check continuation ``` ` hasContinuation := false` ` for _, d2 := range dirs {` ` if d2.rowOff == d.rowOff && d2.colOff == d.colOff {` ``` // Cannot move in the same direction ``` ` continue` ` }` ` m2 := move{m.toRow, m.toCol, m.toRow + d2.rowOff, m.toCol + d2.colOff}` ` if g.withdrawAvailable(m2) || g.approachAvailable(m) {` ` hasContinuation = true` ` break` ` }` ` }` ``` ``` ``` // Check Attack ``` ` canWithdraw := g.withdrawAvailable(m)` ` canApproach := g.approachAvailable(m)` ` if !canWithdraw && !canApproach {` ` p.s = append(p.s, score{d, false, false, 0, false})` ` }` ` if canWithdraw {` ` p.s = append(p.s, score{d, true, hasContinuation, g.CountPotentialDead(m, false), false})` ` }` ` if canApproach {` ` p.s = append(p.s, score{d, true, hasContinuation, g.CountPotentialDead(m, true), true})` ` }` ` }` ` p.FindBestDir()` `}` ``` ``` ``` ``` `type cpu struct {` ` legal []place` ` bestScore int` ` bestMove []int` `}` ``` ``` `func (c *cpu) PickMove(g *Game) (move, bool, bool, bool) {` ` c.Clear()` ` c.GetLegalMoves(g)` ``` ``` ` for i := range c.legal {` ` if c.legal[i].maxPts > c.bestScore {` ` c.bestScore = c.legal[i].maxPts` ` c.bestMove = []int{i}` ` } else if c.legal[i].maxPts == c.bestScore {` ` c.bestMove = append(c.bestMove, i)` ` }` ` }` ` bestM := rand.Intn(len(c.bestMove))` ` m := c.legal[c.bestMove[bestM]]` ` bestS := rand.Intn(len(m.bestScore))` ` return move{` ` m.row,` ` m.col,` ` m.row+m.s[m.bestScore[bestS]].d.rowOff,` ` m.col+m.s[m.bestScore[bestS]].d.colOff},` ` m.s[m.bestScore[bestS]].approach,` ` m.s[m.bestScore[bestS]].attacking,` ` m.s[m.bestScore[bestS]].continuation` `}` ``` ``` `func (c *cpu) Clear() {` ` c.legal = make([]place, 0, 15)` ` c.bestMove = make([]int, 0, 5)` ` c.bestScore = 0` `}` ``` ``` `func (c *cpu) GetLegalMoves(g *Game) {` ` for r, row := range g.board {` ` for p, pt := range row {` ` if pt.state == Empty || pt.state == Black {` ` continue` ` }` ` pl := place{r, p, g.board[r][p].strong, make([]score, 0, 8), -1, make([]int, 0, 5)}` ` pl.Score(g)` ` if len(pl.s) > 0 {` ` c.legal = append(c.legal, pl)` ` }` ` }` ` }` `}`