fix: battles are not round-based

This commit is contained in:
IliaDenisov
2026-02-19 15:07:51 +02:00
parent 8378df29c2
commit 0c0df976bd
2 changed files with 60 additions and 43 deletions
+33 -16
View File
@@ -1,6 +1,7 @@
package controller
import (
"iter"
"maps"
"math"
"math/rand/v2"
@@ -84,15 +85,6 @@ func FilterBattleOpponents(c *Cache, attIdx, defIdx int, cacheProbability map[in
}
/*
FIXME: Сражение происходит раундами
Случайным образом из всех участвующих в сражении вооруженных кораблей выбирается один...
...Затем вновь случайным образом выбирается корабль, который будет стрелять...
Так продолжается до тех пор, пока не отстреляются все корабли. Если после
этого еще остались корабли и с той и с другой стороны, все повторяется с
самого начала (происходит еще один цикл сражения).
*/
func ProduceBattles(c *Cache) []*Battle {
cacheProbability := make(map[int]map[int]float64)
defer func() { clear(cacheProbability) }()
@@ -159,13 +151,23 @@ func ProduceBattles(c *Cache) []*Battle {
}
func SingleBattle(c *Cache, b *Battle) {
roundShooters := make(map[int]bool)
for len(b.attacker) > 0 {
attackers := slices.Collect(maps.Keys(b.attacker))
attIdx := attackers[rand.IntN(len(attackers))]
// список участников раунда
clear(roundShooters)
for sgi := range b.attacker {
roundShooters[sgi] = true
}
for len(roundShooters) > 0 {
// attacke group id among round participants
attIdx := randomValue(maps.Keys(roundShooters))
delete(roundShooters, attIdx)
for range b.shipAmmo[attIdx] {
defenders := slices.Collect(maps.Keys(b.attacker[attIdx]))
defIdx := defenders[rand.IntN(len(defenders))]
// defender group id among all attacker's opponents
defIdx := randomValue(maps.Keys(b.attacker[attIdx]))
destroyed := false
probability := b.attacker[attIdx][defIdx]
@@ -188,20 +190,30 @@ func SingleBattle(c *Cache, b *Battle) {
c.ShipGroupDestroyItem(defIdx)
}
if c.ShipGroup(defIdx).Number == 0 {
delete(b.attacker, defIdx) // Eliminated group cant attack anyone
// Eliminated group cant attack anyone
delete(b.attacker, defIdx)
delete(roundShooters, defIdx)
for attIdx := range b.attacker {
delete(b.attacker[attIdx], defIdx) // Other attackers can't attack eliminated group anymore
// Other attackers can't attack eliminated group anymore
delete(b.attacker[attIdx], defIdx)
if len(b.attacker[attIdx]) == 0 {
delete(b.attacker, attIdx) // Remove attacker if he lost all opponents
// Remove attacker if he lost all opponents
delete(b.attacker, attIdx)
delete(roundShooters, attIdx)
}
}
}
// When attacker has no more targets to shoot - break its ammo cycle
if len(b.attacker[attIdx]) == 0 {
break
}
}
}
}
}
func DestructionProbability(attWeapons, attWeaponsTech, defShields, defShiledsTech, defFullMass float64) float64 {
effAttack := attWeapons * attWeaponsTech
@@ -212,3 +224,8 @@ func DestructionProbability(attWeapons, attWeaponsTech, defShields, defShiledsTe
func EffectiveDefence(defShields, defShiledsTech, defFullMass float64) float64 {
return defShields * defShiledsTech / math.Pow(defFullMass, 1./3.) * math.Pow(30., 1./3.)
}
func randomValue(v iter.Seq[int]) int {
ids := slices.Collect(v)
return ids[rand.IntN(len(ids))]
}
+2 -2
View File
@@ -14,11 +14,11 @@ func (c *Controller) MakeTurn() error {
c.Cache.g.Turn += 1
c.Cache.g.Stage = 0
// TODO: Выполнение приказов
// 01. Вышедшие расы удаляются из списка участвующих рас перед началом просчета очередного хода
c.Cache.TurnWipeExtinctRaces()
// TODO: передача кораблей между расами
// 02. Товары загружаются на корабли, находящиеся в начале грузовых маршрутов, и корабли входят в гиперпространство (но ещё не полетели)
c.Cache.SendRoutedGroups()