|
|
|
@ -4,7 +4,6 @@ import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"sort"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
@ -73,12 +72,13 @@ type Board struct {
|
|
|
|
|
moves [][2]int
|
|
|
|
|
movesColor int
|
|
|
|
|
|
|
|
|
|
validMoves map[int][]int
|
|
|
|
|
validMoves map[int][][]int
|
|
|
|
|
|
|
|
|
|
from map[int]int
|
|
|
|
|
to map[int]int
|
|
|
|
|
|
|
|
|
|
selected [2]int
|
|
|
|
|
selectedNum int
|
|
|
|
|
selectedSpace int
|
|
|
|
|
|
|
|
|
|
premove [][2]int
|
|
|
|
|
Premovefrom map[int]int
|
|
|
|
@ -130,8 +130,8 @@ func (b *Board) GetIntState() []int {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) resetSelection() {
|
|
|
|
|
b.selected[0] = 0
|
|
|
|
|
b.selected[1] = 0
|
|
|
|
|
b.selectedSpace = 0
|
|
|
|
|
b.selectedNum = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) autoSendMoves() {
|
|
|
|
@ -142,29 +142,6 @@ func (b *Board) autoSendMoves() {
|
|
|
|
|
if b.v[StateMovablePieces] > 0 {
|
|
|
|
|
movable = b.v[StateMovablePieces]
|
|
|
|
|
}
|
|
|
|
|
if len(b.premove) == 1 {
|
|
|
|
|
abs := b.premove[0][1] - b.premove[0][0]
|
|
|
|
|
direction := 1
|
|
|
|
|
if abs < 0 {
|
|
|
|
|
abs *= -1
|
|
|
|
|
direction = -1
|
|
|
|
|
}
|
|
|
|
|
if b.v[StatePlayerDice1] == b.v[StatePlayerDice2] {
|
|
|
|
|
for expandDoubles := 4; expandDoubles >= 2; expandDoubles-- {
|
|
|
|
|
if abs != b.v[StatePlayerDice1]*expandDoubles {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
from, _ := b.premove[0][0], b.premove[0][1]
|
|
|
|
|
|
|
|
|
|
b.premove = nil
|
|
|
|
|
for i := 1; i <= expandDoubles; i++ {
|
|
|
|
|
b.premove = append(b.premove, [2]int{from + ((b.v[StatePlayerDice1]*i - 1) * direction), from + ((b.v[StatePlayerDice1] * i) * direction)})
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if len(b.premove) < movable {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
@ -370,10 +347,10 @@ func (b *Board) renderSpace(index int, spaceValue int) []byte {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Highlight legal moves
|
|
|
|
|
highlightSpace := b.ValidMove(b.selected[0], index)
|
|
|
|
|
highlightSpace := b.ValidMove(b.selectedSpace, index)
|
|
|
|
|
highlightSpace = false // TODO Make configurable, disable by default
|
|
|
|
|
//+(b.v[StatePlayerDice1]*b.v[StatePlayerColor]) ||b.selected[0] == index+(b.v[StatePlayerDice2]*b.v[StatePlayerColor])) && b.selected[1] > 0
|
|
|
|
|
if b.selected[1] > 0 && highlightSpace && index != 25 && index != 0 {
|
|
|
|
|
//+(b.v[StatePlayerDice1]*b.v[StatePlayerColor]) ||b.selectedSpace == index+(b.v[StatePlayerDice2]*b.v[StatePlayerColor])) && b.selectedNum > 0
|
|
|
|
|
if b.selectedNum > 0 && highlightSpace && index != 25 && index != 0 {
|
|
|
|
|
foregroundColor = "black"
|
|
|
|
|
backgroundColor = "yellow"
|
|
|
|
|
}
|
|
|
|
@ -384,7 +361,7 @@ func (b *Board) renderSpace(index int, spaceValue int) []byte {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rightArrowFrom := (b.v[StateDirection] == b.movesColor) == (index > 12)
|
|
|
|
|
if b.selected[0] == index && b.selected[1] > 0 && spaceValue <= abs && spaceValue > abs-b.selected[1] {
|
|
|
|
|
if b.selectedSpace == index && b.selectedNum > 0 && spaceValue <= abs && spaceValue > abs-b.selectedNum {
|
|
|
|
|
r = []byte("*")
|
|
|
|
|
} else if b.Premovefrom[index] > 0 && spaceValue > (abs+b.Premoveto[index])-b.Premovefrom[index] && spaceValue <= abs+b.Premoveto[index] {
|
|
|
|
|
if index == 25-b.PlayerBarSpace() {
|
|
|
|
@ -425,7 +402,7 @@ func (b *Board) renderSpace(index int, spaceValue int) []byte {
|
|
|
|
|
func (b *Board) ResetMoves() {
|
|
|
|
|
b.moves = nil
|
|
|
|
|
b.movesColor = 0
|
|
|
|
|
b.validMoves = make(map[int][]int)
|
|
|
|
|
b.validMoves = make(map[int][][]int)
|
|
|
|
|
b.from = make(map[int]int)
|
|
|
|
|
b.to = make(map[int]int)
|
|
|
|
|
}
|
|
|
|
@ -453,9 +430,15 @@ func (b *Board) allPlayerPiecesInHomeBoard() bool {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
value := b.v[StateBoardSpace0+index]
|
|
|
|
|
|
|
|
|
|
// Include pre-moves
|
|
|
|
|
mod := b.v[StatePlayerColor]
|
|
|
|
|
value -= b.client.Board.Premovefrom[index] * mod
|
|
|
|
|
return value != 0
|
|
|
|
|
|
|
|
|
|
if b.v[StatePlayerColor] == -1 {
|
|
|
|
|
return value < 0
|
|
|
|
|
}
|
|
|
|
|
return value > 0
|
|
|
|
|
}
|
|
|
|
|
for i := 1; i < 24; i++ {
|
|
|
|
|
if i >= homeBoardStart && i <= homeBoardEnd {
|
|
|
|
@ -479,12 +462,12 @@ func (b *Board) spaceAvailable(index int) bool {
|
|
|
|
|
(b.v[StatePlayerColor] == -1 && b.v[StateBoardSpace0+index] <= 1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) GetValidMoves(from int) []int {
|
|
|
|
|
func (b *Board) GetValidMoves(from int) [][]int {
|
|
|
|
|
if validMoves, ok := b.validMoves[from]; ok {
|
|
|
|
|
return validMoves
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var validMoves []int
|
|
|
|
|
var validMoves [][]int
|
|
|
|
|
defer func() {
|
|
|
|
|
b.validMoves[from] = validMoves
|
|
|
|
|
}()
|
|
|
|
@ -493,7 +476,6 @@ func (b *Board) GetValidMoves(from int) []int {
|
|
|
|
|
return validMoves
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO consider opponent blocking midway In full move
|
|
|
|
|
trySpaces := [][]int{
|
|
|
|
|
{b.v[StatePlayerDice1]},
|
|
|
|
|
{b.v[StatePlayerDice2]},
|
|
|
|
@ -529,12 +511,10 @@ CHECKSPACES:
|
|
|
|
|
space := from + (checkSpace * b.v[StateDirection])
|
|
|
|
|
if _, value := foundMoves[space]; !value {
|
|
|
|
|
foundMoves[space] = true
|
|
|
|
|
validMoves = append(validMoves, space)
|
|
|
|
|
validMoves = append(validMoves, trySpaces[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sort.Ints(validMoves)
|
|
|
|
|
|
|
|
|
|
return validMoves
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -560,8 +540,16 @@ func (b *Board) ValidMove(f int, t int) bool {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
validMoves := b.GetValidMoves(f)
|
|
|
|
|
CHECKVALID:
|
|
|
|
|
for i := range validMoves {
|
|
|
|
|
if validMoves[i] == t {
|
|
|
|
|
checkSpace := 0
|
|
|
|
|
for _, space := range validMoves[i] {
|
|
|
|
|
checkSpace += space
|
|
|
|
|
if !b.spaceAvailable(f + (checkSpace * b.v[StateDirection])) {
|
|
|
|
|
continue CHECKVALID
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if f+(checkSpace*b.v[StateDirection]) == t {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -603,7 +591,7 @@ func (b *Board) Move(player int, f string, t string) {
|
|
|
|
|
|
|
|
|
|
b.v[StateTurn] = player * -1
|
|
|
|
|
|
|
|
|
|
b.validMoves = make(map[int][]int)
|
|
|
|
|
b.validMoves = make(map[int][][]int)
|
|
|
|
|
b.ResetPreMoves()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -627,18 +615,77 @@ func (b *Board) SimplifyMoves() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) AddPreMove(from int, to int) bool {
|
|
|
|
|
func (b *Board) GetSelection() (num int, space int) {
|
|
|
|
|
return b.selectedNum, b.selectedSpace
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) SetSelection(num int, space int) {
|
|
|
|
|
b.selectedNum, b.selectedSpace = num, space
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) ResetSelection() {
|
|
|
|
|
b.selectedNum, b.selectedSpace = 0, 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) addPreMove(from int, to int, num int) bool {
|
|
|
|
|
// Allow bearing off when the player moves their own pieces on to the bar
|
|
|
|
|
if to == 0 || to == 25 {
|
|
|
|
|
to = b.PlayerHomeSpace()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expand combined move
|
|
|
|
|
moves := b.client.Board.GetValidMoves(from)
|
|
|
|
|
|
|
|
|
|
CHECKPREMOVES:
|
|
|
|
|
for i := range moves {
|
|
|
|
|
checkSpace := 0
|
|
|
|
|
for _, space := range moves[i] {
|
|
|
|
|
checkSpace += space
|
|
|
|
|
lf("CHECK %d %d", checkSpace, from+(checkSpace*b.v[StateDirection]))
|
|
|
|
|
if !b.spaceAvailable(from + (checkSpace * b.v[StateDirection])) {
|
|
|
|
|
continue CHECKPREMOVES
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lf("SECOND PHASE %+v %d", moves[i], num)
|
|
|
|
|
if (from+(checkSpace*b.v[StateDirection]) == to) && len(moves[i]) > 1 {
|
|
|
|
|
lf("SECOND.5 PHASE %+v %d", moves[i], num)
|
|
|
|
|
for j := 0; j < num; j++ {
|
|
|
|
|
checkSpace = 0
|
|
|
|
|
lastSpace := 0
|
|
|
|
|
for _, space := range moves[i] {
|
|
|
|
|
checkSpace += space
|
|
|
|
|
lf("THIRD PHASE %d %d", from+(lastSpace*b.v[StateDirection]), from+(checkSpace*b.v[StateDirection]))
|
|
|
|
|
|
|
|
|
|
if !b.addPreMove(from+(lastSpace*b.v[StateDirection]), from+(checkSpace*b.v[StateDirection]), 1) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
lastSpace = checkSpace
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !b.ValidMove(from, to) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
b.premove = append(b.premove, [2]int{from, to})
|
|
|
|
|
b.Premovefrom[from]++
|
|
|
|
|
b.Premoveto[to]++
|
|
|
|
|
|
|
|
|
|
for i := 0; i < num; i++ {
|
|
|
|
|
b.premove = append(b.premove, [2]int{from, to})
|
|
|
|
|
b.Premovefrom[from]++
|
|
|
|
|
b.Premoveto[to]++
|
|
|
|
|
}
|
|
|
|
|
lf("ADD %+v", b.premove)
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Board) AddPreMove(from int, to int) bool {
|
|
|
|
|
if !b.addPreMove(from, to, b.selectedNum) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
lf("FINAL %+v", b.premove)
|
|
|
|
|
|
|
|
|
|
b.resetSelection()
|
|
|
|
|
b.autoSendMoves()
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|