diff options
-rw-r--r-- | extra/cluedo.go | 73 | ||||
-rw-r--r-- | extra/cluedo_test.go | 50 |
2 files changed, 123 insertions, 0 deletions
diff --git a/extra/cluedo.go b/extra/cluedo.go new file mode 100644 index 0000000..1ef11cc --- /dev/null +++ b/extra/cluedo.go @@ -0,0 +1,73 @@ +package extra + +import ( + "math/rand" + "strings" +) + +var ( + rooms = []string{"HALL", "LOUNGE", "DINING ROOM", "KITCHEN", "BALLROOM", "CONSERVATORY", "BILLIARD ROOM", "LIBRARY", "STUDY"} + weapons = []string{"CANDLESTICK", "DAGGER", "LEAD PIPE", "REVOLVER", "ROPE", "SPANNER"} + people = []string{"Miss Scarlett", "Colonel Mustard", "Mrs. White", "Reverend Green", "Mrs. Peacock", "Professor Plum"} +) + +type MurderTrifecta struct { + Murderer string + Weapon string + Room string +} + +type CluedoRoundInfo struct { + Answer MurderTrifecta + PlayersCards map[string][]string +} + +func (c *CluedoRoundInfo) GetPlayerCards(player string) string { + // maybe format it a little + return "cards of " + player + "are " + strings.Join(c.PlayersCards[player], ",") +} + +func CluedoPrepCards(playerOrder []string) *CluedoRoundInfo { + res := &CluedoRoundInfo{} + // Select murder components + trifecta := MurderTrifecta{ + Murderer: people[rand.Intn(len(people))], + Weapon: weapons[rand.Intn(len(weapons))], + Room: rooms[rand.Intn(len(rooms))], + } + // Collect non-murder cards + var notInvolved []string + for _, room := range rooms { + if room != trifecta.Room { + notInvolved = append(notInvolved, room) + } + } + for _, weapon := range weapons { + if weapon != trifecta.Weapon { + notInvolved = append(notInvolved, weapon) + } + } + for _, person := range people { + if person != trifecta.Murderer { + notInvolved = append(notInvolved, person) + } + } + // Shuffle and distribute cards + rand.Shuffle(len(notInvolved), func(i, j int) { + notInvolved[i], notInvolved[j] = notInvolved[j], notInvolved[i] + }) + players := map[string][]string{} + cardsPerPlayer := len(notInvolved) / len(playerOrder) + // playerOrder := []string{"{{user}}", "{{char}}", "{{char2}}"} + for i, player := range playerOrder { + start := i * cardsPerPlayer + end := (i + 1) * cardsPerPlayer + if end > len(notInvolved) { + end = len(notInvolved) + } + players[player] = notInvolved[start:end] + } + res.Answer = trifecta + res.PlayersCards = players + return res +} diff --git a/extra/cluedo_test.go b/extra/cluedo_test.go new file mode 100644 index 0000000..e7a53b1 --- /dev/null +++ b/extra/cluedo_test.go @@ -0,0 +1,50 @@ +package extra + +import ( + "testing" +) + +func TestPrepCards(t *testing.T) { + // Run the function to get the murder combination and player cards + roundInfo := CluedoPrepCards([]string{"{{user}}", "{{char}}", "{{char2}}"}) + // Create a map to track all distributed cards + distributedCards := make(map[string]bool) + // Check that the murder combination cards are not distributed to players + murderCards := []string{roundInfo.Answer.Murderer, roundInfo.Answer.Weapon, roundInfo.Answer.Room} + for _, card := range murderCards { + if distributedCards[card] { + t.Errorf("Murder card %s was distributed to a player", card) + } + } + // Check each player's cards + for player, cards := range roundInfo.PlayersCards { + for _, card := range cards { + // Ensure the card is not part of the murder combination + for _, murderCard := range murderCards { + if card == murderCard { + t.Errorf("Player %s has a murder card: %s", player, card) + } + } + // Ensure the card is unique and not already distributed + if distributedCards[card] { + t.Errorf("Card %s is duplicated in player %s's hand", card, player) + } + distributedCards[card] = true + } + } + // Verify that all non-murder cards are distributed + allCards := append(append([]string{}, rooms...), weapons...) + allCards = append(allCards, people...) + for _, card := range allCards { + isMurderCard := false + for _, murderCard := range murderCards { + if card == murderCard { + isMurderCard = true + break + } + } + if !isMurderCard && !distributedCards[card] { + t.Errorf("Card %s was not distributed to any player", card) + } + } +} |