func (self *State) executeConflicts(l common.Logger) { execution := []func(){} for _, node := range self.Nodes { total := 0 for _, units := range node.Units { total += units } for playerId, units := range node.Units { enemies := total - units if units > 0 && enemies > 0 { newSum := common.Max(0, common.Min(units-1, int(float64(units)-(float64(enemies)/5.0)))) playerIdCpy := playerId nodeCpy := node if newSum < units { oldSum := units execution = append(execution, func() { nodeCpy.Units[playerIdCpy] = newSum self.Changes[nodeCpy.Id] = append(self.Changes[nodeCpy.Id], Change{ Units: newSum - oldSum, PlayerId: playerIdCpy, Reason: ChangeReason("Conflict"), }) }) } } } } for _, exec := range execution { exec() } }
func (self *State) executeOrders(orderMap map[PlayerId]Orders) { execution := []func(){} for playerId, orders := range orderMap { for _, order := range orders { if src, found := self.Nodes[order.Src]; found { if edge, found := src.Edges[order.Dst]; found { toMove := common.Min(src.Units[playerId], order.Units) src.Units[playerId] -= toMove edgeCpy := edge playerIdCpy := playerId if toMove > 0 { execution = append(execution, func() { edgeCpy.Units[0][playerIdCpy] += toMove self.Changes[edgeCpy.Src] = append(self.Changes[edgeCpy.Src], Change{ Units: -toMove, PlayerId: playerIdCpy, Reason: ChangeReason("Orders"), }) }) } } } } } for _, exec := range execution { exec() } }
func (self *State) executeGrowth(c common.Logger) { execution := []func(){} for _, node := range self.Nodes { total := 0 for _, units := range node.Units { total += units } players := make([]PlayerId, 0, len(node.Units)) for playerId, units := range node.Units { if units > 0 { players = append(players, playerId) } } if len(players) == 1 { playerId := players[0] units := node.Units[playerId] if total > 0 && total < node.Size { nodeCpy := node newSum := common.Min(node.Size, int(1+float64(units)*(1.0+(growthFactor*(float64(node.Size-total)/float64(node.Size)))))) if newSum > units { execution = append(execution, func() { nodeCpy.Units[playerId] = newSum self.Changes[nodeCpy.Id] = append(self.Changes[nodeCpy.Id], Change{ Units: newSum - units, PlayerId: playerId, Reason: ChangeReason("Growth"), }) }) } } } else if len(players) > 1 { if total > node.Size { for playerId, units := range node.Units { if units > 0 { playerIdCpy := playerId nodeCpy := node newSum := common.Max(0, int(float64(units)/(1.0+(starvationFactor*(float64(units)/float64(node.Size)))))-1) if newSum < units { oldSum := units execution = append(execution, func() { nodeCpy.Units[playerIdCpy] = newSum self.Changes[nodeCpy.Id] = append(self.Changes[nodeCpy.Id], Change{ Units: newSum - oldSum, PlayerId: playerIdCpy, Reason: ChangeReason("Starvation"), }) }) } } } } } } for _, exec := range execution { exec() } }
/* Orders will return orders randomly moving up to 20% of all troops in each occupied node along randomly chosen edges of that node. */ func (self Randomizer) Orders(logger common.Logger, me state.PlayerId, s *state.State) (result state.Orders) { // Go through all nodes for _, node := range s.Nodes { // If I have units here if node.Units[me] > 0 { // Create a slice with room for one float per edge in this node breakpoints := make(sort.Float64Slice, len(node.Edges)) // Fill it with numbers between 0 and 0.2 for index, _ := range breakpoints { breakpoints[index] = rand.Float64() / 5 } // Sort the numbers sort.Sort(breakpoints) lastRate := 0.0 rate := 1.0 // For each edge in this node for _, edge := range node.Edges { // Take the fraction between the first float in the slice and the last picked float (or zero) rate = breakpoints[0] - lastRate lastRate = rate // Remove the first float from the slice breakpoints = breakpoints[1:] // Calculate how many units the fraction corresponds to units := common.Min(node.Units[me], int(float64(node.Units[me])*rate)) // If any, create a move order for those units if units > 0 { result = append(result, state.Order{ Src: edge.Src, Dst: edge.Dst, Units: units, }) } } } } // Return the created orders return }