~hokiegeek/tucana

cb0d9b8c5bab53beb0c702827386ccb20d782482 — HokieGeek 4 months ago 3ec985f v0.7.0
Added bonus sights variant, completing all first edition rules
2 files changed, 74 insertions(+), 31 deletions(-)

M cmd/tucana/main.go
M game.go
M cmd/tucana/main.go => cmd/tucana/main.go +5 -1
@@ 53,6 53,9 @@ func getInput(game *tucana.Game) error {
						return err
					}
				}
				if bon > 0 {
					fmt.Println("bonus sight!")
				}
				points += pts + bon
				// TODO: display remaining visits?
			}


@@ 68,6 71,7 @@ func getInput(game *tucana.Game) error {
func main() {
	numPlayers := flag.Int("numPlayers", 1, "The number of players")
	boardPtr := flag.String("board", "petit", "The board to use (petit, grande)")
	sightBonusVariantPtr := flag.Bool("sightBonus", false, "Enables the Sight 6 point bonus variant")

	flag.Parse()



@@ 81,7 85,7 @@ func main() {
		board = tucana.IslaPetit
	}

	game, err := tucana.New(board, *numPlayers)
	game, err := tucana.New(board, *numPlayers, *sightBonusVariantPtr)
	if err != nil {
		panic(err)
	}

M game.go => game.go +69 -30
@@ 180,13 180,14 @@ const (

// Global variables defining the game components
var (
	TerrainCards       TerrainDeck
	InitialSetupDeck   [13]InitialSetupCard
	BonusVillagesCards BonusVillagesDeck
	SightScoring       map[Board]map[Sight][]int
	VillagesScoring    map[Board]map[VillageConnection]int
	maxTurns           int
	maxRoundsBoard     []int
	TerrainCards              TerrainDeck
	InitialSetupDeck          [13]InitialSetupCard
	BonusVillagesCards        BonusVillagesDeck
	SightScoring              map[Board]map[Sight][]int
	VillagesScoring           map[Board]map[VillageConnection]int
	BonusSightsVariantScoring int
	maxTurns                  int
	maxRoundsBoard            []int
)

func init() {


@@ 248,11 249,7 @@ func init() {
	BonusVillagesCards[VillagesConnectionDD] = []int{6, 4}
	BonusVillagesCards[VillagesConnectionEE] = []int{7, 5}

	/* TODO: Bonus sights (variant): 6 points for each for a sight seen twice
	if variant is selected:
	2-4 players: 1 card  randomly selected
	5-8 players: 2 cards randomly selected
	*/
	BonusSightsVariantScoring = 6

	SightScoring = make(map[Board]map[Sight][]int)
	SightScoring[IslaPetit] = make(map[Sight][]int)


@@ 307,16 304,17 @@ func (s Score) String() string {

// Game captures the state of a running game
type Game struct {
	InitiaSetup       InitialSetupCard           `json:"initialSetup"`
	Board             Board                      `json:"board"`
	Terrain           TerrainDeck                `json:"terrain"`
	VillageBonuses    BonusVillagesDeck          `json:"villageBonuses"`
	NumPlayers        int                        `json:"numPlayers"`
	Round             int                        `json:"round"`
	Turn              int                        `json:"turn"`
	SightsVisited     [3]map[Sight]int           `json:"sightsVisited"`
	VillagesConnected map[VillageConnection]bool `json:"villagesConnected"`
	BonusesEarned     []int                      `json:"bonusesEarned"`
	InitiaSetup        InitialSetupCard           `json:"initialSetup"`
	Board              Board                      `json:"board"`
	Terrain            TerrainDeck                `json:"terrain"`
	VillageBonuses     BonusVillagesDeck          `json:"villageBonuses"`
	NumPlayers         int                        `json:"numPlayers"`
	Round              int                        `json:"round"`
	Turn               int                        `json:"turn"`
	SightsVisited      []map[Sight]int            `json:"sightsVisited"`
	VillagesConnected  map[VillageConnection]bool `json:"villagesConnected"`
	BonusesEarned      []int                      `json:"bonusesEarned"`
	BonusSightsVariant []Sight                    `json:"bonusSightsVariant"`
}

func (g *Game) currentTerrain() []Terrain {


@@ 422,7 420,6 @@ func (g *Game) VisitSight(sight Sight) (int, int, bool) {
	}

	if numVisits == len(SightScoring[g.Board][sight]) {
		// fmt.Println("no more visits")
		return 0, 0, false
	}



@@ 431,7 428,19 @@ func (g *Game) VisitSight(sight Sight) (int, int, bool) {
	}
	g.SightsVisited[g.Round-1][sight]++

	return SightScoring[g.Board][sight][numVisits], 0, numVisits+1 == len(SightScoring[g.Board][sight])
	var bonus int
	if len(g.BonusSightsVariant) > 0 {
		for i, s := range g.BonusSightsVariant {
			if s == sight {
				bonus += BonusSightsVariantScoring
				g.BonusSightsVariant[i] = g.BonusSightsVariant[len(g.BonusSightsVariant)-1]
				g.BonusSightsVariant[len(g.BonusSightsVariant)-1] = SightUnknown
				g.BonusSightsVariant = g.BonusSightsVariant[:len(g.BonusSightsVariant)-1]
			}
		}
	}

	return SightScoring[g.Board][sight][numVisits], bonus, numVisits+1 == len(SightScoring[g.Board][sight])
}

// Score returns the currently accumulated score


@@ 490,12 499,22 @@ func (g *Game) String() string {
	buf.WriteString("\n")

	buf.WriteString(g.InitiaSetup.String())
	buf.WriteString("\n")

	if len(g.BonusSightsVariant) > 0 {
		buf.WriteString("Variant 6 point bonus Sights: ")
		for _, s := range g.BonusSightsVariant {
			buf.WriteString(s.String())
			buf.WriteString(" ")
		}
		buf.WriteString("\n")
	}

	return buf.String()
}

// New creates a new game state
func New(board Board, numPlayers int) (*Game, error) {
func New(board Board, numPlayers int, enableBonusSightVariant bool) (*Game, error) {
	g := new(Game)
	g.Round = 1
	g.Board = board


@@ 526,12 545,32 @@ func New(board Board, numPlayers int) (*Game, error) {
		g.VillageBonuses[k] = bonuses
	}

	g.SightsVisited[0] = make(map[Sight]int)
	g.SightsVisited[1] = make(map[Sight]int)
	// TODO: if g.board == IslaGrande {
	g.SightsVisited[2] = make(map[Sight]int)
	// }
	g.SightsVisited = append(g.SightsVisited, make(map[Sight]int))
	g.SightsVisited = append(g.SightsVisited, make(map[Sight]int))
	if g.Board == IslaGrande {
		g.SightsVisited = append(g.SightsVisited, make(map[Sight]int))
	}
	g.VillagesConnected = make(map[VillageConnection]bool)

	// Bonus sights (variant): 6 points for each for a sight seen twice
	if enableBonusSightVariant && g.NumPlayers > 1 {
		// if variant is selected:
		// 2-4 players: 1 card  randomly selected
		sights := []Sight{SightObelisk, SightBook, SightToucan, SightNative, SightDragon}
		bonus := rand.Intn(len(sights) - 1)
		g.BonusSightsVariant = append(g.BonusSightsVariant, sights[bonus])

		// 5-8 players: 2 cards randomly selected
		if g.NumPlayers > 4 {
			// Remove the previous bonus
			sights[bonus] = sights[len(sights)-1]
			sights[len(sights)-1] = SightUnknown
			sights = sights[:len(sights)-1]

			bonus := rand.Intn(len(sights) - 1)
			g.BonusSightsVariant = append(g.BonusSightsVariant, sights[bonus])
		}
	}

	return g, nil
}