Giter Club home page Giter Club logo

pokemonbattlelib's People

Contributors

a-very-cunning-ham avatar adapap avatar adriang11 avatar carpenterd777 avatar dyc3 avatar grinchpal avatar jordan883 avatar krixstin avatar rdhadda123 avatar svuong959 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pokemonbattlelib's Issues

Pokemon Party building tools

Is your feature request related to a problem? Please describe.
Users are going to want to build parties quickly, and we're going to want it to write tests.

Currently, the steps to building a party are:

  1. Create the party
  2. Create the pokemon
  3. Set the pokemon moves
  4. Set the pokemon stats
  5. Set the pokemon's current hp to the max hp
  6. Repeat 2-5 up to 5 more times
  7. Add all the pokemon to the party

This kinda sucks, especially because of step 5.

Describe the solution you'd like

There should be some way to generate pokemon with correct stats based on the national dex number and level

The process should look more like:

  1. Create the party
  2. Generate a pokemon
  3. Set the pokemon moves
  4. Repeat 2-3 up to 5 more times
  5. Add all the pokemon to the party

However, it needs to still be possible to hand craft pokemon if needed. This would be just a convenience tool.

Describe alternatives you've considered

Additional context

Add the Pokemon Type

Obviously, we need a type to represent a Pokemon in a battle. Keep memory footprint in mind when considering what types to use. Feel free to add any enums that you need to accomplish this.

See: https://github.com/StevensSEC/pokemonbattlelib/wiki/Requirements#pokemon

It's not necessary for the first iteration of this type to be perfect. We can change it later if needed.

Tasks

  • Define the contents of type Pokemon struct that are necessary to have in a Pokemon battle, or to be able to obtain external metadata.
    • For example: the Pokemon's name should not be stored in the struct, but the National Pokedex number should since it can be used to look up the Pokemon's name.
  • Implement the Stringer interface for Pokemon. Example: https://tour.golang.org/methods/17

Add the Battle type

We need a way to track the current state of a Pokemon battle.

It's not necessary for the first iteration of this type to be perfect. We can change it later if needed.

Tasks

  • Define the contents of type Battle struct that necessary for a Pokemon battle.

Example Pokemon Battles

We need test cases to ensure the accuracy of our Pokemon battle implementation.

Eventually, we will turn these into automated test cases.

Tasks

  • Describe 3 Pokemon battles from start to finish, clearly documenting the results for each turn with the reason for why it happened, and put it in the documentation (docs/example-battles.md)
    • If possible, include the RNG seed at the start of the battle, damage numbers, buffs, debuffs, etc. The more information the better.
    • One battle should be as simple as possible, avoiding edge cases, between 2 low level Pokemon (one on each side).
    • One battle should include super-effective/not-very-effective type matchups.
    • The complexity of the last battle is up to your discretion.

"Remote controlled" Agent for use in testing

Is your feature request related to a problem? Please describe.
We need some way to supply the battle with turns from an Agent in a specific order in tests.

Describe the solution you'd like
An Agent that has a channel that it takes a Turn from and returns it when Act is called. This will allow us to write tests that check specific sequences of Turns easier.

Describe alternatives you've considered

Additional context

Sort turns by priority

In a Pokemon battle, certain types of turns are supposed to occur before others.

Relevant code:

pokemonbattlelib/battle.go

Lines 118 to 122 in 07c4cf0

turnOrder := []int{}
// TODO: determine the correct order based on priority and other factors
for i := range active {
turnOrder = append(turnOrder, i)
}

Sort turnOrder in descending order by Priority() on the corresponding turns. Allow the ability to add other factors that can affect the sorting order.

This may be useful: https://golang.org/pkg/sort/

Code generation for moves

Currently, the code generation script parses the available moves, but it does not actually output any generated code for them.

Items: Berries

Add functionality for effects of berries in battle. Each berry is consumed upon usage and typically affects 1 or more stat values.

See: https://veekun.com/dex/items/berries

In-a-pinch

Num Item Effect
57 Apicot Berry Held: Consumed at 1/4 max HP to boost Special Defense.
62 Custap Berry Held: Consumed at 1/4 max HP when using a move to go first.
54 Ganlon Berry Held: Consumed at 1/4 max HP to boost Defense.
58 Lansat Berry Held: Consumed at 1/4 max HP to boost critical hit ratio by two stages.
53 Liechi Berry Held: Consumed at 1/4 max HP to boost Attack.
61 Micle Berry Held: Consumed at 1/4 max HP to boost accuracy of next move by 20%. (Gen IV: Perfect accuracy)
56 Petaya Berry Held: Consumed at 1/4 max HP to boost Special Attack.
55 Salac Berry Held: Consumed at 1/4 max HP to boost Speed.
59 Starf Berry Held: Consumed at 1/4 max HP to boost a random stat by two stages.

