From ccb341fef4f7c9abb195bbfcb8dc09c075cc63a7 Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Fri, 20 Sep 2024 10:04:13 +0100 Subject: [PATCH] checkpoint: add 50% chance to catch a pokemon --- main.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index fcf0dc8..6916c9f 100644 --- a/main.go +++ b/main.go @@ -5,11 +5,13 @@ import ( "errors" "fmt" "maps" + "math/rand/v2" "os" "slices" "strings" "time" + "codeflow.dananglin.me.uk/apollo/pokedex/internal/api/pokeapi" "codeflow.dananglin.me.uk/apollo/pokedex/internal/pokeclient" ) @@ -18,8 +20,6 @@ type State struct { Next *string } -var state State - type command struct { name string description string @@ -28,6 +28,10 @@ type command struct { type callbackFunc func(args []string) error +type pokedex map[string]pokeapi.Pokemon + +var dexter = make(pokedex) + func main() { run() } @@ -38,6 +42,8 @@ func run() { 10*time.Second, ) + var state State + commandMap := map[string]command{ "exit": { name: "exit", @@ -52,18 +58,23 @@ func run() { "map": { name: "map", description: "Displays the next 20 locations in the Pokemon world", - callback: mapFunc(client), + callback: mapFunc(client, &state), }, "mapb": { name: "map back", description: "Displays the previous 20 locations in the Pokemon world", - callback: mapBFunc(client), + callback: mapBFunc(client, &state), }, "explore": { name: "explore", description: "Lists all the pokemon in a given area", callback: exploreFunc(client), }, + "catch": { + name: "catch", + description: "Catches a pokemon and adds them to your Pokedex", + callback: catchFunc(client), + }, } summaries := summaryMap(commandMap) @@ -137,26 +148,26 @@ func exitFunc(_ []string) error { return nil } -func mapFunc(client *pokeclient.Client) callbackFunc { +func mapFunc(client *pokeclient.Client, state *State) callbackFunc { return func(_ []string) error { url := state.Next if url == nil { url = new(string) - *url = pokeclient.LocationAreaEndpoint + *url = pokeclient.LocationAreaPath } - return printResourceList(client, *url) + return printResourceList(client, *url, state) } } -func mapBFunc(client *pokeclient.Client) callbackFunc { +func mapBFunc(client *pokeclient.Client, state *State) callbackFunc { return func(_ []string) error { url := state.Previous if url == nil { return fmt.Errorf("no previous locations available") } - return printResourceList(client, *url) + return printResourceList(client, *url, state) } } @@ -195,7 +206,46 @@ func exploreFunc(client *pokeclient.Client) callbackFunc { } } -func printResourceList(client *pokeclient.Client, url string) error { +func catchFunc(client *pokeclient.Client) callbackFunc { + return func(args []string) error { + if args == nil { + return errors.New("the name of the Pokemon has not been specified") + } + + if len(args) != 1 { + return fmt.Errorf( + "unexpected number of Pokemon names: want 1; got %d", + len(args), + ) + } + + pokemonName := args[0] + + fmt.Printf("Throwing a Pokeball at %s...\n", pokemonName) + + pokemon, err := client.GetPokemon(pokemonName) + if err != nil { + return fmt.Errorf( + "unable to get the information on %s: %w", + pokemonName, + err, + ) + } + + chance := 50 + + if caught := catchPokemon(chance); caught { + dexter[pokemonName] = pokemon + fmt.Printf("%s was caught!\n", pokemonName) + } else { + fmt.Printf("%s escaped!\n", pokemonName) + } + + return nil + } +} + +func printResourceList(client *pokeclient.Client, url string, state *State) error { list, err := client.GetNamedAPIResourceList(url) if err != nil { return fmt.Errorf("unable to get the list of resources: %w", err) @@ -234,3 +284,34 @@ func parseArgs(input string) (string, []string) { return split[0], split[1:] } + +func catchPokemon(chance int) bool { + if chance == 100 { + return true + } + + if chance == 0 { + return false + } + + maxInt := 100 + + numGenerator := rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64())) + + luckyNumberSet := make(map[int]struct{}) + + for len(luckyNumberSet) < chance { + num := numGenerator.IntN(maxInt) + if _, ok := luckyNumberSet[num]; !ok { + luckyNumberSet[num] = struct{}{} + } + } + + roller := rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64())) + + got := roller.IntN(maxInt) + + _, ok := luckyNumberSet[got] + + return ok +}