Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions tta-server/app/controllers/GameStateResource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import javax.inject.Singleton
import logic.Logic
import models.ActionId
import models.DeltaPlayerState
import models.DerivedGameState
import models.GameState
import models.PlayerIndex
import models.PlayerState
Expand All @@ -18,9 +19,7 @@ import play.api.mvc.Controller
@Singleton
class GameStateResource @Inject() () extends Controller {

def derivedGameState = Logic.deriveGameState(gameState)
def activePlayerState = gameState.activePlayerState
def activePlayerDerivedState = derivedGameState.derivedPlayerStates(gameState.activePlayerIndex)

var gameState = GameState(
PlayerIndex(0),
Expand All @@ -34,24 +33,22 @@ class GameStateResource @Inject() () extends Controller {

def runAction(actionIdString: String) = Action {
val actionId = ActionId(actionIdString)
val action = activePlayerDerivedState.actions(actionId)
gameState = gameState.updatedActivePlayerState(DeltaPlayerState.applyDeltaPlayerState(action.doIt(gameState)))
val action = gameState.getActionsForActivePlayer(actionId)
gameState = gameState.updatedActivePlayerState(action.deltaPlayerState.applyDeltaPlayerState(activePlayerState))

Ok(makeResponse(gameState))
}

def endTurn = Action {

val newActivePlayerState = Logic.updatePlayerStateAtEndOfTurn(activePlayerState, activePlayerDerivedState)

gameState = gameState.copy(
activePlayerIndex = gameState.activePlayerIndex.incrementMod(gameState.playerStates.size),
playerStates = gameState.playerStates.updated(gameState.activePlayerIndex, newActivePlayerState))
gameState = gameState.updatedActivePlayerState(
gameState.getEndTurnActionForActivePlayer.deltaPlayerState.applyDeltaPlayerState(activePlayerState)).copy(
activePlayerIndex = gameState.activePlayerIndex.incrementMod(gameState.playerStates.size))

Ok(makeResponse(gameState))
}

private[this] def makeResponse(gameState: GameState): JsValue = {
val derivedGameState = Logic.deriveGameState(gameState)
val derivedGameState = DerivedGameState(activePlayerActions = gameState.getActionsForActivePlayer)
Json.obj(
"gameState" -> gameState,
"derivedGameState" -> derivedGameState)
Expand Down
43 changes: 0 additions & 43 deletions tta-server/app/logic/Logic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,5 @@ import models._
import scala.collection.immutable

object Logic {

def deriveGameState(gameState: GameState): DerivedGameState = {
DerivedGameState(
derivedPlayerStates = gameState.playerStates.map { case (playerIndex, _) =>
playerIndex -> derivePlayerState(playerIndex, gameState)
})
}

def derivePlayerState(playerIndex: PlayerIndex, gameState: GameState): DerivedPlayerState = {

// Generate valid DerivedPlayerStates from civil cards in hand
val civilHandDerivedPlayerStates = gameState.activePlayerState.civilHand.map { card =>
card.generatePlayActionDerivedPlayerState(gameState)
}.toList

// Generate valid DerivedPlayerStates from techs that have been researched
val techsDerivedPlayerStates = gameState.activePlayerState.techs.map { tech =>
tech.generateResearchedDerivedPlayerState(gameState)
}.toList

// Generate increase population action, if valid
val increasePopulationDerivedPlayerStates =
List(Population.generateIncreasePopulationActionDerivedPlayerState(gameState))

// Calculate resource gains from buildings you've already built
val playerState = gameState.playerStates(playerIndex)
val buildingEffects = playerState.buildings.map(_.derivePlayerState(gameState))

// Pool everything together
val allEffects = civilHandDerivedPlayerStates ++ techsDerivedPlayerStates ++
increasePopulationDerivedPlayerStates ++ buildingEffects

allEffects.fold(DerivedPlayerState.empty)(_ + _)
}

def updatePlayerStateAtEndOfTurn(
playerState: PlayerState,
derivedPlayerState: DerivedPlayerState): PlayerState = {
playerState.copy(
ore = playerState.ore + derivedPlayerState.orePerTurn,
food = playerState.food + derivedPlayerState.foodPerTurn,
science = playerState.science + derivedPlayerState.sciencePerTurn)
}

}
4 changes: 2 additions & 2 deletions tta-server/app/models/Action.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import play.api.libs.json.OWrites
import play.api.libs.json.Reads

trait Action {
def doIt(gameState: GameState): DeltaPlayerState
def deltaPlayerState: DeltaPlayerState
}

object Action {
Expand All @@ -23,7 +23,7 @@ object Action {
}

val empty: Action = new Action {
def doIt(gameState: GameState): DeltaPlayerState = DeltaPlayerState.empty
def deltaPlayerState: DeltaPlayerState = DeltaPlayerState.empty
}
}

42 changes: 15 additions & 27 deletions tta-server/app/models/Building.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,27 @@ import play.api.libs.json.Reads
import play.api.libs.json.Writes

trait Building extends Tech {
def derivePlayerState(gameState: GameState): DerivedPlayerState
def costToBuild: Int
def deltaPlayerStateAtEndTurnIfBuilt: DeltaPlayerState

private def canBuild(gameState: GameState): Boolean = {
gameState.activePlayerState.ore >= this.costToBuild &&
gameState.activePlayerState.population >= 1
}

override def generateResearchedDerivedPlayerState(gameState: GameState): DerivedPlayerState = {
override def getResearchedAction(gameState: GameState): Option[(ActionId, Action)] = {
val building = this
val actions: Map[ActionId, Action] = {
if (building.canBuild(gameState)) {
val buildAction: Action = new Action {
override def doIt(gameState: GameState): DeltaPlayerState = DeltaPlayerState.empty.copy(
newBuildings = List(building),
population = -1,
ore = -building.costToBuild)
}
Map(ActionId("build" + this.prettyName) -> buildAction)
} else {
Map.empty
if (building.canBuild(gameState)) {
val buildAction: Action = new Action {
override def deltaPlayerState: DeltaPlayerState = DeltaPlayerState.empty.copy(
newBuildings = List(building),
population = -1,
ore = -building.costToBuild)
}
Some(ActionId("build" + this.prettyName) -> buildAction)
} else {
None
}

DerivedPlayerState.empty.copy(actions = actions)
}
}

Expand All @@ -51,21 +47,17 @@ case class Bronze(foo: Int) extends Building with Mine {
override val prettyName = "Bronze"
override val costToBuild: Int = 2
override val costToResearch: Int = 0
override val deltaPlayerStateAtEndTurnIfBuilt = DeltaPlayerState.empty.copy(ore = 1)

def derivePlayerState(gameState: GameState): DerivedPlayerState = {
DerivedPlayerState.empty.copy(orePerTurn = 1)
}
}

case class Iron(foo: Int) extends Building with Mine {

override val prettyName = "Iron"
override val costToBuild: Int = 5
override val costToResearch: Int = 5
override val deltaPlayerStateAtEndTurnIfBuilt = DeltaPlayerState.empty.copy(ore = 2)

def derivePlayerState(gameState: GameState): DerivedPlayerState = {
DerivedPlayerState.empty.copy(orePerTurn = 2)
}
}


Expand All @@ -76,10 +68,8 @@ case class Agriculture(foo: Int) extends Building with Farm {
override val prettyName = "Agriculture"
override val costToBuild: Int = 2
override val costToResearch: Int = 0
override val deltaPlayerStateAtEndTurnIfBuilt = DeltaPlayerState.empty.copy(food = 1)

def derivePlayerState(gameState: GameState): DerivedPlayerState = {
DerivedPlayerState.empty.copy(foodPerTurn = 1)
}
}


Expand All @@ -89,8 +79,6 @@ case class Philosophy(foo: Int) extends Building with Lab {
override val prettyName = "Philosophy"
override val costToBuild: Int = 3
override val costToResearch: Int = 0
override val deltaPlayerStateAtEndTurnIfBuilt = DeltaPlayerState.empty.copy(science = 1)

def derivePlayerState(gameState: GameState): DerivedPlayerState = {
DerivedPlayerState.empty.copy(sciencePerTurn = 1)
}
}
2 changes: 1 addition & 1 deletion tta-server/app/models/Card.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import play.api.libs.json.Writes

trait Card {
def prettyName: String
def generatePlayActionDerivedPlayerState(gameState:GameState): DerivedPlayerState
def getPlayAction(gameState:GameState): Option[(ActionId, Action)]
}

object Card {
Expand Down
36 changes: 25 additions & 11 deletions tta-server/app/models/DeltaPlayerState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,35 @@ case class DeltaPlayerState(
population: Int,
ore: Int,
food: Int,
science: Int)
science: Int) {

object DeltaPlayerState {
def +(other: DeltaPlayerState): DeltaPlayerState = {
DeltaPlayerState(
newBuildings = newBuildings ++ other.newBuildings,
newTechs = newTechs ++ other.newTechs,
newCivilHand = newCivilHand ++ other.newCivilHand,
removedCivilHand = removedCivilHand ++ other.removedCivilHand,
population = population + other.population,
ore = ore + other.ore,
food = food + other.food,
science = science + other.science)
}

def applyDeltaPlayerState(deltaPlayerState: DeltaPlayerState): (PlayerState => PlayerState) = {
(playerState: PlayerState) => PlayerState(
buildings = playerState.buildings ++ deltaPlayerState.newBuildings,
techs = playerState.techs ++ deltaPlayerState.newTechs,
civilHand = (playerState.civilHand ++ deltaPlayerState.newCivilHand) diff deltaPlayerState.removedCivilHand,
population = playerState.population + deltaPlayerState.population,
ore = playerState.ore + deltaPlayerState.ore,
food = playerState.food + deltaPlayerState.food,
science = playerState.science + deltaPlayerState.science)
def applyDeltaPlayerState(playerState: PlayerState): PlayerState = {
PlayerState(
buildings = playerState.buildings ++ this.newBuildings,
techs = playerState.techs ++ this.newTechs,
civilHand = (playerState.civilHand ++ this.newCivilHand) diff this.removedCivilHand,
population = playerState.population + this.population,
ore = playerState.ore + this.ore,
food = playerState.food + this.food,
science = playerState.science + this.science)
}

}

object DeltaPlayerState {

val empty = DeltaPlayerState(
newBuildings = List.empty,
newTechs = List.empty,
Expand Down
2 changes: 1 addition & 1 deletion tta-server/app/models/DerivedGameState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import play.api.libs.json.Reads
import scala.collection.immutable

case class DerivedGameState(
derivedPlayerStates: Map[PlayerIndex, DerivedPlayerState])
activePlayerActions: Map[ActionId, Action])

object DerivedGameState {
import util.JsonFormats.Implicits.mapFormat
Expand Down
34 changes: 0 additions & 34 deletions tta-server/app/models/DerivedPlayerState.scala

This file was deleted.

39 changes: 37 additions & 2 deletions tta-server/app/models/GameState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,43 @@ case class GameState(
playerStates(activePlayerIndex)
}

def updatedActivePlayerState(f: PlayerState => PlayerState): GameState = {
copy(playerStates = playerStates.updated(activePlayerIndex, f(activePlayerState)))
def updatedActivePlayerState(playerState: PlayerState): GameState = {
copy(playerStates = playerStates.updated(activePlayerIndex, playerState))
}

def getEndTurnActionForActivePlayer: Action = {

val gameState = this
new Action {
override def deltaPlayerState: DeltaPlayerState = {
gameState.activePlayerState.buildings.map { building =>
building.deltaPlayerStateAtEndTurnIfBuilt
}.foldLeft(DeltaPlayerState.empty)(_ + _)
}
}

}

def getActionsForActivePlayer: Map[ActionId, Action] = {

// Generate valid play actions from civil cards in hand
val civilHandPlayActions = this.activePlayerState.civilHand.flatMap { card =>
card.getPlayAction(this)
}.toMap

// Generate valid actions from techs that have been researched
val techResearchedActions = this.activePlayerState.techs.flatMap { tech =>
tech.getResearchedAction(this)
}.toMap

// Generate increase population action, if valid
val increasePopulationAction = Population.getIncreasePopulationAction(this)

// Pool everything together
val allActions: Map[ActionId, Action] = civilHandPlayActions ++ techResearchedActions ++ increasePopulationAction

allActions

}
}

Expand Down
21 changes: 9 additions & 12 deletions tta-server/app/models/Population.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,19 @@ object Population {
gameState.activePlayerState.food >= costToIncrease(gameState)
}

def generateIncreasePopulationActionDerivedPlayerState(gameState: GameState): DerivedPlayerState = {
def getIncreasePopulationAction(gameState: GameState): Option[(ActionId, Action)] = {

val actions: Map[ActionId, Action] = {
if (Population.canIncrease(gameState)) {
val increasePopulationAction: Action = new Action {
override def doIt(gameState: GameState): DeltaPlayerState = DeltaPlayerState.empty.copy(
population = 1,
food = -costToIncrease(gameState))
}
Map(ActionId("increasePopulation") -> increasePopulationAction)
} else {
Map.empty
if (Population.canIncrease(gameState)) {
val increasePopulationAction: Action = new Action {
override def deltaPlayerState: DeltaPlayerState = DeltaPlayerState.empty.copy(
population = 1,
food = -costToIncrease(gameState))
}
Some(ActionId("increasePopulation") -> increasePopulationAction)
} else {
None
}

DerivedPlayerState.empty.copy(actions = actions)
}

}
Loading