Medicine

Num Item Effect
5 Aspear Berry Held: Consumed when frozen to cure frozen.
1 Cheri Berry Held: Consumed when paralyzed to cure paralysis.
2 Chesto Berry Held: Consumed when asleep to cure sleep.
6 Leppa Berry Held: Consumed when a move runs out of PP to restore its PP by 10.
9 Lum Berry Held: Consumed to cure any status condition or confusion.
7 Oran Berry Held: Consumed at 1/2 max HP to recover 10 HP.
3 Pecha Berry Held: Consumed when poisoned to cure poison.
8 Persim Berry Held: Consumed when confused to cure confusion.
4 Rawst Berry Held: Consumed when burned to cure a burn.
10 Sitrus Berry Held: Consumed at 1/2 max HP to recover 1/4 max HP.

Other

Num Item Effect
60 Enigma Berry Held: Consumed when struck by a super-effective attack to restore 1/4 max HP.
63 Jaboca Berry Held: Consumed to deal 1/8 attacker's max HP when holder is struck by a physical attack.
? Kee Berry Held: When the holder is hit by a physical move, increases its Defense by one stage.
? Maranga Berry Held: When the holder is hit by a special move, increases its Special Defense by one stage.
64 Rowap Berry Held: Consumed to deal 1/8 attacker's max HP when holder is struck by a special attack.

Picky Healing

Num Item Effect
14 Aguav Berry Held: Consumed at 1/2 max HP to restore 1/8 max HP. Confuses Pokémon that dislike bitter flavor.
11 Figy Berry Held: Consumed at 1/2 max HP to restore 1/8 max HP. Confuses Pokémon that dislike spicy flavor.
15 Iapapa Berry Held: Consumed at 1/2 max HP to restore 1/8 max HP. Confuses Pokémon that dislike sour flavor.
13 Mago Berry Held: Consumed at 1/2 max HP to restore 1/8 max HP. Confuses Pokémon that dislike sweet flavor.
12 Wiki Berry Held: Consumed at 1/2 max HP to restore 1/8 max HP. Confuses Pokémon that dislike dry flavor.

Type protection

Num Item Effect
51 Babiri Berry Held: Consumed when struck by a super-effective Steel-type attack to halve the damage.
47 Charti Berry Held: Consumed when struck by a super-effective Rock-type attack to halve the damage.
52 Chilan Berry Held: Consumed when struck by a Normal-type attack to halve the damage.
41 Chople Berry Held: Consumed when struck by a super-effective Fighting-type attack to halve the damage.
44 Coba Berry Held: Consumed when struck by a super-effective Flying-type attack to halve the damage.
50 Colbur Berry Held: Consumed when struck by a super-effective Dark-type attack to halve the damage.
49 Haban Berry Held: Consumed when struck by a super-effective Dragon-type attack to halve the damage.
48 Kasib Berry Held: Consumed when struck by a super-effective Ghost-type attack to halve the damage.
42 Kebia Berry Held: Consumed when struck by a super-effective Poison-type attack to halve the damage.
36 Occa Berry Held: Consumed when struck by a super-effective Fire-type attack to halve the damage.
37 Passho Berry Held: Consumed when struck by a super-effective Water-type attack to halve the damage.
45 Payapa Berry Held: Consumed when struck by a super-effective Psychic-type attack to halve the damage.
39 Rindo Berry Held: Consumed when struck by a super-effective Grass-type attack to halve the damage.
43 Shuca Berry Held: Consumed when struck by a super-effective Ground-type attack to halve the damage.
46 Tanga Berry Held: Consumed when struck by a super-effective Bug-type attack to halve the damage.
38 Wacan Berry Held: Consumed when struck by a super-effective Electric-type attack to halve the damage.
40 Yache Berry Held: Consumed when struck by a super-effective Ice-type attack to halve the damage.

Pokemon should faint when HP reaches 0.

We need a Transaction that can tell the battle that a pokemon has fainted.

  • Triggers when pokemon's reaches 0
  • Checks to see if any pokemon in the party have not fainted, if all are fainted, battle is over
  • Sends out next pokemon

Consolidate numeric types

We currently use a mix of int, uint, uint8, uint16, and float64 throughout the library. I think the performance benefits do not outweigh the confusion from mixing these types together, so I suggest that we pick 1 integer type and one floating point type.

