...

Source file src/code.rocket9labs.com/tslocum/bgammon/gamestate.go

Documentation: code.rocket9labs.com/tslocum/bgammon

     1  package bgammon
     2  
     3  import (
     4  	"log"
     5  )
     6  
     7  type GameState struct {
     8  	*Game
     9  	PlayerNumber int8
    10  	Available    [][]int8 // Legal moves.
    11  	Forced       bool     // A forced move is being played automatically.
    12  	Spectating   bool
    13  }
    14  
    15  func (g *GameState) OpponentPlayer() Player {
    16  	if g.PlayerNumber == 1 {
    17  		return g.Player2
    18  	}
    19  	return g.Player1
    20  }
    21  
    22  func (g *GameState) LocalPlayer() Player {
    23  	if g.PlayerNumber == 1 {
    24  		return g.Player1
    25  	}
    26  	return g.Player2
    27  }
    28  
    29  func (g *GameState) SpaceAt(x int8, y int8) int8 {
    30  	if (x < 0 || x > 12) || (y < 0 || y > 9) {
    31  		return -1
    32  	}
    33  
    34  	var space int8 = -1
    35  	if x <= 5 {
    36  		space = x + 1
    37  	} else if x == 6 {
    38  		if y <= 4 {
    39  			return SpaceBarOpponent
    40  		} else {
    41  			return SpaceBarPlayer
    42  		}
    43  	} else {
    44  		space = x
    45  	}
    46  
    47  	if g.PlayerNumber == 2 {
    48  		if y <= 4 {
    49  			space = 25 - space
    50  		}
    51  	} else {
    52  		if y <= 4 {
    53  			space += 12
    54  		} else {
    55  			space = 13 - space
    56  		}
    57  	}
    58  	return space
    59  }
    60  
    61  // Pips returns the pip count for the specified player.
    62  func (g *GameState) Pips(player int8) int {
    63  	var pips int
    64  	var spaceValue int
    65  	if player == 1 {
    66  		pips += int(PlayerCheckers(g.Board[SpaceBarPlayer], player)) * 25
    67  	} else {
    68  		pips += int(PlayerCheckers(g.Board[SpaceBarOpponent], player)) * 25
    69  	}
    70  	if g.Variant != VariantBackgammon {
    71  		if player == 1 && !g.Player1.Entered {
    72  			pips += int(PlayerCheckers(g.Board[SpaceHomePlayer], player)) * 25
    73  		} else if player == 2 && !g.Player2.Entered {
    74  			pips += int(PlayerCheckers(g.Board[SpaceHomeOpponent], player)) * 25
    75  		}
    76  	}
    77  	for i := 1; i < 25; i++ {
    78  		if player == g.PlayerNumber && g.Variant != VariantTabula {
    79  			spaceValue = i
    80  		} else {
    81  			spaceValue = 25 - i
    82  		}
    83  		pips += int(PlayerCheckers(g.Board[i], player)) * spaceValue
    84  	}
    85  	return pips
    86  }
    87  
    88  // MayDouble returns whether the player may send the 'double' command.
    89  func (g *GameState) MayDouble() bool {
    90  	if g.Spectating || g.Winner != 0 || g.Variant != VariantBackgammon {
    91  		return false
    92  	}
    93  	return g.Points != 1 && g.Turn != 0 && g.Turn == g.PlayerNumber && g.Roll1 == 0 && !g.DoubleOffered && (g.DoublePlayer == 0 || g.DoublePlayer == g.PlayerNumber)
    94  }
    95  
    96  // MayRoll returns whether the player may send the 'roll' command.
    97  func (g *GameState) MayRoll() bool {
    98  	if g.Spectating || g.Winner != 0 || g.DoubleOffered {
    99  		return false
   100  	}
   101  	switch g.Turn {
   102  	case 0:
   103  		if g.PlayerNumber == 1 {
   104  			return g.Player2.Name != "" && (g.Roll1 == 0 || (g.Roll1 == g.Roll2))
   105  		} else if g.PlayerNumber == 2 {
   106  			return g.Player1.Name != "" && (g.Roll2 == 0 || (g.Roll1 == g.Roll2))
   107  		}
   108  		return false
   109  	case 1:
   110  		return g.PlayerNumber == g.Turn && g.Player2.Name != "" && g.Roll1 == 0
   111  	case 2:
   112  		return g.PlayerNumber == g.Turn && g.Player1.Name != "" && g.Roll1 == 0
   113  	default:
   114  		log.Panicf("unknown turn %d", g.Turn)
   115  		return false
   116  	}
   117  }
   118  
   119  // MayChooseRoll returns whether the player may send the 'ok' command, supplying
   120  // the chosen roll. This command only applies to acey-deucey games.
   121  func (g *GameState) MayChooseRoll() bool {
   122  	return g.Variant == VariantAceyDeucey && g.Turn != 0 && g.Turn == g.PlayerNumber && ((g.Roll1 == 1 && g.Roll2 == 2) || (g.Roll1 == 2 && g.Roll2 == 1)) && len(g.Moves) == 2
   123  }
   124  
   125  // MayOK returns whether the player may send the 'ok' command.
   126  func (g *GameState) MayOK() bool {
   127  	if g.Spectating || g.Winner != 0 {
   128  		return false
   129  	} else if g.Turn != 0 && g.Turn != g.PlayerNumber && g.PlayerNumber != g.DoublePlayer && g.DoubleOffered {
   130  		return true
   131  	}
   132  	return g.Turn != 0 && g.Turn == g.PlayerNumber && g.Roll1 != 0 && len(g.Available) == 0
   133  }
   134  
   135  // MayResign returns whether the player may send the 'resign' command.
   136  func (g *GameState) MayResign() bool {
   137  	if g.Spectating || g.Winner != 0 {
   138  		return false
   139  	}
   140  	return g.Turn != 0 && g.Turn != g.PlayerNumber && g.PlayerNumber != g.DoublePlayer && g.DoubleOffered
   141  }
   142  
   143  // MayReset returns whether the player may send the 'reset' command.
   144  func (g *GameState) MayReset() bool {
   145  	if g.Spectating || g.Winner != 0 {
   146  		return false
   147  	}
   148  	return g.Turn != 0 && g.Turn == g.PlayerNumber && len(g.Moves) > 0
   149  }
   150  

View as plain text