Pokemon Server
Mix.install([
{:kino, github: "livebook-dev/kino", override: true},
{:kino_lab, "~> 0.1.0-dev", github: "jonatanklosko/kino_lab"},
{:vega_lite, "~> 0.1.4"},
{:kino_vega_lite, "~> 0.1.1"},
{:benchee, "~> 0.1"},
{:ecto, "~> 3.7"},
{:math, "~> 0.7.0"},
{:faker, "~> 0.17.0"},
{:utils, path: "#{__DIR__}/../utils"},
{:tested_cell, git: "https://github.com/BrooklinJazz/tested_cell"}
])
Navigation
Setup
Ensure you type the ea
keyboard shortcut to evaluate all Elixir cells before starting. Alternatively you can evaluate the Elixir cells as you read.
Overview
You’re going to create a pokemon battle game with persistence.
Pokemon will each be their own process storing the stats of a pokemon.
flowchart
PK[Pokemon]
PS[PokemonServer]
PS --> PK
PK --> name[name: charmander]
PK --> type[type: fire]
PK --> hp[health: 20]
PK --> at[attack: 5]
Pokemon can attack each other. An attack should update the Pokemon
‘s health in the PokemonServer
‘s state.
flowchart
PK1[Pokemon]
PK2[Pokemon]
PS1[PokemonServer]
PS2[PokemonServer]
PS1 --> PK1
PS2 --> PK2
PS1 --attack--> PS2
PK2 --> hp[health: 10]
Define A Pokemon Struct
In the Elixir cell below, define a Pokemon
struct. Use Ecto.Changeset
to validate the struct fields and ensure that:
-
:name
will be a string. -
:type
will be an atom of either:grass
,:water
, or:fire
-
:health
will be an integer0
or greater with a default value of20
-
:attack
will be an integer1
or greater with a default value of5
We should be able to create a new pokemon like so:
# Using default values
{:ok, %Pokemon{name: "charmander", type: "fire", health: 20, attack: 20}} =
Pokemon.new(%{name: "charmander", type: "fire"})
# Or manually setting all values
{:ok, bulbasaur} = Pokemon.new(%{name: "bulbasaur", type: "water", health: 30, attack: 2})
And we should get an error if we enter invalid input.
Pokemon.new(%{name: 1, type: "fire"})
{:error, changeset} = Pokemon.new(%{name: "bulbasaur", type: "water", health: 30, attack: 2})
Pokemon should be able to attack/2
other pokemon. Take type advantage into consideration.
see Pokemon Battle for a reminder on type advantages.
{:ok, charmander} = Pokemon.new(%{name: "charmander", type: "fire", damage: 20})
{:ok, bulbasaur} = Pokemon.new(%{name: "bulbasaur", type: "water", health: 100})
Pokemon.attack(charmander, bulbasaur)
%Pokemon{name: "bulbasaur", type: "water", damage: 5, health: 90}
Pokemon health should not fall below 0.
{:ok, charmander} = Pokemon.new(%{name: "charmander", type: "fire", damage: 110})
{:ok, bulbasaur} = Pokemon.new(%{name: "charmander", type: "fire", health: 100})
Pokemon.attack(charmander, bulbasaur)
%Pokemon{name: "charmader", type: "fire", damage: 5, health: 0}
Your Solution
Enter your solution in the Elixir cell below.
defmodule Pokemon do
end
Create A Pokemon Genserver
In the Elixir cell below, create a PokemonServer
Genserver which should store a Pokemon
struct in it’s state.
We should be able to start/1
a new pokemon server.
{:ok, charmander} = Pokemon.new(%{name: "charmander", type: "fire"})
charmander_server = PokemonServer.start(charmander)
We should be able to retrieve current stats of the Pokemon.
PokemonServer.stats(charmander_server)
%Pokemon{name: "charmander", type: "fire", health: 20, damage: 5}
We should be able to attack another pokemon.
{:ok, charmander} = Pokemon.new(%{name: "charmander", type: "fire", damage: 20})
{:ok, bulbasaur} = Pokemon.new(%{name: "bulbasaur", type: "water", health: 100})
charmander_server = PokemonServer.start(charmander)
bulbasaur_server = PokemonServer.start(charmander)
PokemonServer.attack(charmander, bulbasaur)
PokemonServer.stats(bulbasaur_server)
%Pokemon{name: "bulbasaur", type: "water", damage: 5, health: 90}
Your Solution
Enter your answer in the Elixir cell below.
defmodule PokemonServer do
end
Commit Your Progress
Run the following in your command line from the project folder to track and save your progress in a Git commit.
$ git add .
$ git commit -m "finish pokemon server exercise"