generated from templates/go-generic
117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package commands
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/rand/v2"
|
|
"slices"
|
|
|
|
"codeflow.dananglin.me.uk/apollo/pokecli/internal/pokeclient"
|
|
"codeflow.dananglin.me.uk/apollo/pokecli/internal/poketrainer"
|
|
)
|
|
|
|
func CatchFunc(client *pokeclient.Client, trainer *poketrainer.Trainer) CommandFunc {
|
|
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]
|
|
|
|
if _, caught := trainer.GetPokemonFromPokedex(pokemonName); caught {
|
|
return fmt.Errorf(
|
|
"you've already caught a %s",
|
|
pokemonName,
|
|
)
|
|
}
|
|
|
|
pokemonDetails, err := client.GetPokemon(pokemonName)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"unable to get the information on %s: %w",
|
|
pokemonName,
|
|
err,
|
|
)
|
|
}
|
|
|
|
encountersPath := pokemonDetails.LocationAreaEncounters
|
|
|
|
encounterAreas, err := client.GetPokemonLocationAreas(encountersPath)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"unable to get the Pokemon's possible encounter areas: %w",
|
|
err,
|
|
)
|
|
}
|
|
|
|
validLocationArea := false
|
|
currentLocation := trainer.CurrentLocationAreaName()
|
|
|
|
for _, area := range slices.All(encounterAreas) {
|
|
if currentLocation == area.LocationArea.Name {
|
|
validLocationArea = true
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
if !validLocationArea {
|
|
return fmt.Errorf(
|
|
"%s cannot be found in %s",
|
|
pokemonName,
|
|
currentLocation,
|
|
)
|
|
}
|
|
|
|
chance := 50
|
|
|
|
fmt.Printf("Throwing a Pokeball at %s...\n", pokemonName)
|
|
|
|
if caught := success(chance); caught {
|
|
trainer.AddPokemonToPokedex(pokemonName, pokemonDetails)
|
|
fmt.Printf("%s was caught!\nYou may now inspect it with the inspect command.\n", pokemonName)
|
|
} else {
|
|
fmt.Printf("%s escaped!\n", pokemonName)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func success(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
|
|
}
|