Finish code generation for Pokemon

Currently, the code generation for pokemon only generates code to define their national dex number, and nothing else.

Now that #6 is complete, we need to add the rest of the fields to the code generation.

LinkAgentParty validation

Relevant code:

func (b *Battle) LinkAgentParty(agentIdx, partyIdx int) error {
if b.agentParties == nil {
b.agentParties = make(map[int]int)
}
// TODO: check if agentIdx, partyIdx are valid indexes
// TODO: check if agent is already linked
// TODO: check if party is already linked
b.agentParties[agentIdx] = partyIdx
return nil
}

Implement ItemTurn type and add case to SimulateRound()

This will represent a turn where a Trainer uses an item on their Pokemon (or an opposing Pokemon in the case of using a Poke Ball in a wild Pokemon battle).

See: https://github.com/StevensSEC/pokemonbattlelib/wiki/Requirements#bag-using-an-item

Items and their effect have yet to be implemented in full, so the actual use of the item does not have to have an effect yet.

Using an item always takes precedence to any FightTurns that may occur, essentially placing it in the highest priority bracket (higher than any move would have).

  • Using an item passes the turn
  • Using an item takes place before FightTurns
  • Add case to SimulateRound()

Add the ElementalType type

We need a way keep track of single and dual type Pokemon.

It's not necessary for the first iteration of this type to be perfect. We can change it later if needed.

Tasks

Dead pokemon can still take turns.

Current Behavior

If a pokemon faints before taking it's turn, it will ignore the fact that it is dead, and take it's turn anyway.

To Reproduce
Code snippet to reproduce the problem (if applicable)

Failing test case 1
func TestBattleDeadPokemonForfeitTurn(t *testing.T) {
	a1 := Agent(dumbAgent{})
	a2 := Agent(dumbAgent{})
	party1 := NewParty(&a1, 0)
	pkmn1 := GetPokemon(4)
	pkmn1.Stats = [6]uint{30, 10, 10, 10, 10, 10}
	pkmn1.CurrentHP = 1
	pound := GetMove(1)
	pkmn1.Moves[0] = &pound
	party1.AddPokemon(&pkmn1)
	party2 := NewParty(&a2, 1)
	pkmn2 := GetPokemon(7)
	pkmn2.Stats = [6]uint{30, 10, 10, 10, 10, 100}
	pkmn2.CurrentHP = 30
	pkmn2.Moves[0] = &pound
	party2.AddPokemon(&pkmn2)
	b := NewBattle()
	b.AddParty(party1, party2)
	err := b.Start()
	if err != nil {
		t.Fatal("failed to start battle")
	}

	transactions, ended := b.SimulateRound()
	if !ended {
		t.Error("Expected SimulateRound to indicate that the battle has ended, but it did not.")
	}
	if n := len(transactions); n != 3 {
		t.Errorf("Expected 3 transactions to occur, got %d", n)
	}
	logtest := []struct {
		turn Transaction
		want string
	}{
		{
			turn: transactions[0],
			want: "Squirtle used Pound on Charmander for 3 damage.",
		},
		{
			turn: transactions[1],
			want: "Charmander fainted.",
		},
		{
			turn: transactions[2],
			want: "The battle has ended.",
		},
	}
	for _, tt := range logtest {
		got := tt.turn.BattleLog()
		if got != tt.want {
			t.Errorf("Expected battle log to be %s, got %s", tt.want, got)
		}
	}
}
Failing test case 2
func TestBattleDeadPokemonForfeitTurn2(t *testing.T) {
	a1 := Agent(dumbAgent{})
	a2 := Agent(dumbAgent{})
	party1 := NewParty(&a1, 0)
	pkmn1 := GetPokemon(4)
	pkmn3 := GetPokemon(387)
	pkmn1.Stats = [6]uint{30, 10, 10, 10, 10, 10}
	pkmn1.CurrentHP = 1
	pkmn3.Stats = [6]uint{30, 10, 10, 10, 10, 10}
	pkmn3.CurrentHP = 30
	pound := GetMove(1)
	pkmn1.Moves[0] = &pound
	pkmn3.Moves[0] = &pound
	party1.AddPokemon(&pkmn1, &pkmn3)
	party2 := NewParty(&a2, 1)
	pkmn2 := GetPokemon(7)
	pkmn2.Stats = [6]uint{30, 10, 10, 10, 10, 100}
	pkmn2.CurrentHP = 30
	pkmn2.Moves[0] = &pound
	party2.AddPokemon(&pkmn2)
	b := NewBattle()
	b.AddParty(party1, party2)
	err := b.Start()
	if err != nil {
		t.Fatal("failed to start battle")
	}

	transactions, _ := b.SimulateRound()
	if n := len(transactions); n != 3 {
		t.Errorf("Expected 3 transactions to occur, got %d", n)
	}
	logtest := []struct {
		turn Transaction
		want string
	}{
		{
			turn: transactions[0],
			want: "Squirtle used Pound on Charmander for 3 damage.",
		},
		{
			turn: transactions[1],
			want: "Charmander fainted.",
		},
		{
			turn: transactions[2],
			want: "Turtwig was sent out.",
		},
	}
	for _, tt := range logtest {
		got := tt.turn.BattleLog()
		if got != tt.want {
			t.Errorf("Expected battle log to be %s, got %s", tt.want, got)
		}
	}
}

