wip: turn generation
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand/v2"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type Battle struct {
|
||||
Planet uint
|
||||
Groups []int // ShipGroup indexes
|
||||
BattleReport BattleReport
|
||||
}
|
||||
|
||||
type BattleReport struct {
|
||||
BattleAction []BattleAction
|
||||
}
|
||||
|
||||
type BattleAction struct {
|
||||
Attacker int
|
||||
Defenter int
|
||||
Destroyed bool
|
||||
}
|
||||
|
||||
type BattleOpponent struct {
|
||||
RaceIndex int
|
||||
ShipGroupIndex int
|
||||
ShipType ShipType
|
||||
}
|
||||
|
||||
func ProduceBattles(g *Game) error {
|
||||
|
||||
battleOnPlanet := Battle{}
|
||||
_ = battleOnPlanet
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SingleBattle(g *Game, b Battle) {
|
||||
attacker := SelectAttackShip(g, b.Groups)
|
||||
for shots := range attacker.ShipType.Armament {
|
||||
// groupsCopy := slices.Clone(b.Groups)
|
||||
// groupsWithoutAttacker := append(groupsCopy[:attackerIdx], groupsCopy[attackerIdx+1:]...)
|
||||
_ = SelectDefendShip(g, slices.Clone(b.Groups), attacker)
|
||||
|
||||
_ = shots
|
||||
}
|
||||
}
|
||||
|
||||
func SelectAttackShip(g *Game, battleGroups []int) BattleOpponent {
|
||||
sgi := rand.IntN(len(battleGroups))
|
||||
if sgi > len(g.ShipGroups)-1 {
|
||||
panic("SelectAttackShip: battleGroups is bigger than game's ship groups")
|
||||
}
|
||||
sg := g.ShipGroups[sgi]
|
||||
ri := slices.IndexFunc(g.Race, func(r Race) bool { return r.ID == sg.OwnerID })
|
||||
if ri < 0 {
|
||||
panic(fmt.Sprintf("SelectAttackShip: ship group #%v owner race not found by ID=%v", sg.Index, sg.OwnerID))
|
||||
}
|
||||
st, ok := ShipClass(g, ri, sg.TypeID)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("SelectAttackShip: ship class not found for race=%q group=%v", g.Race[ri].Name, sg.Index))
|
||||
}
|
||||
if st.Weapons == 0 || st.Armament == 0 {
|
||||
panic(fmt.Sprintf("SelectAttackShip: ship_class=%q of race=%q has no weapons for attack", st.Name, g.Race[ri].Name))
|
||||
}
|
||||
return BattleOpponent{
|
||||
RaceIndex: ri,
|
||||
ShipGroupIndex: sgi,
|
||||
ShipType: st,
|
||||
}
|
||||
}
|
||||
|
||||
func SelectDefendShip(g *Game, battleGroups []int, attacker BattleOpponent) BattleOpponent {
|
||||
enemyGroups := FilterAttackingPretendent(g, attacker.RaceIndex, battleGroups)
|
||||
sgi := rand.IntN(len(enemyGroups))
|
||||
if sgi > len(g.ShipGroups)-1 {
|
||||
panic("SelectDefendShip: battleGroups is bigger than game's ship groups")
|
||||
}
|
||||
sg := g.ShipGroups[sgi]
|
||||
ri := slices.IndexFunc(g.Race, func(r Race) bool { return r.ID == sg.OwnerID })
|
||||
if ri < 0 {
|
||||
panic(fmt.Sprintf("SelectDefendShip: ship group #%v owner race not found by ID=%v", sg.Index, sg.OwnerID))
|
||||
}
|
||||
st, ok := ShipClass(g, ri, sg.TypeID)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("SelectDefendShip: ship class not found for race=%q group=%v", g.Race[ri].Name, sg.Index))
|
||||
}
|
||||
return BattleOpponent{
|
||||
RaceIndex: ri,
|
||||
ShipGroupIndex: sgi,
|
||||
ShipType: st,
|
||||
}
|
||||
}
|
||||
|
||||
// attackerIdx - attacker race index
|
||||
func FilterAttackingPretendent(g *Game, attackerIdx int, battleGroups []int) []int {
|
||||
result := make([]int, 0)
|
||||
for sgi := range battleGroups {
|
||||
sg := g.ShipGroups[sgi]
|
||||
enemyIdx := slices.IndexFunc(g.Race, func(r Race) bool { return r.ID == sg.OwnerID })
|
||||
if enemyIdx < 0 {
|
||||
panic(fmt.Sprintf("FilterAttackingPretendent: ship group #%v owner race not found by ID=%v", sg.Index, sg.OwnerID))
|
||||
}
|
||||
rel, err := g.relationInternal(attackerIdx, enemyIdx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// attacker race will be in peace with itself, so attacker ships will be filtered out as well
|
||||
if rel.Relation == RelationPeace {
|
||||
continue
|
||||
}
|
||||
result = append(result, sgi)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func DestroyProbability(attWeapons, attWeaponsTech, defShields, defShiledsTech, defFullMass float64) float64 {
|
||||
effAttack := attWeapons * attWeaponsTech
|
||||
effDefence := EffectiveDefence(defShields, defShiledsTech, defFullMass)
|
||||
return (math.Log10(effAttack/effDefence)/math.Log10(4) + 1) / 2
|
||||
}
|
||||
|
||||
func EffectiveDefence(defShields, defShiledsTech, defFullMass float64) float64 {
|
||||
return defShields * defShiledsTech / math.Pow(defFullMass, 1./3.) * math.Pow(30., 1./3.)
|
||||
}
|
||||
Reference in New Issue
Block a user