feat: support controller's cache
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"math"
|
||||
"math/rand/v2"
|
||||
"slices"
|
||||
|
||||
@@ -143,13 +142,14 @@ func FilterBattleOpponents(
|
||||
return true
|
||||
}
|
||||
|
||||
p := DestructionProbability(
|
||||
cacheShipClass[attIdx].Weapons,
|
||||
g.ShipGroups[attIdx].TechLevel(TechWeapons),
|
||||
cacheShipClass[defIdx].Shields,
|
||||
g.ShipGroups[defIdx].TechLevel(TechShields),
|
||||
g.ShipGroups[defIdx].FullMass(cacheShipClass[defIdx]),
|
||||
)
|
||||
// p := DestructionProbability(
|
||||
// cacheShipClass[attIdx].Weapons,
|
||||
// g.ShipGroups[attIdx].TechLevel(TechWeapons),
|
||||
// cacheShipClass[defIdx].Shields,
|
||||
// g.ShipGroups[defIdx].TechLevel(TechShields),
|
||||
// g.ShipGroups[defIdx].FullMass(cacheShipClass[defIdx]),
|
||||
// )
|
||||
p := 0.
|
||||
// Exclude opponent's group which cannot be probably destroyed
|
||||
if p <= 0 {
|
||||
return true
|
||||
@@ -288,15 +288,15 @@ func RaceIndex(g *Game, ID uuid.UUID) int {
|
||||
return i
|
||||
}
|
||||
|
||||
func DestructionProbability(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 DestructionProbability(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.)
|
||||
}
|
||||
// func EffectiveDefence(defShields, defShiledsTech, defFullMass float64) float64 {
|
||||
// return defShields * defShiledsTech / math.Pow(defFullMass, 1./3.) * math.Pow(30., 1./3.)
|
||||
// }
|
||||
|
||||
func (b BattleReport) MarshalBinary() (data []byte, err error) {
|
||||
return json.Marshal(&b)
|
||||
|
||||
@@ -1,34 +1,14 @@
|
||||
package game_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/iliadenisov/galaxy/internal/game/battle"
|
||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
attacker = game.ShipType{
|
||||
ShipTypeReport: game.ShipTypeReport{
|
||||
Name: "Attacker",
|
||||
Drive: 8,
|
||||
Armament: 1,
|
||||
Weapons: 8,
|
||||
Shields: 8,
|
||||
Cargo: 0,
|
||||
},
|
||||
}
|
||||
defender = game.ShipType{
|
||||
ShipTypeReport: game.ShipTypeReport{
|
||||
Name: "Defender",
|
||||
Drive: 1,
|
||||
Armament: 1,
|
||||
Weapons: 1,
|
||||
Shields: 1,
|
||||
Cargo: 0,
|
||||
},
|
||||
}
|
||||
ship = game.ShipType{
|
||||
ShipTypeReport: game.ShipTypeReport{
|
||||
Name: "Ship",
|
||||
@@ -41,31 +21,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func TestDestructionProbability(t *testing.T) {
|
||||
probability := game.DestructionProbability(ship.Weapons, 1, ship.Shields, 1, ship.EmptyMass())
|
||||
assert.Equal(t, .5, probability)
|
||||
|
||||
undefeatedShip := ship
|
||||
undefeatedShip.Shields = 55
|
||||
probability = game.DestructionProbability(ship.Weapons, 1, undefeatedShip.Shields, 1, undefeatedShip.EmptyMass())
|
||||
assert.LessOrEqual(t, probability, 0.)
|
||||
|
||||
disruptiveShip := ship
|
||||
disruptiveShip.Weapons = 40
|
||||
probability = game.DestructionProbability(disruptiveShip.Weapons, 1, ship.Shields, 1, ship.EmptyMass())
|
||||
assert.GreaterOrEqual(t, probability, 1.)
|
||||
}
|
||||
|
||||
func TestEffectiveDefence(t *testing.T) {
|
||||
assert.Equal(t, 10., game.EffectiveDefence(ship.Shields, 1, ship.EmptyMass()))
|
||||
|
||||
attackerEffectiveDefence := game.EffectiveDefence(attacker.Shields, 1, attacker.EmptyMass())
|
||||
defenderEffectiveDefence := game.EffectiveDefence(defender.Shields, 1, defender.EmptyMass())
|
||||
|
||||
// attacker's effective shields must be 'just' 4 times greater than defender's
|
||||
assert.InDelta(t, defenderEffectiveDefence*4, attackerEffectiveDefence, 0)
|
||||
}
|
||||
|
||||
func TestCollectPlanetGroups(t *testing.T) {
|
||||
g := newGame()
|
||||
|
||||
@@ -158,24 +113,7 @@ func TestFilterBattleOpponents(t *testing.T) {
|
||||
assert.True(t, game.FilterBattleOpponents(g, 2, 0, cacheShipGroupRaceID, cacheRelation, cacheShipClass, cacheProbability))
|
||||
cacheRelation[Race_1_idx][Race_0_idx] = game.RelationWar
|
||||
|
||||
assert.LessOrEqual(t, game.DestructionProbability(Cruiser.Weapons, 1, undefeatedShip.Shields, 1, undefeatedShip.EmptyMass()), 0.)
|
||||
assert.LessOrEqual(t, battle.DestructionProbability(Cruiser.Weapons, 1, undefeatedShip.Shields, 1, undefeatedShip.EmptyMass()), 0.)
|
||||
assert.True(t, game.FilterBattleOpponents(g, 1, 3, cacheShipGroupRaceID, cacheRelation, cacheShipClass, cacheProbability))
|
||||
assert.NotContains(t, cacheProbability[1], 3)
|
||||
}
|
||||
|
||||
func TestSlicesDeleteFunc(t *testing.T) {
|
||||
type Container struct {
|
||||
S []int
|
||||
}
|
||||
c := Container{S: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
|
||||
r1 := slices.DeleteFunc(c.S, func(e int) bool { return e%2 != 0 })
|
||||
assert.Len(t, r1, 5)
|
||||
for i := range r1 {
|
||||
assert.Equal(t, i*2, r1[i], "elem #%d", i)
|
||||
assert.Equal(t, i*2, c.S[i], "elem #%d", i)
|
||||
}
|
||||
assert.Len(t, c.S, 10)
|
||||
for i := len(r1); i < len(c.S); i++ {
|
||||
assert.Equal(t, 0, c.S[i], "elem #%d", i)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user