Expected Behavior

Inactive pokemon should be unable to take turns. If a pokemon is deactivated before it takes it's turn, the turn is ignored.

Additional context

Add RNG Interface

We need an interface to handle random number generators. More specifically, we need an interface that we can use to implement various RNG algorithms used in Pokemon games. See: https://github.com/StevensSEC/pokemonbattlelib/wiki/Requirements#rng

For the initial seed, since getting the delay between the player starting the game and pressing "Continue", we can probably ignore it.

Tasks

  • Create an interface type to handle setting the seed and generating random numbers between 2 values (inclusive)
  • Implement this interface on a new type which implements the LCRNG described here.
    • Allow setting the seed
    • Generate seed
      • Get the date and time

Implement SwitchTurn type and add case to SimulateRound()

This will represent a turn where a Trainer changes their active Pokemon (the one currently battling) to a Pokemon in their party that has not yet fainted.

See: https://github.com/StevensSEC/pokemonbattlelib/wiki/Requirements#pokemon-switching-out

Switching Pokemon always takes precedence to any FightTurns that may occur, essentially placing it in the highest priority bracket (higher than any move would have). (The exception is the move Pursuit, but this has not been implemented yet. It should be kept in mind while designing the type though.)

  • Switching Pokemon passes the turn
  • Switching Pokemon takes place before any FightTurns
  • A Trainer cannot switch to a fainted Pokemon
  • A Trainer cannot switch to the already active Pokemon
  • Add case to SimulateRound()

Add the HoldItem type

