Skip to content

Commit

Permalink
cast: add pestilence (#301)
Browse files Browse the repository at this point in the history
* cast: add pestilence

* move pestilence population influence to city

* Move gaias blessing influence to city
  • Loading branch information
msom authored Feb 8, 2025
1 parent 712eda2 commit 44a225f
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 50 deletions.
46 changes: 45 additions & 1 deletion game/magic/city/city.go
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,10 @@ func (city *City) ComputeUnrest(garrison []units.StackUnit) int {
unrestAbsolute += 1
}

if city.HasEnchantment(data.CityEnchantmentPestilence) {
unrestAbsolute += 2
}

// capital race vs town race modifier
// unrest from spells
// supression from units
Expand Down Expand Up @@ -1411,7 +1415,7 @@ func (city *City) GetWeaponBonus() data.WeaponBonus {

// do all the stuff needed per turn
// increase population, add production, add food/money, etc
func (city *City) DoNextTurn(garrison []units.StackUnit) []CityEvent {
func (city *City) DoNextTurn(garrison []units.StackUnit, mapObject *maplib.Map) []CityEvent {
var cityEvents []CityEvent
if city.Outpost {
event := city.GrowOutpost()
Expand All @@ -1424,6 +1428,13 @@ func (city *City) DoNextTurn(garrison []units.StackUnit) []CityEvent {

oldPopulation := city.Population
city.Population += city.PopulationGrowthRate()

if city.HasEnchantment(data.CityEnchantmentPestilence) {
if city.Citizens() >= 11 || city.Citizens() > (rand.IntN(10) + 1) {
city.Population -= 1000
}
}

if city.Population > city.MaximumCitySize() * 1000 {
city.Population = city.MaximumCitySize() * 1000
}
Expand Down Expand Up @@ -1456,6 +1467,39 @@ func (city *City) DoNextTurn(garrison []units.StackUnit) []CityEvent {
}
}

if city.HasEnchantment(data.CityEnchantmentGaiasBlessing) {

for dx := -2; dx <= 2; dx++ {
for dy := -2; dy <= 2; dy++ {
mx := mapObject.WrapX(city.X + dx)
my := city.Y + dy

if mx < 0 || mx >= mapObject.Width() || my < 0 || my >= mapObject.Height() {
continue
}

tile := mapObject.GetTile(mx, my)
terrainType := tile.Tile.TerrainType()

// 10% chance to convert volcanos to hills
if mapObject.HasVolcano(mx, my) && rand.IntN(100) < 10 {
mapObject.RemoveVolcano(mx, my)
mapObject.Map.SetTerrainAt(mx, my, terrain.Hill, mapObject.Data, mapObject.Plane)
}

// 10% chance to convert desert to grassland
if terrainType == terrain.Desert && rand.IntN(100) < 10 {
mapObject.Map.SetTerrainAt(mx, mx, terrain.Grass, mapObject.Data, mapObject.Plane)
}

// 20% chance to remove corruption
if mapObject.HasCorruption(mx, my) && rand.IntN(100) < 20 {
mapObject.RemoveCorruption(mx, my)
}
}
}
}

// update minimum farmers
city.ResetCitizens(garrison)

Expand Down
28 changes: 28 additions & 0 deletions game/magic/city/city_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,34 @@ func TestEnchantments(test *testing.T){
// 5 * (5 - 10) food surplus
test.Errorf("City PopulationGrowthRate is not correct: %v", city.PopulationGrowthRate())
}

// Pestilence
city.AddEnchantment(data.CityEnchantmentPestilence, banner)

if city.FoodProductionRate() != 5 {
// ((5 * 2 farmer + 0.2 * 10) with halved excess) / 2 = 5.25
test.Errorf("City FoodProductionRate is not correct: %v", city.FoodProductionRate())
}

if int(city.WorkProductionRate()) != int(math.Floor(15.75)) {
// (2 x (3 x 2 worker + 5 x 0.5 farmer) + 13.5 terrain) / 2 = 12.375
test.Errorf("City WorkProductionRate is not correct: %v", city.WorkProductionRate())
}

if city.GoldSurplus() != 23 {
// 2 x 8 taxation + 15.75/2 trade goods
test.Errorf("City GoldSurplus is not correct: %v", city.GoldSurplus())
}

if city.ComputeUnrest(stack) != 5 {
// (0.2 race + 0.25 famine) * 10 + 1 cursed lands - 2 gaias blessing + 2 pestilence
test.Errorf("City ComputeUnrest is not correct: %v", city.ComputeUnrest(stack))
}

if city.PopulationGrowthRate() != -250 {
// 5 * (5 - 10) food surplus
test.Errorf("City PopulationGrowthRate is not correct: %v", city.PopulationGrowthRate())
}
}


Expand Down
5 changes: 1 addition & 4 deletions game/magic/data/enchantment.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,6 @@ func (enchantment CityEnchantment) LbxIndex() int {
case CityEnchantmentEvilPresence: return 82
case CityEnchantmentInspirations: return 100
case CityEnchantmentNaturesEye: return 99
// case CityEnchantmentPestilence: FIXME: How is this displayed?
case CityEnchantmentProsperity: return 101
case CityEnchantmentLifeWard: return 96
case CityEnchantmentSorceryWard: return 97
Expand All @@ -391,15 +390,14 @@ func (enchantment CityEnchantment) SoundIndex() int {
// case CityEnchantmentAstralGate: return 0
// case CityEnchantmentChaosRift: return 0
case CityEnchantmentCloudOfShadow, CityEnchantmentEvilPresence, CityEnchantmentFamine,
CityEnchantmentWallOfDarkness:
CityEnchantmentPestilence, CityEnchantmentWallOfDarkness:
return 32
// case CityEnchantmentConsecration: return 0
case CityEnchantmentCursedLands: return 61
case CityEnchantmentDarkRituals: return 60
// case CityEnchantmentEarthGate: return 0
// case CityEnchantmentFlyingFortress: return 0
case CityEnchantmentGaiasBlessing, CityEnchantmentNaturesEye: return 28
// case CityEnchantmentPestilence: return 0
// case CityEnchantmentLifeWard: return 0
// case CityEnchantmentSorceryWard: return 0
// case CityEnchantmentNatureWard: return 0
Expand All @@ -418,7 +416,6 @@ func (enchantment CityEnchantment) IconOffset() int {
// case CityEnchantmentConsecration: return 0
case CityEnchantmentInspirations: return 134
case CityEnchantmentNaturesEye: return 114
// case CityEnchantmentPestilence: return 0
case CityEnchantmentProsperity: return 153
// case CityEnchantmentLifeWard: return 0
// case CityEnchantmentSorceryWard: return 0
Expand Down
6 changes: 6 additions & 0 deletions game/magic/game/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ func (game *Game) doCastSpell(player *playerlib.Player, spell spellbook.Spell) {
game.doCastCityEnchantment(yield, tileX, tileY, player, data.CityEnchantmentFamine)
}

game.Events <- &GameEventSelectLocationForSpell{Spell: spell, Player: player, LocationType: LocationTypeEnemyCity, SelectedFunc: selected}
case "Pestilence":
selected := func (yield coroutine.YieldFunc, tileX int, tileY int){
game.doCastCityEnchantment(yield, tileX, tileY, player, data.CityEnchantmentPestilence)
}

game.Events <- &GameEventSelectLocationForSpell{Spell: spell, Player: player, LocationType: LocationTypeEnemyCity, SelectedFunc: selected}
case "Change Terrain":
game.Events <- &GameEventSelectLocationForSpell{Spell: spell, Player: player, LocationType: LocationTypeChangeTerrain, SelectedFunc: game.doCastChangeTerrain}
Expand Down
44 changes: 1 addition & 43 deletions game/magic/game/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -5965,46 +5965,6 @@ func (game *Game) DissipateEnchantments(player *playerlib.Player, power int) {
// FIXME: dissipate unit enchantments
}

// apply automatic terraforming and purification to all cities of a player with gaias blessing
func (game *Game) doGaiasBlessing(player *playerlib.Player) {
for _, city := range player.Cities {
if city.HasEnchantment(data.CityEnchantmentGaiasBlessing) {

mapObject := game.GetMap(city.Plane)

for dx := -2; dx <= 2; dx++ {
for dy := -2; dy <= 2; dy++ {
mx := player.WrapX(city.X + dx)
my := city.Y + dy

if mx < 0 || mx >= mapObject.Width() || my < 0 || my >= mapObject.Height() {
continue
}

tile := mapObject.GetTile(mx, my)
terrainType := tile.Tile.TerrainType()

// 10% chance to convert volcanos to hills
if mapObject.HasVolcano(mx, my) && rand.IntN(100) < 10 {
mapObject.RemoveVolcano(mx, my)
mapObject.Map.SetTerrainAt(mx, my, terrain.Hill, mapObject.Data, mapObject.Plane)
}

// 10% chance to convert desert to grassland
if terrainType == terrain.Desert && rand.IntN(100) < 10 {
mapObject.Map.SetTerrainAt(mx, mx, terrain.Grass, mapObject.Data, mapObject.Plane)
}

// 20% chance to remove corruption
if mapObject.HasCorruption(mx, my) && rand.IntN(100) < 20 {
mapObject.RemoveCorruption(mx, my)
}
}
}
}
}
}

func (game *Game) StartPlayerTurn(player *playerlib.Player) {
disbandedMessages := game.DisbandUnits(player)

Expand Down Expand Up @@ -6101,7 +6061,7 @@ func (game *Game) StartPlayerTurn(player *playerlib.Player) {
var removeCities []*citylib.City

for _, city := range player.Cities {
cityEvents := city.DoNextTurn(player.GetUnits(city.X, city.Y, city.Plane))
cityEvents := city.DoNextTurn(player.GetUnits(city.X, city.Y, city.Plane), game.GetMap(city.Plane))
for _, event := range cityEvents {
switch event.(type) {
case *citylib.CityEventPopulationGrowth:
Expand Down Expand Up @@ -6214,8 +6174,6 @@ func (game *Game) StartPlayerTurn(player *playerlib.Player) {
player.RemoveCity(city)
}

game.doGaiasBlessing(player)

game.maybeHireHero(player)
game.maybeHireMercenaries(player)
game.maybeBuyFromMerchant(player)
Expand Down
1 change: 1 addition & 0 deletions test/cityview/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ func (engine *Engine) Update() error {
case ebiten.Key5: engine.toggleEnchantment(data.CityEnchantmentChaosRift)
case ebiten.Key6: engine.toggleEnchantment(data.CityEnchantmentHeavenlyLight)
case ebiten.Key7: engine.toggleEnchantment(data.CityEnchantmentCloudOfShadow)
case ebiten.Key8: engine.toggleEnchantment(data.CityEnchantmentPestilence)
}
}

Expand Down
5 changes: 3 additions & 2 deletions test/overworld/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@ func createScenario13(cache *lbx.LbxCache) *gamelib.Game {
player.KnownSpells.AddSpell(allSpells.FindByName("Gaia's Blessing"))
player.KnownSpells.AddSpell(allSpells.FindByName("Cursed Lands"))
player.KnownSpells.AddSpell(allSpells.FindByName("Famine"))
player.KnownSpells.AddSpell(allSpells.FindByName("Pestilence"))
player.KnownSpells.AddSpell(allSpells.FindByName("Nature Awareness"))
player.KnownSpells.AddSpell(allSpells.FindByName("Change Terrain"))
player.KnownSpells.AddSpell(allSpells.FindByName("Transmute"))
Expand Down Expand Up @@ -1052,8 +1053,8 @@ func createScenario13(cache *lbx.LbxCache) *gamelib.Game {
city2.Plane = data.PlaneArcanus
city2.ProducingBuilding = buildinglib.BuildingHousing
city2.ProducingUnit = units.UnitNone
city2.Farmers = 5
city2.Workers = 5
city2.Farmers = 10
city2.Workers = 4
city2.Wall = false
city2.ResetCitizens(nil)
enemy.AddCity(city2)
Expand Down

0 comments on commit 44a225f

Please sign in to comment.