feat: cargo unload challenge
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
e "github.com/iliadenisov/galaxy/internal/error"
|
||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||
"github.com/iliadenisov/galaxy/internal/model/order"
|
||||
)
|
||||
|
||||
@@ -108,11 +109,12 @@ func (c *Controller) applyCommand(actor string, cmd order.DecodableCommand) (err
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: test commands ordering
|
||||
func (c *Controller) applyOrders(t uint) error {
|
||||
raceOrder := make(map[int][]order.DecodableCommand)
|
||||
unloadGroups := make([]uuid.UUID, 0)
|
||||
unloadQuantities := make([]float64, 0)
|
||||
commandRace := make(map[string]string)
|
||||
challenge := make(map[string]*order.CommandShipGroupUnload)
|
||||
cmdApplied := make(map[string]bool)
|
||||
|
||||
for ri := range c.Cache.listRaceActingIdx() {
|
||||
o, ok, err := c.Repo.LoadOrder(t, c.Cache.g.Race[ri].ID)
|
||||
if err != nil {
|
||||
@@ -123,30 +125,33 @@ func (c *Controller) applyOrders(t uint) error {
|
||||
}
|
||||
raceOrder[ri] = o.Commands
|
||||
for i := range o.Commands {
|
||||
if o.Commands[i].CommandType() == order.CommandTypeShipGroupUnload {
|
||||
unloadCommand := o.Commands[i].(order.CommandShipGroupUnload)
|
||||
unloadGroups = append(unloadGroups, uuid.MustParse(unloadCommand.ID))
|
||||
unloadQuantities = append(unloadQuantities, unloadCommand.Quantity)
|
||||
commandRace[o.Commands[i].CommandID()] = c.Cache.g.Race[ri].Name
|
||||
if v, ok := order.AsCommand[*order.CommandShipGroupUnload](o.Commands[i]); ok {
|
||||
if _, ok := challenge[v.ID]; ok {
|
||||
panic(fmt.Sprintf("unload command %s already cached", v.ID))
|
||||
}
|
||||
if ok, err := c.shouldChallenge(v); err != nil {
|
||||
return err
|
||||
} else if ok {
|
||||
challenge[v.ID] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.Cache.shipGroupUnloadColonistChallenge(unloadGroups, unloadQuantities); err != nil {
|
||||
return err
|
||||
for _, cmdID := range c.challengeUnload(challenge) {
|
||||
if err := c.applyCommand(commandRace[cmdID], challenge[cmdID]); err == nil {
|
||||
cmdApplied[cmdID] = true
|
||||
}
|
||||
}
|
||||
|
||||
for ri := range raceOrder {
|
||||
for _, cmd := range raceOrder[ri] {
|
||||
if cmd.CommandType() == order.CommandTypeShipGroupUnload {
|
||||
// group unload commands execution should be failed at this point,
|
||||
// otherwise produce no-errors
|
||||
if v, ok := order.AsCommand[*order.CommandShipGroupUnload](cmd); ok {
|
||||
v.Result(0)
|
||||
}
|
||||
if v, ok := cmdApplied[cmd.CommandID()]; ok && v {
|
||||
continue
|
||||
}
|
||||
// any command might fail due to challenged planets colonization
|
||||
_ = c.applyCommand(c.Cache.g.Race[ri].Name, cmd)
|
||||
_ = c.applyCommand(commandRace[cmd.CommandID()], cmd)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,3 +163,57 @@ func (c *Controller) applyOrders(t uint) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) shouldChallenge(cmd *order.CommandShipGroupUnload) (resut bool, err error) {
|
||||
sgi, ok := c.Cache.shipGroupIndexByID(uuid.MustParse(cmd.ID))
|
||||
if !ok {
|
||||
err = e.NewGameStateError("challenge group unload: group not found: %v", cmd.ID)
|
||||
return
|
||||
}
|
||||
sg := c.Cache.ShipGroup(sgi)
|
||||
pn, ok := sg.AtPlanet()
|
||||
if !ok || sg.CargoType == nil {
|
||||
return false, nil
|
||||
}
|
||||
p := c.Cache.MustPlanet(pn)
|
||||
if p.Owned() || *sg.CargoType != game.CargoColonist {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *Controller) challengeUnload(challenge map[string]*order.CommandShipGroupUnload) []string {
|
||||
if len(challenge) == 0 {
|
||||
return nil
|
||||
}
|
||||
planetRaceQuantity := make(map[uint]map[int]float64, 0)
|
||||
raceCommand := make(map[uint]map[int][]string)
|
||||
for cmdID, cmd := range challenge {
|
||||
sgi, ok := c.Cache.shipGroupIndexByID(uuid.MustParse(cmd.ID))
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("challenge group unload: group not found: %v", cmd.ID))
|
||||
}
|
||||
sg := c.Cache.ShipGroup(sgi)
|
||||
ri := c.Cache.ShipGroupOwnerRaceIndex(sgi)
|
||||
pn, ok := sg.AtPlanet()
|
||||
if _, ok := raceCommand[pn]; !ok {
|
||||
raceCommand[pn] = make(map[int][]string)
|
||||
}
|
||||
raceCommand[pn][ri] = append(raceCommand[pn][ri], cmdID)
|
||||
if _, ok := planetRaceQuantity[pn]; !ok {
|
||||
planetRaceQuantity[pn] = make(map[int]float64)
|
||||
}
|
||||
planetRaceQuantity[pn][ri] = planetRaceQuantity[pn][ri] + UnloadCargoRequest(float64(sg.Load), cmd.Quantity)
|
||||
}
|
||||
|
||||
result := make([]string, 0)
|
||||
for pn := range planetRaceQuantity {
|
||||
if len(planetRaceQuantity[pn]) < 2 {
|
||||
continue
|
||||
}
|
||||
winner := MaxOrRandomLoadId(planetRaceQuantity[pn], func(ri int) float64 { return float64(c.Cache.g.Race[ri].Votes) })
|
||||
result = append(result, raceCommand[pn][winner]...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user