Created
October 27, 2018 23:01
-
-
Save pablitar/e802f45625125f53b30d76fd55ed2028 to your computer and use it in GitHub Desktop.
Gimnasio Pokemon 20182C TADP Aula 407
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pokemon | |
import scala.util.Try | |
object GimnasioPokemon { | |
type Actividad = Pokemon => Pokemon | |
class NoPuedeRealizarActividadException extends RuntimeException | |
trait TipoPokemon { | |
def debilidades: Set[TipoPokemon] = Set() | |
def esDebilContra(unTipo: TipoPokemon) = debilidades.contains(unTipo) | |
def unapply(unPokemon: Pokemon): Option[Pokemon] = | |
Some(unPokemon).filter(unPokemon => unPokemon.tieneTipo(this)) | |
} | |
case object Pelea extends TipoPokemon | |
case object Normal extends TipoPokemon | |
case object Fantasma extends TipoPokemon | |
case object Electrico extends TipoPokemon | |
case object Agua extends TipoPokemon | |
case object Fuego extends TipoPokemon { | |
override val debilidades = Set(Agua, Tierra, Roca) | |
} | |
case object Tierra extends TipoPokemon { | |
override val debilidades = Set(Agua) | |
} | |
case object Roca extends TipoPokemon { | |
override val debilidades = Set(Agua) | |
} | |
trait Piedra | |
case object PiedraElectrica extends Piedra | |
case class EspeciePokemon(resistenciaEvolutiva: Int, | |
tipo: TipoPokemon, | |
tipoSecundario: Option[TipoPokemon] = None, | |
evolucion: Option[(Pokemon => Boolean, EspeciePokemon)] = None) | |
trait EstadoPokemon { | |
def realizarActividad(pokemon: Pokemon, actividad: Actividad): Pokemon = actividad(pokemon) | |
def unapply(unPokemon: Pokemon): Option[Pokemon] = | |
Some(unPokemon).filter(unPokemon => unPokemon.estado == this) | |
} | |
case object OK extends EstadoPokemon | |
case object KO extends EstadoPokemon { | |
override def realizarActividad(pokemon: Pokemon, actividad: Actividad): Pokemon = { | |
throw new NoPuedeRealizarActividadException | |
} | |
} | |
case class Dormido(turnosRestantes: Int = 3) extends EstadoPokemon { | |
override def realizarActividad(pokemon: Pokemon, actividad: Actividad): Pokemon = { | |
if (turnosRestantes <= 1) pokemon.cambiarEstado(OK) | |
else pokemon.cambiarEstado(copy(turnosRestantes - 1)) | |
} | |
} | |
case object Paralizado extends EstadoPokemon | |
case class Rutina(nombre: String, actividades: Seq[Actividad]) | |
case class Pokemon( | |
experiencia: Int, | |
energia: Int, | |
energiaMaxima: Int, | |
fuerza: Int, | |
velocidad: Int, | |
especie: EspeciePokemon, | |
piedra: Option[Piedra] = None, | |
intercambiado: Boolean = false, | |
estado: EstadoPokemon = OK) { | |
def darPiedra(unaPiedra: Piedra) = copy(piedra = Some(unaPiedra)).chequearEvolucion() | |
def tienePiedra(unaPiedra: Piedra): Boolean = piedra.contains(unaPiedra) | |
def esDebilContra(unTipo: TipoPokemon) = tipo.esDebilContra(unTipo) || tipoSecundario.exists(_.esDebilContra(unTipo)) | |
require(energia >= 0, "La energia debe ser mayor a 0") | |
def perderEnergia(unaEnergia: Int): Pokemon = | |
copy(energia = (energia - unaEnergia).max(0)) | |
def ganarExperiencia(unaExperiencia: Int): Pokemon = { | |
copy(experiencia = experiencia + unaExperiencia).chequearEvolucion() | |
} | |
def chequearEvolucion(): Pokemon = { | |
especie.evolucion.find({ case (condicion, especie) => condicion(this) | |
}).map(ev => this.evolucionar(ev._2)).getOrElse(this) | |
} | |
def evolucionar(unaEspecie: EspeciePokemon): Pokemon = copy(especie = unaEspecie) | |
//Fuerza, Tipo principal, Tipo secundario | |
def recuperarAlMaximo: Pokemon = copy(energia = energiaMaxima) | |
def tipo = especie.tipo | |
def nivel: Int = experiencia / especie.resistenciaEvolutiva | |
def tipoSecundario = especie.tipoSecundario | |
def realizarActividad(actividad: Actividad): Pokemon = { | |
estado.realizarActividad(this, actividad) | |
} | |
def realizarRutina(rutina: Rutina): Try[Pokemon] = Try { | |
rutina.actividades.foldLeft(this)(_ realizarActividad _ ) | |
} | |
def cambiarEstado(unEstado: EstadoPokemon): Pokemon = copy(estado = unEstado) | |
def tieneTipo(tipoPokemon: TipoPokemon): Boolean = tipo == tipoPokemon || tipoSecundario.contains(tipoPokemon) | |
} | |
object PokemonConFuerza { | |
def unapply(unPokemon: Pokemon): Option[Int] = Some(unPokemon.fuerza) | |
} | |
object Actividades { | |
val descansar: Actividad = pokemon => (pokemon match { | |
case OK(p) if p.energia < p.energiaMaxima * 0.5 => p.cambiarEstado(Dormido()) | |
case p => p | |
}).recuperarAlMaximo | |
def levantarPesas(peso: Int): Actividad = { | |
case Fantasma(pokemon) => throw new NoPuedeRealizarActividadException() | |
case Paralizado(pokemon) => pokemon.cambiarEstado(KO) | |
case pokemon@PokemonConFuerza(fuerza) if peso > fuerza * 10 => | |
pokemon.perderEnergia(10).cambiarEstado(Paralizado) | |
case Pelea(pokemon) => pokemon.ganarExperiencia(peso * 2) | |
case pokemon => pokemon.ganarExperiencia(peso) | |
// else pokemon.ganarExperiencia(pokemon.puntosAGanar(peso)) | |
} | |
def nadar(minutos: Int): Actividad = | |
pokemon => (pokemon match { | |
case unPokemon if unPokemon.esDebilContra(Agua) => unPokemon.cambiarEstado(KO) | |
case Agua(unPokemon) => unPokemon.copy(velocidad = unPokemon.velocidad + minutos / 60) | |
case unPokemon => unPokemon | |
}).ganarExperiencia(20 * minutos).perderEnergia(minutos) | |
def usarPiedra(piedra: Piedra)(pokemon: Pokemon) = pokemon.darPiedra(piedra) | |
} | |
object Especies { | |
val charmeleon = EspeciePokemon(120, Fuego) | |
val charmander = EspeciePokemon(100, Fuego, evolucion = Some((_.nivel >= 16, charmeleon))) | |
val pikachu = EspeciePokemon(100, Electrico, evolucion = Some((_.tienePiedra(PiedraElectrica), charmeleon))) | |
val machoke = EspeciePokemon(120, Pelea) | |
} | |
object Criadero { | |
def crearPikachu: Pokemon = Pokemon(0, 100, 100, 5, 10, Especies.pikachu) | |
def crearMachoke: Pokemon = Pokemon(0, 100, 100, 5, 5, Especies.machoke) | |
} | |
} | |
object GimnasioPokemonApp extends App { | |
import GimnasioPokemon._ | |
val unMachoke = Criadero.crearMachoke | |
var pikachu = Criadero.crearPikachu | |
pikachu = Actividades.levantarPesas(5)(pikachu) | |
println(pikachu) | |
pikachu = Actividades.levantarPesas(5)(pikachu) | |
println(pikachu) | |
private val nadarMucho: Actividades = Actividades.nadar(30) | |
pikachu = nadarMucho(pikachu) | |
println(pikachu) | |
println(Actividades.levantarPesas(5)(unMachoke)) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment