This commit is contained in:
Yair Morgenstern 2021-01-16 21:07:53 +02:00
parent 942aa981ba
commit 7e092fdf16
2 changed files with 53 additions and 44 deletions

View File

@ -27,17 +27,24 @@ import kotlin.math.roundToInt
* @property constructionQueue a list of constructions names enqueued * @property constructionQueue a list of constructions names enqueued
*/ */
class CityConstructions { class CityConstructions {
@Transient lateinit var cityInfo: CityInfo @Transient
@Transient private var builtBuildingObjects = ArrayList<Building>() lateinit var cityInfo: CityInfo
@Transient val builtBuildingUniqueMap = UniqueMap()
@Transient
private var builtBuildingObjects = ArrayList<Building>()
@Transient
val builtBuildingUniqueMap = UniqueMap()
var builtBuildings = HashSet<String>() var builtBuildings = HashSet<String>()
val inProgressConstructions = HashMap<String, Int>() val inProgressConstructions = HashMap<String, Int>()
var currentConstructionFromQueue: String var currentConstructionFromQueue: String
get() { get() {
if(constructionQueue.isEmpty()) return "" else return constructionQueue.first() if (constructionQueue.isEmpty()) return "" else return constructionQueue.first()
}
set(value) {
if (constructionQueue.isEmpty()) constructionQueue.add(value) else constructionQueue[0] = value
} }
set(value) { if(constructionQueue.isEmpty()) constructionQueue.add(value) else constructionQueue[0]=value }
var currentConstructionIsUserSet = false var currentConstructionIsUserSet = false
var constructionQueue = mutableListOf<String>() var constructionQueue = mutableListOf<String>()
val queueMaxSize = 10 val queueMaxSize = 10
@ -47,7 +54,7 @@ class CityConstructions {
val toReturn = CityConstructions() val toReturn = CityConstructions()
toReturn.builtBuildings.addAll(builtBuildings) toReturn.builtBuildings.addAll(builtBuildings)
toReturn.inProgressConstructions.putAll(inProgressConstructions) toReturn.inProgressConstructions.putAll(inProgressConstructions)
toReturn.currentConstructionIsUserSet=currentConstructionIsUserSet toReturn.currentConstructionIsUserSet = currentConstructionIsUserSet
toReturn.constructionQueue.addAll(constructionQueue) toReturn.constructionQueue.addAll(constructionQueue)
return toReturn return toReturn
} }
@ -122,7 +129,7 @@ class CityConstructions {
currentConstruction changed on another thread */ currentConstruction changed on another thread */
val currentConstructionSnapshot = currentConstructionFromQueue val currentConstructionSnapshot = currentConstructionFromQueue
var result = currentConstructionSnapshot.tr() var result = currentConstructionSnapshot.tr()
if (currentConstructionSnapshot!="" if (currentConstructionSnapshot != ""
&& !PerpetualConstruction.perpetualConstructionsMap.containsKey(currentConstructionSnapshot)) { && !PerpetualConstruction.perpetualConstructionsMap.containsKey(currentConstructionSnapshot)) {
val turnsLeft = turnsToConstruction(currentConstructionSnapshot) val turnsLeft = turnsToConstruction(currentConstructionSnapshot)
result += " - $turnsLeft${Fonts.turn}" result += " - $turnsLeft${Fonts.turn}"
@ -163,14 +170,14 @@ class CityConstructions {
} }
} }
class NotBuildingOrUnitException(message:String):Exception(message) class NotBuildingOrUnitException(message: String) : Exception(message)
throw NotBuildingOrUnitException("$constructionName is not a building or a unit!") throw NotBuildingOrUnitException("$constructionName is not a building or a unit!")
} }
internal fun getBuiltBuildings(): Sequence<Building> = builtBuildingObjects.asSequence() internal fun getBuiltBuildings(): Sequence<Building> = builtBuildingObjects.asSequence()
fun containsBuildingOrEquivalent(building: String): Boolean = fun containsBuildingOrEquivalent(building: String): Boolean =
isBuilt(building) || getBuiltBuildings().any{it.replaces==building} isBuilt(building) || getBuiltBuildings().any { it.replaces == building }
fun getWorkDone(constructionName: String): Int { fun getWorkDone(constructionName: String): Int {
if (inProgressConstructions.containsKey(constructionName)) return inProgressConstructions[constructionName]!! if (inProgressConstructions.containsKey(constructionName)) return inProgressConstructions[constructionName]!!
@ -188,7 +195,7 @@ class CityConstructions {
fun turnsToConstruction(constructionName: String, useStoredProduction: Boolean = true): Int { fun turnsToConstruction(constructionName: String, useStoredProduction: Boolean = true): Int {
val workLeft = getRemainingWork(constructionName, useStoredProduction) val workLeft = getRemainingWork(constructionName, useStoredProduction)
if(workLeft < 0) // we've done more work than actually necessary - possible if circumstances cause buildings to be cheaper later if (workLeft < 0) // we've done more work than actually necessary - possible if circumstances cause buildings to be cheaper later
return 1 // we'll finish this next turn return 1 // we'll finish this next turn
val cityStatsForConstruction: Stats val cityStatsForConstruction: Stats
@ -214,9 +221,11 @@ class CityConstructions {
//endregion //endregion
//region state changing functions //region state changing functions
fun setTransients(){ fun setTransients() {
builtBuildingObjects = ArrayList(builtBuildings.map { cityInfo.getRuleset().buildings[it] builtBuildingObjects = ArrayList(builtBuildings.map {
?: throw java.lang.Exception("Building $it is not found!")}) cityInfo.getRuleset().buildings[it]
?: throw java.lang.Exception("Building $it is not found!")
})
updateUniques() updateUniques()
} }
@ -226,11 +235,11 @@ class CityConstructions {
inProgressConstructions[currentConstructionFromQueue] = inProgressConstructions[currentConstructionFromQueue]!! + productionToAdd inProgressConstructions[currentConstructionFromQueue] = inProgressConstructions[currentConstructionFromQueue]!! + productionToAdd
} }
fun constructIfEnough(){ fun constructIfEnough() {
validateConstructionQueue() validateConstructionQueue()
val construction = getConstruction(currentConstructionFromQueue) val construction = getConstruction(currentConstructionFromQueue)
if(construction is PerpetualConstruction) chooseNextConstruction() // check every turn if we could be doing something better, because this doesn't end by itself if (construction is PerpetualConstruction) chooseNextConstruction() // check every turn if we could be doing something better, because this doesn't end by itself
else { else {
val productionCost = construction.getProductionCost(cityInfo.civInfo) val productionCost = construction.getProductionCost(cityInfo.civInfo)
if (inProgressConstructions.containsKey(currentConstructionFromQueue) if (inProgressConstructions.containsKey(currentConstructionFromQueue)
@ -244,7 +253,7 @@ class CityConstructions {
validateConstructionQueue() validateConstructionQueue()
validateInProgressConstructions() validateInProgressConstructions()
if(getConstruction(currentConstructionFromQueue) !is PerpetualConstruction) if (getConstruction(currentConstructionFromQueue) !is PerpetualConstruction)
addProductionPoints(cityStats.production.roundToInt()) addProductionPoints(cityStats.production.roundToInt())
} }
@ -301,24 +310,24 @@ class CityConstructions {
cityInfo.civInfo.addNotification("[${construction.name}] has been built in [" + cityInfo.name + "]", cityInfo.location, Color.BROWN) cityInfo.civInfo.addNotification("[${construction.name}] has been built in [" + cityInfo.name + "]", cityInfo.location, Color.BROWN)
} }
fun addBuilding(buildingName:String){ fun addBuilding(buildingName: String) {
val buildingObject = cityInfo.getRuleset().buildings[buildingName]!! val buildingObject = cityInfo.getRuleset().buildings[buildingName]!!
builtBuildingObjects = builtBuildingObjects.withItem(buildingObject) builtBuildingObjects = builtBuildingObjects.withItem(buildingObject)
builtBuildings.add(buildingName) builtBuildings.add(buildingName)
updateUniques() updateUniques()
} }
fun removeBuilding(buildingName:String){ fun removeBuilding(buildingName: String) {
val buildingObject = cityInfo.getRuleset().buildings[buildingName]!! val buildingObject = cityInfo.getRuleset().buildings[buildingName]!!
builtBuildingObjects = builtBuildingObjects.withoutItem(buildingObject) builtBuildingObjects = builtBuildingObjects.withoutItem(buildingObject)
builtBuildings.remove(buildingName) builtBuildings.remove(buildingName)
updateUniques() updateUniques()
} }
fun updateUniques(){ fun updateUniques() {
builtBuildingUniqueMap.clear() builtBuildingUniqueMap.clear()
for(building in getBuiltBuildings()) for (building in getBuiltBuildings())
for(unique in building.uniqueObjects) for (unique in building.uniqueObjects)
builtBuildingUniqueMap.addUnique(unique) builtBuildingUniqueMap.addUnique(unique)
} }
@ -369,7 +378,7 @@ class CityConstructions {
return cultureBuildingToBuild return cultureBuildingToBuild
} }
private fun removeCurrentConstruction() = removeFromQueue(0,true) private fun removeCurrentConstruction() = removeFromQueue(0, true)
fun chooseNextConstruction() { fun chooseNextConstruction() {
validateConstructionQueue() validateConstructionQueue()
@ -398,14 +407,13 @@ class CityConstructions {
} }
/** If this was done automatically, we should automatically try to choose a new construction and treat it as such */ /** If this was done automatically, we should automatically try to choose a new construction and treat it as such */
fun removeFromQueue(constructionQueueIndex: Int, automatic:Boolean) { fun removeFromQueue(constructionQueueIndex: Int, automatic: Boolean) {
constructionQueue.removeAt(constructionQueueIndex) constructionQueue.removeAt(constructionQueueIndex)
if (constructionQueue.isEmpty()){ if (constructionQueue.isEmpty()) {
if(automatic) chooseNextConstruction() if (automatic) chooseNextConstruction()
else constructionQueue.add("Nothing") // To prevent Construction Automation else constructionQueue.add("Nothing") // To prevent Construction Automation
currentConstructionIsUserSet = false currentConstructionIsUserSet = false
} } else currentConstructionIsUserSet = true // we're just continuing the regular queue
else currentConstructionIsUserSet = true // we're just continuing the regular queue
} }
fun raisePriority(constructionQueueIndex: Int) { fun raisePriority(constructionQueueIndex: Int) {
@ -414,7 +422,7 @@ class CityConstructions {
// Lowering == Highering next element in queue // Lowering == Highering next element in queue
fun lowerPriority(constructionQueueIndex: Int) { fun lowerPriority(constructionQueueIndex: Int) {
raisePriority(constructionQueueIndex+1) raisePriority(constructionQueueIndex + 1)
} }
//endregion //endregion
@ -423,4 +431,4 @@ class CityConstructions {
this[idx1] = this[idx2] this[idx1] = this[idx2]
this[idx2] = tmp this[idx2] = tmp
} }
} // for json parsing, we need to have a default constructor }

View File

@ -42,9 +42,9 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
} }
constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE)) constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE))
constructionsQueueScrollPane.setOverscroll(false,false) constructionsQueueScrollPane.setOverscroll(false, false)
availableConstructionsScrollPane = ScrollPane(availableConstructionsTable.addBorder(2f, Color.WHITE)) availableConstructionsScrollPane = ScrollPane(availableConstructionsTable.addBorder(2f, Color.WHITE))
availableConstructionsScrollPane.setOverscroll(false,false) availableConstructionsScrollPane.setOverscroll(false, false)
constructionsQueueTable.background = ImageGetter.getBackground(Color.BLACK) constructionsQueueTable.background = ImageGetter.getBackground(Color.BLACK)
availableConstructionsTable.background = ImageGetter.getBackground(Color.BLACK) availableConstructionsTable.background = ImageGetter.getBackground(Color.BLACK)
@ -98,7 +98,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
queue.forEachIndexed { i, constructionName -> queue.forEachIndexed { i, constructionName ->
if (i != 0) // This is already displayed as "Current construction" if (i != 0) // This is already displayed as "Current construction"
constructionsQueueTable.add(getQueueEntry(i, constructionName)) constructionsQueueTable.add(getQueueEntry(i, constructionName))
.expandX().fillX().row() .expandX().fillX().row()
if (i != queue.size - 1) if (i != queue.size - 1)
constructionsQueueTable.addSeparator() constructionsQueueTable.addSeparator()
} }
@ -112,7 +112,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
getCell(constructionsQueueScrollPane).maxHeight(stage.height / 3 - 10f) getCell(constructionsQueueScrollPane).maxHeight(stage.height / 3 - 10f)
} }
private fun getConstructionButtonDTOs():ArrayList<ConstructionButtonDTO> { private fun getConstructionButtonDTOs(): ArrayList<ConstructionButtonDTO> {
val constructionButtonDTOList = ArrayList<ConstructionButtonDTO>() val constructionButtonDTOList = ArrayList<ConstructionButtonDTO>()
val city = cityScreen.city val city = cityScreen.city
@ -156,7 +156,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private fun updateAvailableConstructions() { private fun updateAvailableConstructions() {
val constrScrollY = availableConstructionsScrollPane.scrollY val constrScrollY = availableConstructionsScrollPane.scrollY
if(!availableConstructionsTable.hasChildren()) { // if (!availableConstructionsTable.hasChildren()) { //
availableConstructionsTable.add("Loading...".toLabel()).pad(10f) availableConstructionsTable.add("Loading...".toLabel()).pad(10f)
} }
val units = ArrayList<Table>() val units = ArrayList<Table>()
@ -225,11 +225,11 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
val constructionResource = cityConstructions.getConstruction(name).getResource() val constructionResource = cityConstructions.getConstruction(name).getResource()
if(constructionResource != null) if (constructionResource != null)
text += "\n"+"Consumes 1 [$constructionResource]".tr() text += "\n" + "Consumes 1 [$constructionResource]".tr()
table.defaults().pad(2f).minWidth(40f) table.defaults().pad(2f).minWidth(40f)
if(isFirstConstructionOfItsKind) table.add(getProgressBar(name)).minWidth(5f) if (isFirstConstructionOfItsKind) table.add(getProgressBar(name)).minWidth(5f)
else table.add().minWidth(5f) else table.add().minWidth(5f)
table.add(ImageGetter.getConstructionImage(name).surroundWithCircle(40f)).padRight(10f) table.add(ImageGetter.getConstructionImage(name).surroundWithCircle(40f)).padRight(10f)
table.add(text.toLabel()).expandX().fillX().left() table.add(text.toLabel()).expandX().fillX().left()
@ -252,7 +252,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
return table return table
} }
fun getProgressBar(constructionName:String): Table { fun getProgressBar(constructionName: String): Table {
val cityConstructions = cityScreen.city.cityConstructions val cityConstructions = cityScreen.city.cityConstructions
val construction = cityConstructions.getConstruction(constructionName) val construction = cityConstructions.getConstruction(constructionName)
if (construction is PerpetualConstruction) return Table() if (construction is PerpetualConstruction) return Table()
@ -265,6 +265,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
} }
class ConstructionButtonDTO(val construction: IConstruction, val buttonText: String, val rejectionReason: String = "") class ConstructionButtonDTO(val construction: IConstruction, val buttonText: String, val rejectionReason: String = "")
private fun getConstructionButton(constructionButtonDTO: ConstructionButtonDTO): Table { private fun getConstructionButton(constructionButtonDTO: ConstructionButtonDTO): Table {
val construction = constructionButtonDTO.construction val construction = constructionButtonDTO.construction
val pickConstructionButton = Table() val pickConstructionButton = Table()
@ -306,7 +307,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private fun isSelectedQueueEntry(): Boolean = selectedQueueEntry >= 0 private fun isSelectedQueueEntry(): Boolean = selectedQueueEntry >= 0
fun cannotAddConstructionToQueue(construction:IConstruction, city:CityInfo, cityConstructions:CityConstructions): Boolean { fun cannotAddConstructionToQueue(construction: IConstruction, city: CityInfo, cityConstructions: CityConstructions): Boolean {
return cityConstructions.isQueueFull() return cityConstructions.isQueueFull()
|| !cityConstructions.getConstruction(construction.name).isBuildable(cityConstructions) || !cityConstructions.getConstruction(construction.name).isBuildable(cityConstructions)
|| !cityScreen.canChangeState || !cityScreen.canChangeState
@ -325,7 +326,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
button.disable() button.disable()
else { else {
button.onClick { button.onClick {
cityConstructions.removeFromQueue(selectedQueueEntry,false) cityConstructions.removeFromQueue(selectedQueueEntry, false)
cityScreen.selectedConstruction = null cityScreen.selectedConstruction = null
selectedQueueEntry = -1 selectedQueueEntry = -1
cityScreen.update() cityScreen.update()
@ -345,7 +346,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
return button return button
} }
fun addConstructionToQueue(construction:IConstruction, cityConstructions: CityConstructions) { fun addConstructionToQueue(construction: IConstruction, cityConstructions: CityConstructions) {
cityConstructions.addToQueue(construction.name) cityConstructions.addToQueue(construction.name)
if (!construction.shouldBeDisplayed(cityConstructions)) cityScreen.selectedConstruction = null if (!construction.shouldBeDisplayed(cityConstructions)) cityScreen.selectedConstruction = null
cityScreen.update() cityScreen.update()
@ -400,7 +401,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
|| !cityScreen.canChangeState || !cityScreen.canChangeState
|| city.isPuppet || city.isInResistance() || city.isPuppet || city.isInResistance()
|| !city.canPurchase(construction) || !city.canPurchase(construction)
|| (constructionGoldCost > city.civInfo.gold && !city.civInfo.gameInfo.gameParameters.godMode) ) || (constructionGoldCost > city.civInfo.gold && !city.civInfo.gameInfo.gameParameters.godMode))
button.disable() button.disable()
} }
@ -450,7 +451,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
tab.touchable = Touchable.enabled tab.touchable = Touchable.enabled
tab.onClick { tab.onClick {
tab.touchable = Touchable.disabled tab.touchable = Touchable.disabled
city.cityConstructions.removeFromQueue(constructionQueueIndex,false) city.cityConstructions.removeFromQueue(constructionQueueIndex, false)
cityScreen.selectedConstruction = null cityScreen.selectedConstruction = null
cityScreen.update() cityScreen.update()
} }