feat: added catch, inspect, and pokedex commands

This commit is contained in:
Stevan Freeborn
2026-07-29 06:52:44 -05:00
parent 017ac7a7bb
commit 7fb09a12fd
2 changed files with 171 additions and 11 deletions
+115 -9
View File
@@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"math/rand"
"os" "os"
"sort" "sort"
"time" "time"
@@ -11,11 +12,12 @@ import (
) )
type context struct { type context struct {
commands map[string]cliCommand commands map[string]cliCommand
client *pokeapi.Client client *pokeapi.Client
prevOffset int prevOffset int
nextOffset int nextOffset int
args []string args []string
caughtPokemon map[string]pokeapi.Pokemon
} }
func (r *context) register(c cliCommand) { func (r *context) register(c cliCommand) {
@@ -55,11 +57,31 @@ func NewContext() *context {
callback: commandExplore, callback: commandExplore,
} }
catchCommand := cliCommand{
name: "catch",
description: "Attempt to catch pokemon with given name",
callback: commandCatch,
}
inspectCommand := cliCommand{
name: "inspect",
description: "Inspect information about pokemon with given name if caught",
callback: commandInspect,
}
pokedexCommand := cliCommand{
name: "pokedex",
description: "Display the names of all pokemon you've caught",
callback: commandPokedex,
}
c := &context{ c := &context{
commands: map[string]cliCommand{}, commands: map[string]cliCommand{},
client: pokeapi.NewClient(pokecache.NewCache(5 * time.Second)), client: pokeapi.NewClient(pokecache.NewCache(5 * time.Second)),
prevOffset: 0, prevOffset: 0,
nextOffset: 0, nextOffset: 0,
args: []string{},
caughtPokemon: map[string]pokeapi.Pokemon{},
} }
c.register(exitCommand) c.register(exitCommand)
@@ -67,6 +89,9 @@ func NewContext() *context {
c.register(mapCommand) c.register(mapCommand)
c.register(mapBackCommand) c.register(mapBackCommand)
c.register(exploreCommand) c.register(exploreCommand)
c.register(catchCommand)
c.register(inspectCommand)
c.register(pokedexCommand)
return c return c
} }
@@ -165,3 +190,84 @@ func commandExplore(c *context) error {
return nil return nil
} }
func commandCatch(c *context) error {
// TODO: Probably want to allow user to decide
// if they want to catch a pokemon they've
// already caught. Maybe present xp of current
// vs encountered then let them choose.
if len(c.args) < 1 {
fmt.Println("Please provide pokemon name. i.e. catch <pokemon_name>")
return nil
}
pokemon, err := c.client.Pokemon.Get(c.args[0])
if err != nil {
return err
}
fmt.Printf("Throwing a Pokeball at %s...\n", pokemon.Name)
roll := rand.Intn(100)
baseChance := 75.0
pokemonXpMinValue := 0
pokemonXpMaxValue := 1000
pokemonXp := min(max(pokemon.BaseExperience, pokemonXpMinValue), pokemonXpMaxValue)
modifier := int(float64(pokemonXp) / float64(pokemonXpMaxValue) * float64(baseChance))
chance := int(baseChance) - modifier
if roll > chance {
c.caughtPokemon[pokemon.Name] = pokemon
fmt.Printf("You caught %s!\n", pokemon.Name)
} else {
fmt.Printf("%s was able to break free!\n", pokemon.Name)
}
return nil
}
func commandInspect(c *context) error {
if len(c.args) < 1 {
fmt.Println("Please provide pokemon name. i.e. inspect <pokemon_name>")
return nil
}
pokemonToInspect := c.args[0]
pokemon, caught := c.caughtPokemon[pokemonToInspect]
if !caught {
fmt.Printf("You have not previously caught a %s", pokemonToInspect)
return nil
}
fmt.Printf("Name: %s\n", pokemon.Name)
fmt.Printf("Height: %d\n", pokemon.Height)
fmt.Printf("Weight: %d\n", pokemon.Weight)
fmt.Println("Stats:")
for _, stat := range pokemon.Stats {
fmt.Printf(" - %s: %d\n", stat.Stat.Name, stat.BaseStat)
}
fmt.Println("Types:")
for _, t := range pokemon.Types {
fmt.Printf(" - %s\n", t.Type.Name)
}
return nil
}
func commandPokedex(c *context) error {
fmt.Println("Your Pokedex:")
for _, pokemon := range c.caughtPokemon {
fmt.Printf(" - %s\n", pokemon.Name)
}
return nil
}
+56 -2
View File
@@ -19,6 +19,7 @@ type Client struct {
cache *pokecache.Cache cache *pokecache.Cache
Locations *locationsEndpoint Locations *locationsEndpoint
Pokemon *pokemonEndpoint
} }
func NewClient(cache *pokecache.Cache) *Client { func NewClient(cache *pokecache.Cache) *Client {
@@ -29,6 +30,7 @@ func NewClient(cache *pokecache.Cache) *Client {
} }
c.Locations = &locationsEndpoint{client: c, path: "/location-area"} c.Locations = &locationsEndpoint{client: c, path: "/location-area"}
c.Pokemon = &pokemonEndpoint{client: c, path: "/pokemon"}
return c return c
} }
@@ -160,12 +162,12 @@ type Location struct {
Url string `json:"url"` Url string `json:"url"`
} }
type Pokemon struct { type EncounteredPokemon struct {
Name string `json:"name"` Name string `json:"name"`
} }
type PokemonEncounter struct { type PokemonEncounter struct {
Pokemon Pokemon `json:"pokemon"` Pokemon EncounteredPokemon `json:"pokemon"`
} }
type LocationArea struct { type LocationArea struct {
@@ -220,3 +222,55 @@ func (le *locationsEndpoint) List(offset int) (Page[Location], error) {
return page, nil return page, nil
} }
type Stat struct {
Name string `json:"name"`
}
type PokemonStat struct {
BaseStat int `json:"base_stat"`
Effort int `json:"effort"`
Stat Stat `json:"stat"`
}
type Type struct {
Name string `json:"name"`
}
type PokemonType struct {
Type Type `json:"type"`
}
type Pokemon struct {
Id int `json:"id"`
Name string `json:"name"`
Height int `json:"height"`
Weight int `json:"weight"`
Stats []PokemonStat `json:"stats"`
Types []PokemonType `json:"types"`
BaseExperience int `json:"base_experience"`
}
type pokemonEndpoint struct {
path string
client *Client
}
func (pe *pokemonEndpoint) Get(name string) (Pokemon, error) {
var pokemon Pokemon
requestUrl := fmt.Sprintf("%s/%s", pe.path, name)
req, err := pe.client.NewRequest(http.MethodGet, requestUrl, map[string]string{}, nil)
if err != nil {
return pokemon, err
}
err = pe.client.doWithJsonResponse(req, &pokemon)
if err != nil {
return pokemon, err
}
return pokemon, nil
}