Held items change the way that a Pokemon battle functions drastically. Each hold item belongs to a class (such as Stat Modifier, Medicine, Berries, or other effects. Representing items will be challenging, as there are many different types of items that produce different effects. Also, we must determine if we want to include all possible items or only those which have an affect on the battle itself.

This issue should be incremental, with the data representation being the first and simplest layer.

go generate does not regenerate pokedex_GEN.go

Current Behavior

go generate does not regenerate pokedex_GEN.go

To Reproduce

  1. delete pokedex_GEN.go
  2. run go generate
  3. See that pokedex_GEN.go is not created.

Expected Behavior

go generate should regenerate pokedex_GEN.go, even if pokedex_GEN.go is not already present.

Additional context
Seems like pokedex.go was removed. pokedex.go should be recreated with

//go:generate go run data/gen.go

Note that there is no spaces in //go:generate

CI

  • Runs tests
  • Collects code coverage
  • CI success status badge in README
  • Code coverage badge in README

GetOpponents returns incorrect results

Current Behavior

GetOpponents returns the same results as GetAllies

Expected Behavior

GetAllies should return friendly targets.
GetOpponents should return enemy targets.

Additional context

Example code for starting a battle

We need to provide code examples for starting a new battle in the documentation. Preferably, we should have a minimal example in the readme, as well as an example or 2 in examples_test.go.

Enforce gofmt in CI

For some reason, some people's editors are not automatically running gofmt on the code. This causes erroneous changes to be made when somebody's editor does auto run gofmt, and it clogs up diffs when reviewing pull requests.

Tasks

  • Have CI test to make sure gofmt won't modify any files
    • Maybe auto commit corrections?
    • test -z $(gofmt -l . | tr -d '\n') returns non-zero exit code if this test fails
  • Have codegen script run gofmt on generated code

Abstract transactions for organization/testing

Transactions are becoming too complex to keep in the scope of battles. We can introduce a new file, transactions.go to manage the different types of transactions as they scale as well as test them separately without creating battle instances. Additionally, the logic performed by transactions should be separate so that we can unit test its functionality.

Quick example:
ItemTurn should add transactions based on the item function. Using a potion should produce an ItemTransaction (to consume the potion) and a HealTransaction (to restore HP). The handlers for both transactions should be separate functions that we can test.

Implement RunTurn type and add case to SimulateRound()

This will represent a turn where a Trainer or Pokemon attempts to leave a battle.

See: https://github.com/StevensSEC/pokemonbattlelib/wiki/Requirements#run-running-away

This option has different behavior depending on if the battle is between a player Trainer and another player Trainer, a player Trainer and an NPC Trainer, or a Trainer and a wild Pokemon:

  • In a battle between two player Trainers, this option is equivalent to attempt to forfeit the match. The match ends in a loss for the player Trainer who selected this option if the other Trainer selects any other option. The match ends in a draw if both Trainers select this option on the same turn.

  • In a battle between a player Trainer and an NPC Trainer, this option cannot be selected, and a message is displayed to warn the player Trainer without passing their turn. NPC Trainers will not select this option.

  • In a battle between a player Trainer and a wild Pokemon, if the player Trainer attempts to flee, the Speeds of the two Pokemon active in the battle are compared and success is determined using the formula linked above. If the wild Pokemon attempts to flee, it succeeds without needing to compare its Speed. If either Pokemon has an effect that prevents them from fleeing, selecting this option fails. This will not pass the turn for the Trainer, and the wild Pokemon cannot select this option.

  • Multi player Trainer case functional

    • One team selecting option causes match loss for that team
    • All teams selecting option on same turn causes match draw
  • Trainer and NPC case functional

    • Player receives warning upon selecting this option
    • Turn is not passed
  • Trainer and wild Pokemon case functional

    • Speed comparison performed for Trainer
    • No speed comparison performed for wild Pokemon
    • Both Trainer and wild Pokemon can be rendered unable to flee
  • Add case to SimulateRound()

  • Running takes precedence over FightTurns

Tests that check std output pass when they shouldn't

Current Behavior

Some of the current tests that check the std output are not actually checking it.

To Reproduce
If you take the TestBattleOneRound and change the expected output, the test will still pass.

Evironment:

  • OS: Ubuntu 20.04

Additional context

Add rng provider to Battle.

We need some way for battles to generate random numbers predictably even if the user is running multiple battles at the same time.

To do this, we need to add a field to the battle struct with the type RNG (which is already defined in rng.go).

type Battle struct {
Weather int // one of the 6 in-battle weather conditions
ShiftSet bool // shift or set battle style for NPC trainer battles
State BattleState
parties []*party // All parties participating in the battle
}

NewBattle should initialize this field.

func NewBattle() *Battle {
b := Battle{
State: BEFORE_START,
}
return &b
}

Battle Log/History

Is your feature request related to a problem? Please describe.
We need some way to let users know what happened in each round of the battle.

Describe the solution you'd like
Possible solution:

  • Have each turn implement a BattleLog() method that outputs a string that would be end-user facing (eg. "Bulbasaur used X for -Y HP. It was super effective!"), and also have Turns make data about the result publicly accessible so that users could do animations and stuff. The battle could then just record the turns.

Additional context
Also may be necessary to fix #49 .

Remove extra csv files

The \data directory contains some extra csv files. For example, conquest_kingdoms_names.csv contains the names of the kingdoms from the Pokemon Conquest spinoff game and super_contest_effect_prose.csv contains the effect text for moves during a Super Contest. This might make it confusing what information needs to be used in the future.

Proposal

Remove csv files not directly relevant to Pokemon data, move data, or any other data that would be relevant in a Pokemon battle.

pkg.go.dev doesn't seem to be picking up our nightly releases

Current Behavior

pkg.go.dev doesn't seem to be picking up our nightly releases right away.

Expected Behavior

Expected documentation on pkg.go.dev to be up to date.

Additional context
Maybe it requires a new tag every time instead of updating an existing tag.

It does update, but every 2-3 weeks?

EV Transactions

Add transactions and helper functions to manipulate EVs of a Pokemon.

Data entry and accessing it at runtime

We need to be able to access metadata about pokemon, moves, etc at runtime. pokedex.go should manage this information.

Desired Solution

Code generation based on files. When go build is run, it should run a script to generate the code with the metadata. This is accomplished with the magic comment go:generate.

This example will run gen.go before building the rest of the package.

//go:generate go run gen.go

The script should read some files out of the data/ directory, and generate code based on it's contents.

Tasks

  • File format(s) or schemas for metadata
  • API for accessing metadata
  • Script for generating code
  • Data entry
    • Pokemon
    • Moves

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.