Resolved #1114 - submarines cannot attack from coast to lake and vice versa

This commit is contained in:
Yair Morgenstern 2019-09-24 17:26:19 +03:00
parent f6009c43ca
commit 40c76b7752
4 changed files with 100 additions and 92 deletions

View File

@ -12,6 +12,7 @@ class Constants{
const val hill = "Hill" const val hill = "Hill"
const val coast = "Coast" const val coast = "Coast"
const val plains = "Plains" const val plains = "Plains"
const val lakes = "Lakes"
const val barbarianEncampment = "Barbarian encampment" const val barbarianEncampment = "Barbarian encampment"
const val ancientRuins = "Ancient ruins" const val ancientRuins = "Ancient ruins"

View File

@ -162,12 +162,18 @@ class UnitAutomation{
} }
fun containsAttackableEnemy(tile: TileInfo, combatant: ICombatant): Boolean { fun containsAttackableEnemy(tile: TileInfo, combatant: ICombatant): Boolean {
if(combatant is MapUnitCombatant){ if(combatant is MapUnitCombatant) {
if (combatant.unit.isEmbarked()) { if (combatant.unit.isEmbarked()) {
if (tile.isWater) return false // can't attack water units while embarked, only land if (tile.isWater) return false // can't attack water units while embarked, only land
if (combatant.isRanged()) return false if (combatant.isRanged()) return false
} }
if (tile.isLand && combatant.unit.hasUnique("Can only attack water")) return false if (combatant.unit.hasUnique("Can only attack water")) {
if (tile.isLand) return false
// trying to attack lake-to-coast or vice versa
if ((tile.baseTerrain == Constants.lakes) != (combatant.getTile().baseTerrain == Constants.lakes))
return false
}
} }
val tileCombatant = Battle(combatant.getCivInfo().gameInfo).getMapCombatantOfTile(tile) val tileCombatant = Battle(combatant.getCivInfo().gameInfo).getMapCombatantOfTile(tile)

View File

@ -33,7 +33,7 @@ class Battle(val gameInfo:GameInfo) {
val attackedTile = defender.getTile() val attackedTile = defender.getTile()
if(attacker is MapUnitCombatant && attacker.getUnitType().isAirUnit()){ if(attacker is MapUnitCombatant && attacker.getUnitType().isAirUnit()){
intercept(attacker,defender) tryInterceptAirAttack(attacker,defender)
if(attacker.isDefeated()) return if(attacker.isDefeated()) return
} }
@ -65,9 +65,9 @@ class Battle(val gameInfo:GameInfo) {
postBattleAction(attacker,defender,attackedTile) postBattleAction(attacker,defender,attackedTile)
} }
private fun postBattleAction(attacker: ICombatant, defender: ICombatant, attackedTile:TileInfo){ private fun postBattleAction(attacker: ICombatant, defender: ICombatant, attackedTile:TileInfo) {
if(attacker.getCivInfo()!=defender.getCivInfo()) { // If what happened was that a civilian unit was captures, that's dealt with in the CaptureCilvilianUnit function if (attacker.getCivInfo() != defender.getCivInfo()) { // If what happened was that a civilian unit was captures, that's dealt with in the CaptureCilvilianUnit function
val whatHappenedString = val whatHappenedString =
if (attacker !is CityCombatant && attacker.isDefeated()) " {was destroyed while attacking}" if (attacker !is CityCombatant && attacker.isDefeated()) " {was destroyed while attacking}"
else " has " + (if (defender.isDefeated()) "destroyed" else "attacked") else " has " + (if (defender.isDefeated()) "destroyed" else "attacked")
@ -75,20 +75,20 @@ class Battle(val gameInfo:GameInfo) {
if (attacker.getUnitType() == UnitType.City) "Enemy city [" + attacker.getName() + "]" if (attacker.getUnitType() == UnitType.City) "Enemy city [" + attacker.getName() + "]"
else "An enemy [" + attacker.getName() + "]" else "An enemy [" + attacker.getName() + "]"
val defenderString = val defenderString =
if (defender.getUnitType() == UnitType.City) " [" + defender.getName()+"]" if (defender.getUnitType() == UnitType.City) " [" + defender.getName() + "]"
else " our [" + defender.getName()+"]" else " our [" + defender.getName() + "]"
val notificationString = attackerString + whatHappenedString + defenderString val notificationString = attackerString + whatHappenedString + defenderString
defender.getCivInfo().addNotification(notificationString, attackedTile.position, Color.RED) defender.getCivInfo().addNotification(notificationString, attackedTile.position, Color.RED)
} }
// Units that heal when killing // Units that heal when killing
if(defender.isDefeated() if (defender.isDefeated()
&& defender is MapUnitCombatant && defender is MapUnitCombatant
&& attacker is MapUnitCombatant){ && attacker is MapUnitCombatant) {
val regex = Regex("""Heals \[(\d*)\] damage if it kills a unit"""") val regex = Regex("""Heals \[(\d*)\] damage if it kills a unit"""")
for(unique in attacker.unit.getUniques()){ for (unique in attacker.unit.getUniques()) {
val match = regex.matchEntire(unique) val match = regex.matchEntire(unique)
if(match==null) continue if (match == null) continue
val amountToHeal = match.groups[1]!!.value.toInt() val amountToHeal = match.groups[1]!!.value.toInt()
attacker.unit.healBy(amountToHeal) attacker.unit.healBy(amountToHeal)
} }
@ -96,74 +96,84 @@ class Battle(val gameInfo:GameInfo) {
// German unique - needs to be checked before we try to move to the enemy tile, since the encampment disappears after we move in // German unique - needs to be checked before we try to move to the enemy tile, since the encampment disappears after we move in
if(defender.isDefeated() && defender.getCivInfo().isBarbarian() if (defender.isDefeated() && defender.getCivInfo().isBarbarian()
&& attackedTile.improvement==Constants.barbarianEncampment && attackedTile.improvement == Constants.barbarianEncampment
&& attacker.getCivInfo().nation.unique== "67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance." && attacker.getCivInfo().nation.unique == "67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance."
&& Random().nextDouble() > 0.67){ && Random().nextDouble() > 0.67) {
attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName()) attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName())
attacker.getCivInfo().gold += 25 attacker.getCivInfo().gold += 25
attacker.getCivInfo().addNotification("A barbarian [${defender.getName()}] has joined us!",attackedTile.position, Color.RED) attacker.getCivInfo().addNotification("A barbarian [${defender.getName()}] has joined us!", attackedTile.position, Color.RED)
} }
// Similarly, Ottoman unique // Similarly, Ottoman unique
if(defender.isDefeated() && defender.getUnitType().isWaterUnit() && attacker.isMelee() && attacker.getUnitType().isWaterUnit() if (defender.isDefeated() && defender.getUnitType().isWaterUnit() && attacker.isMelee() && attacker.getUnitType().isWaterUnit()
&& attacker.getCivInfo().nation.unique== "Pay only one third the usual cost for naval unit maintenance. Melee naval units have a 1/3 chance to capture defeated naval units." && attacker.getCivInfo().nation.unique == "Pay only one third the usual cost for naval unit maintenance. Melee naval units have a 1/3 chance to capture defeated naval units."
&& Random().nextDouble() > 0.33){ && Random().nextDouble() > 0.33) {
attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName()) attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName())
} }
// we're a melee unit and we destroyed\captured an enemy unit // we're a melee unit and we destroyed\captured an enemy unit
else if (attacker.isMelee() else if (attacker.isMelee()
&& (defender.isDefeated() || defender.getCivInfo()==attacker.getCivInfo()) && (defender.isDefeated() || defender.getCivInfo() == attacker.getCivInfo())
// This is so that if we attack e.g. a barbarian in enemy territory that we can't enter, we won't enter it // This is so that if we attack e.g. a barbarian in enemy territory that we can't enter, we won't enter it
&& (attacker as MapUnitCombatant).unit.movement.canMoveTo(attackedTile)) { && (attacker as MapUnitCombatant).unit.movement.canMoveTo(attackedTile)) {
// we destroyed an enemy military unit and there was a civilian unit in the same tile as well // we destroyed an enemy military unit and there was a civilian unit in the same tile as well
if(attackedTile.civilianUnit!=null && attackedTile.civilianUnit!!.civInfo != attacker.getCivInfo()) if (attackedTile.civilianUnit != null && attackedTile.civilianUnit!!.civInfo != attacker.getCivInfo())
captureCivilianUnit(attacker,MapUnitCombatant(attackedTile.civilianUnit!!)) captureCivilianUnit(attacker, MapUnitCombatant(attackedTile.civilianUnit!!))
attacker.unit.movement.moveToTile(attackedTile) attacker.unit.movement.moveToTile(attackedTile)
} }
if(attacker is MapUnitCombatant) { if (attacker is MapUnitCombatant) {
val unit = attacker.unit val unit = attacker.unit
if (unit.hasUnique("Can move after attacking") if (unit.hasUnique("Can move after attacking")
|| (unit.hasUnique("1 additional attack per turn") && unit.attacksThisTurn==0)){ || (unit.hasUnique("1 additional attack per turn") && unit.attacksThisTurn == 0)) {
// if it was a melee attack and we won, then the unit ALREADY got movement points deducted, // if it was a melee attack and we won, then the unit ALREADY got movement points deducted,
// for the movement to the enemy's tile! // for the movement to the enemy's tile!
// and if it's an air unit, it only has 1 movement anyway, so... // and if it's an air unit, it only has 1 movement anyway, so...
if(!attacker.getUnitType().isAirUnit() && !(attacker.getUnitType().isMelee() && defender.isDefeated())) if (!attacker.getUnitType().isAirUnit() && !(attacker.getUnitType().isMelee() && defender.isDefeated()))
unit.useMovementPoints(1f) unit.useMovementPoints(1f)
} } else unit.currentMovement = 0f
else unit.currentMovement = 0f unit.attacksThisTurn += 1
unit.attacksThisTurn+=1 if (unit.isFortified() || unit.action == Constants.unitActionSleep)
if(unit.isFortified() || unit.action == Constants.unitActionSleep) attacker.unit.action = null // but not, for instance, if it's Set Up - then it should definitely keep the action!
attacker.unit.action=null // but not, for instance, if it's Set Up - then it should definitely keep the action!
} else if (attacker is CityCombatant) { } else if (attacker is CityCombatant) {
attacker.city.attackedThisTurn = true attacker.city.attackedThisTurn = true
} }
if(defender.isDefeated() if (defender.isDefeated()
&& defender is CityCombatant && defender is CityCombatant
&& attacker.isMelee()) && attacker.isMelee())
conquerCity(defender.city, attacker) conquerCity(defender.city, attacker)
if(attacker.isMelee()){ if (attacker.isMelee()) {
if(!defender.getUnitType().isCivilian()) // unit was not captured but actually attacked if (!defender.getUnitType().isCivilian()) // unit was not captured but actually attacked
{ {
addXp(attacker,5,defender) addXp(attacker, 5, defender)
addXp(defender,4,attacker) addXp(defender, 4, attacker)
} }
} } else { // ranged attack
else{ // ranged attack addXp(attacker, 2, defender)
addXp(attacker,2,defender) addXp(defender, 2, attacker)
addXp(defender,2,attacker)
} }
// Add culture when defeating a barbarian when Honor policy is adopted (can be either attacker or defender!) // Add culture when defeating a barbarian when Honor policy is adopted (can be either attacker or defender!)
fun tryGetCultureFromHonor(civUnit:ICombatant, barbarianUnit:ICombatant){ tryGetCultureFromHonor(attacker, defender)
tryGetCultureFromHonor(defender, attacker)
if (defender.isDefeated() && defender is MapUnitCombatant && !defender.getUnitType().isCivilian()
&& attacker.getCivInfo().policies.isAdopted("Honor Complete"))
attacker.getCivInfo().gold += defender.unit.baseUnit.getProductionCost(attacker.getCivInfo()) / 10
if (attacker is MapUnitCombatant && attacker.unit.action != null
&& attacker.unit.action!!.startsWith("moveTo"))
attacker.unit.action = null
}
private fun tryGetCultureFromHonor(civUnit:ICombatant, barbarianUnit:ICombatant){
if(barbarianUnit.isDefeated() && barbarianUnit is MapUnitCombatant if(barbarianUnit.isDefeated() && barbarianUnit is MapUnitCombatant
&& barbarianUnit.getCivInfo().isBarbarian() && barbarianUnit.getCivInfo().isBarbarian()
&& civUnit.getCivInfo().policies.isAdopted("Honor")) && civUnit.getCivInfo().policies.isAdopted("Honor"))
@ -171,19 +181,8 @@ class Battle(val gameInfo:GameInfo) {
max(barbarianUnit.unit.baseUnit.strength,barbarianUnit.unit.baseUnit.rangedStrength) max(barbarianUnit.unit.baseUnit.strength,barbarianUnit.unit.baseUnit.rangedStrength)
} }
tryGetCultureFromHonor(attacker,defender)
tryGetCultureFromHonor(defender,attacker)
if(defender.isDefeated() && defender is MapUnitCombatant && !defender.getUnitType().isCivilian()
&& attacker.getCivInfo().policies.isAdopted("Honor Complete"))
attacker.getCivInfo().gold += defender.unit.baseUnit.getProductionCost(attacker.getCivInfo()) / 10
if(attacker is MapUnitCombatant && attacker.unit.action!=null && attacker.unit.action!!.startsWith("moveTo"))
attacker.unit.action=null
}
// XP! // XP!
fun addXp(thisCombatant:ICombatant, amount:Int, otherCombatant:ICombatant){ private fun addXp(thisCombatant:ICombatant, amount:Int, otherCombatant:ICombatant){
if(thisCombatant !is MapUnitCombatant) return if(thisCombatant !is MapUnitCombatant) return
if(thisCombatant.unit.promotions.totalXpProduced() >= 30 && otherCombatant.getCivInfo().isBarbarian()) if(thisCombatant.unit.promotions.totalXpProduced() >= 30 && otherCombatant.getCivInfo().isBarbarian())
return return
@ -211,7 +210,6 @@ class Battle(val gameInfo:GameInfo) {
for(airUnit in airUnits.toList()) airUnit.destroy() for(airUnit in airUnits.toList()) airUnit.destroy()
} }
if (attacker.getCivInfo().isPlayerCivilization()) if (attacker.getCivInfo().isPlayerCivilization())
attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.name)) attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.name))
else city.puppetCity(attacker.getCivInfo()) else city.puppetCity(attacker.getCivInfo())
@ -224,12 +222,13 @@ class Battle(val gameInfo:GameInfo) {
return null return null
} }
fun captureCivilianUnit(attacker: ICombatant, defender: ICombatant){ private fun captureCivilianUnit(attacker: ICombatant, defender: ICombatant){
// barbarians don't capture civilians, City-states don't capture settlers
if(attacker.getCivInfo().isBarbarian() if(attacker.getCivInfo().isBarbarian()
|| (attacker.getCivInfo().isCityState() && defender.getName()==Constants.settler)){ || (attacker.getCivInfo().isCityState() && defender.getName()==Constants.settler)){
defender.takeDamage(100) defender.takeDamage(100)
return return
} // barbarians don't capture civilians! }
if (defender.getCivInfo().isDefeated()) {//Last settler captured if (defender.getCivInfo().isDefeated()) {//Last settler captured
defender.getCivInfo().destroy() defender.getCivInfo().destroy()
@ -245,14 +244,14 @@ class Battle(val gameInfo:GameInfo) {
capturedUnit.updateViewableTiles() capturedUnit.updateViewableTiles()
} }
fun intercept(attacker:MapUnitCombatant, defender: ICombatant){ private fun tryInterceptAirAttack(attacker:MapUnitCombatant, defender: ICombatant) {
val attackedTile = defender.getTile() val attackedTile = defender.getTile()
for(interceptor in defender.getCivInfo().getCivUnits().filter { it.canIntercept(attackedTile) }){ for (interceptor in defender.getCivInfo().getCivUnits().filter { it.canIntercept(attackedTile) }) {
if(Random().nextFloat() > 100f/interceptor.interceptChance()) continue if (Random().nextFloat() > 100f / interceptor.interceptChance()) continue
var damage = BattleDamage().calculateDamageToDefender(MapUnitCombatant(interceptor),attacker) var damage = BattleDamage().calculateDamageToDefender(MapUnitCombatant(interceptor), attacker)
damage += damage*interceptor.interceptDamagePercentBonus()/100 damage += damage * interceptor.interceptDamagePercentBonus() / 100
if(attacker.unit.hasUnique("Reduces damage taken from interception by 50%")) damage/=2 if (attacker.unit.hasUnique("Reduces damage taken from interception by 50%")) damage /= 2
attacker.takeDamage(damage) attacker.takeDamage(damage)
interceptor.attacksThisTurn++ interceptor.attacksThisTurn++
@ -260,16 +259,19 @@ class Battle(val gameInfo:GameInfo) {
val attackerName = attacker.getName() val attackerName = attacker.getName()
val interceptorName = interceptor.name val interceptorName = interceptor.name
if(attacker.isDefeated()){ if (attacker.isDefeated()) {
attacker.getCivInfo().addNotification("Our [$attackerName] was destroyed by an intercepting [$interceptorName]", attacker.getCivInfo()
.addNotification("Our [$attackerName] was destroyed by an intercepting [$interceptorName]",
Color.RED) Color.RED)
defender.getCivInfo().addNotification("Our [$interceptorName] intercepted and destroyed an enemy [$attackerName]", defender.getCivInfo()
.addNotification("Our [$interceptorName] intercepted and destroyed an enemy [$attackerName]",
interceptor.currentTile.position, Color.RED) interceptor.currentTile.position, Color.RED)
} } else {
else{ attacker.getCivInfo()
attacker.getCivInfo().addNotification("Our [$attackerName] was attacked by an intercepting [$interceptorName]", .addNotification("Our [$attackerName] was attacked by an intercepting [$interceptorName]",
Color.RED) Color.RED)
defender.getCivInfo().addNotification("Our [$interceptorName] intercepted and attacked an enemy [$attackerName]", defender.getCivInfo()
.addNotification("Our [$interceptorName] intercepted and attacked an enemy [$attackerName]",
interceptor.currentTile.position, Color.RED) interceptor.currentTile.position, Color.RED)
} }
return return

View File

@ -2,8 +2,6 @@ package com.unciv.logic.map
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.unciv.Constants import com.unciv.Constants
import com.unciv.Constants.Companion.mountain
import com.unciv.Constants.Companion.ocean
import com.unciv.logic.HexMath import com.unciv.logic.HexMath
import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.tile.ResourceType import com.unciv.models.gamebasics.tile.ResourceType
@ -123,7 +121,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
val tile=TileInfo() val tile=TileInfo()
tile.position=vector tile.position=vector
if (type == TerrainType.Land) tile.baseTerrain = "" if (type == TerrainType.Land) tile.baseTerrain = ""
else tile.baseTerrain = ocean else tile.baseTerrain = Constants.ocean
return tile return tile
} }
@ -152,7 +150,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
if (tilesInArea.size <= 10) { if (tilesInArea.size <= 10) {
for (vector in tilesInArea) { for (vector in tilesInArea) {
val tile = map[vector.toString()]!! val tile = map[vector.toString()]!!
tile.baseTerrain = "Lakes" tile.baseTerrain = Constants.lakes
tile.setTransients() tile.setTransients()
} }
} }
@ -160,7 +158,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
} }
//Coasts //Coasts
for (tile in map.values.filter { it.baseTerrain == ocean }) { for (tile in map.values.filter { it.baseTerrain == Constants.ocean }) {
if (HexMath().getVectorsInDistance(tile.position,2).any { hasLandTile(map,it) }) { if (HexMath().getVectorsInDistance(tile.position,2).any { hasLandTile(map,it) }) {
tile.baseTerrain = Constants.coast tile.baseTerrain = Constants.coast
tile.setTransients() tile.setTransients()
@ -170,7 +168,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
override fun randomizeTile(tileInfo: TileInfo, map: HashMap<String, TileInfo>){ override fun randomizeTile(tileInfo: TileInfo, map: HashMap<String, TileInfo>){
if(tileInfo.getBaseTerrain().type==TerrainType.Land && Math.random()<0.05f){ if(tileInfo.getBaseTerrain().type==TerrainType.Land && Math.random()<0.05f){
tileInfo.baseTerrain = mountain tileInfo.baseTerrain = Constants.mountain
tileInfo.setTransients() tileInfo.setTransients()
} }
addRandomTerrainFeature(tileInfo) addRandomTerrainFeature(tileInfo)
@ -185,8 +183,8 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
fun divideIntoAreas2(averageTilesPerArea: Int, waterPercent: Float, distance: Int, map: HashMap<Vector2, TileInfo>) { fun divideIntoAreas2(averageTilesPerArea: Int, waterPercent: Float, distance: Int, map: HashMap<Vector2, TileInfo>) {
val areas = ArrayList<Area>() val areas = ArrayList<Area>()
val terrains = GameBasics.Terrains.values.filter { it.type === TerrainType.Land && it.name != "Lakes" val terrains = GameBasics.Terrains.values.filter { it.type === TerrainType.Land && it.name != Constants.lakes
&& it.name != mountain} && it.name != Constants.mountain}
while(map.values.any { it.baseTerrain=="" }) // the world could be split into lots off tiny islands, and every island deserves land types while(map.values.any { it.baseTerrain=="" }) // the world could be split into lots off tiny islands, and every island deserves land types
{ {
@ -196,7 +194,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
for (i in 0 until numberOfSeeds) { for (i in 0 until numberOfSeeds) {
var terrain = if (Math.random() > waterPercent) terrains.random().name var terrain = if (Math.random() > waterPercent) terrains.random().name
else ocean else Constants.ocean
val tile = emptyTiles.random() val tile = emptyTiles.random()
//change grassland to desert or tundra based on y //change grassland to desert or tundra based on y
@ -204,7 +202,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
if (terrain == "Grassland" || terrain == "Tundra") if (terrain == "Grassland" || terrain == "Tundra")
terrain = "Desert" terrain = "Desert"
} else if (abs(getLatitude(tile.position)) > maxLatitude * 0.7) { } else if (abs(getLatitude(tile.position)) > maxLatitude * 0.7) {
if (terrain == "Grassland" || terrain == Constants.plains || terrain == "Desert" || terrain == ocean) { if (terrain == "Grassland" || terrain == Constants.plains || terrain == "Desert" || terrain == Constants.ocean) {
terrain = "Tundra" terrain = "Tundra"
} }
} else { } else {
@ -263,9 +261,9 @@ class PerlinNoiseRandomMapGenerator:SeedRandomMapGenerator(){
+ Perlin.noise(vector.x*ratio*2,vector.y*ratio*2,mapRandomSeed)/2 + Perlin.noise(vector.x*ratio*2,vector.y*ratio*2,mapRandomSeed)/2
+ Perlin.noise(vector.x*ratio*4,vector.y*ratio*4,mapRandomSeed)/4 + Perlin.noise(vector.x*ratio*4,vector.y*ratio*4,mapRandomSeed)/4
when { when {
height>0.8 -> tile.baseTerrain = mountain height>0.8 -> tile.baseTerrain = Constants.mountain
height>0 -> tile.baseTerrain = "" // we'll leave this to the area division height>0 -> tile.baseTerrain = "" // we'll leave this to the area division
else -> tile.baseTerrain = ocean else -> tile.baseTerrain = Constants.ocean
} }
return tile return tile
} }
@ -297,12 +295,12 @@ class AlexanderRandomMapGenerator:RandomMapGenerator(){
if(map[currentSpark]!!.baseTerrain==grassland){ if(map[currentSpark]!!.baseTerrain==grassland){
for(tile in emptyTilesAroundSpark){ for(tile in emptyTilesAroundSpark){
if(Math.random()<landExpansionChance) map[tile]=TileInfo().apply { baseTerrain=grassland } if(Math.random()<landExpansionChance) map[tile]=TileInfo().apply { baseTerrain=grassland }
else map[tile]=TileInfo().apply { baseTerrain=ocean } else map[tile]=TileInfo().apply { baseTerrain=Constants.ocean }
} }
} }
else{ else{
for(tile in emptyTilesAroundSpark) for(tile in emptyTilesAroundSpark)
map[tile]=TileInfo().apply { baseTerrain=ocean } map[tile]=TileInfo().apply { baseTerrain=Constants.ocean }
} }
sparkList.remove(currentSpark) sparkList.remove(currentSpark)
sparkList.addAll(emptyTilesAroundSpark) sparkList.addAll(emptyTilesAroundSpark)
@ -311,7 +309,7 @@ class AlexanderRandomMapGenerator:RandomMapGenerator(){
val newmap = HashMap<String,TileInfo>() val newmap = HashMap<String,TileInfo>()
for(entry in map){ for(entry in map){
entry.value!!.position = entry.key entry.value!!.position = entry.key
if(entry.value!!.baseTerrain==ocean if(entry.value!!.baseTerrain==Constants.ocean
&& HexMath().getAdjacentVectors(entry.key).all { !map.containsKey(it) || map[it]!!.baseTerrain==grassland }) && HexMath().getAdjacentVectors(entry.key).all { !map.containsKey(it) || map[it]!!.baseTerrain==grassland })
entry.value!!.baseTerrain=grassland entry.value!!.baseTerrain=grassland
@ -364,7 +362,8 @@ open class SeedRandomMapGenerator : RandomMapGenerator() {
open fun divideIntoAreas(averageTilesPerArea: Int, waterPercent: Float, map: HashMap<Vector2, TileInfo>) { open fun divideIntoAreas(averageTilesPerArea: Int, waterPercent: Float, map: HashMap<Vector2, TileInfo>) {
val areas = ArrayList<Area>() val areas = ArrayList<Area>()
val terrains = GameBasics.Terrains.values.filter { it.type === TerrainType.Land && it.name != "Lakes" && it.name != mountain } val terrains = GameBasics.Terrains.values
.filter { it.type === TerrainType.Land && it.name != Constants.lakes && it.name != Constants.mountain }
while(map.values.any { it.baseTerrain=="" }) // the world could be split into lots off tiny islands, and every island deserves land types while(map.values.any { it.baseTerrain=="" }) // the world could be split into lots off tiny islands, and every island deserves land types
{ {
@ -373,7 +372,7 @@ open class SeedRandomMapGenerator : RandomMapGenerator() {
for (i in 0 until numberOfSeeds) { for (i in 0 until numberOfSeeds) {
val terrain = if (Math.random() > waterPercent) terrains.random().name val terrain = if (Math.random() > waterPercent) terrains.random().name
else ocean else Constants.ocean
val area = Area(terrain) val area = Area(terrain)
val tile = emptyTiles.random() val tile = emptyTiles.random()
emptyTiles -= tile emptyTiles -= tile
@ -386,10 +385,10 @@ open class SeedRandomMapGenerator : RandomMapGenerator() {
} }
for (area in areas.filter { it.terrain == ocean && it.locations.size <= 10 }) { for (area in areas.filter { it.terrain == Constants.ocean && it.locations.size <= 10 }) {
// areas with 10 or less tiles are lakes. // areas with 10 or less tiles are lakes.
for (location in area.locations) for (location in area.locations)
map[location]!!.baseTerrain = "Lakes" map[location]!!.baseTerrain = Constants.lakes
} }
} }
@ -439,7 +438,7 @@ open class RandomMapGenerator {
tileInfo.position = position tileInfo.position = position
val terrains = GameBasics.Terrains.values val terrains = GameBasics.Terrains.values
val baseTerrain = terrains.filter { it.type === TerrainType.Land && it.name != "Lakes" }.random() val baseTerrain = terrains.filter { it.type === TerrainType.Land }.random()
tileInfo.baseTerrain = baseTerrain.name tileInfo.baseTerrain = baseTerrain.name
addRandomTerrainFeature(tileInfo) addRandomTerrainFeature(tileInfo)
@ -498,7 +497,7 @@ open class RandomMapGenerator {
} }
open fun setWaterTiles(map: HashMap<String, TileInfo>) { open fun setWaterTiles(map: HashMap<String, TileInfo>) {
for (tile in map.values.filter { it.baseTerrain == ocean }) { for (tile in map.values.filter { it.baseTerrain == Constants.ocean }) {
if (HexMath().getVectorsInDistance(tile.position,2).any { hasLandTile(map,it) }) { if (HexMath().getVectorsInDistance(tile.position,2).any { hasLandTile(map,it) }) {
tile.baseTerrain = Constants.coast tile.baseTerrain = Constants.coast
tile.setTransients() tile.setTransients()
@ -508,12 +507,12 @@ open class RandomMapGenerator {
open fun randomizeTile(tileInfo: TileInfo, map: HashMap<String, TileInfo>){ open fun randomizeTile(tileInfo: TileInfo, map: HashMap<String, TileInfo>){
if(tileInfo.getBaseTerrain().type==TerrainType.Land && Math.random()<0.05f){ if(tileInfo.getBaseTerrain().type==TerrainType.Land && Math.random()<0.05f){
tileInfo.baseTerrain = mountain tileInfo.baseTerrain = Constants.mountain
tileInfo.setTransients() tileInfo.setTransients()
} }
if(tileInfo.getBaseTerrain().type==TerrainType.Land && Math.random()<0.05f if(tileInfo.getBaseTerrain().type==TerrainType.Land && Math.random()<0.05f
&& HexMath().getVectorsInDistance(tileInfo.position,1).all { hasLandTile(map,it) }){ && HexMath().getVectorsInDistance(tileInfo.position,1).all { hasLandTile(map,it) }){
tileInfo.baseTerrain = "Lakes" tileInfo.baseTerrain = Constants.lakes
tileInfo.setTransients() tileInfo.setTransients()
} }
addRandomTerrainFeature(tileInfo) addRandomTerrainFeature(tileInfo)