programaker / Joguin2

Toy Scala project to study some cool Functional Programming concepts (version 1 was in Java)
2 stars 0 forks source link

Changes for GameProgress and its Persistent sibling #4

Closed programaker closed 5 years ago

programaker commented 5 years ago

Writing the tests for the Game Steps that require a GameProgress made me think that this class is not so well designed - for example, Gen[GameProgress] is using GameProgress logic, which means code that need to be tested is being used as input to other tests =/

programaker commented 5 years ago

Ideas:

Current data:

Current behavior:

programaker commented 5 years ago

New ideas:

programaker commented 5 years ago
/* typeclass? object? distributed through app? */
//
//invasionByIndex: Index => Option[Invasion]
//invasionDefeated: Index => Boolean (move to HumanArmy as a kind of battlefield report)
//allInvasionsDefeated: Boolean (actually will be just a gameProgress match)
//defeatInvasion: Index => GameProgress (move to HumanArmy as: City.Invaded => City.Free)

sealed abstract class GameProgress extends Product with Serializable

object GameProgress {
    //invasionByIndex: Index => Option[Invasion] = cities.get(index)
    //invasionDefeated: Index => Boolean = false
    //allInvasionsDefeated: Boolean = false
    //defeatInvasion: Index => GameProgress = GameProgress.InBattle(...)
    final case class Start(
        mainCharacter: MainCharacter, 
        cities: Vector[City.Invaded]
    ) extends GameProgress

    //invasionByIndex: Index => Option[Invasion] = cities.get(index)
    //invasionDefeated: Index => Boolean = cities.get(index) then match 
    //allInvasionsDefeated: Boolean = defeatInvasions === cities.size
    //defeatInvasion: Index => GameProgress = GameProgress.InBattle(...) | GameProgress.MissionAccomplished
    final case class InBattle(
        mainCharacter: MainCharacter,
      cities: Vector[City], //cities invaded and free mixed
      defeatedInvasions: Count
    ) extends GameProgress

    //flag indicating the end of the game
    //invasionIsDefeated: Index => Boolean = true
    //allInvasionsDefeated: Boolean = true
    case object MissionAccomplished extends GameProgress
}

//////

final case class MainCharacter(
  name: Name,
  gender: Gender,
  age: Age,
  experience: Experience
)

//////

sealed abstract class City extends Product with Serializable

object City {
    final case class Free(name: Name, country: Country)
    final case class Invaded(city: City.Free, terraformDevice: TerraformDevice)
}
programaker commented 5 years ago

Ah... another idea! In the last sketch, we have different GameProgresses representing different states. What about moving the behavior to a typeclass?

GameProgress behavior would still be close to the data, but not in the data itself. Also, the typeclass will allow the game steps to deal with the progresses polymorphically

programaker commented 5 years ago

Not necessary; we've chosen to just add a flag defeated to the Invasion. Also, GameProgress behavior became stand-alone functions in the package game.progress