func main() { // Print a nice separator at the end of execution so that 'make fancyrun' looks good defer fmt.Println("-------------------") // Initialize globals processing = false complete = make(chan bool) // Begin listening on the port passed on the command line listener := easynet.HostWithAddress(os.Args[1]) defer listener.Close() // Set up a TCP connection to the master connectionToMaster := easynet.Accept(listener) defer connectionToMaster.Close() // Read configuration from the connection to master config = new(ttypes.CoordConfig) easynet.ReceiveJson(connectionToMaster, config) respondingToRequestsFor = 0 infoQueue = make([][]ttypes.BotInfo, 1, config.NumTurns) // Confirm configuration connectionToMaster.Write([]uint8("connected")) // Set up bots and connect to adjacent coordinators setupAll(listener) // Remember to terminate all child processes upon termination of this process defer killChildren() // Close all connections when program terminates for _, conn := range adjsServe { defer conn.Close() } // Confirm setup connectionToMaster.Write([]uint8("setup complete")) fmt.Printf("%d sees data at start as: \n%v\n grid: %v\n", config.Identifier, botInfosForNeighbor(0), config.Terrain) // Transition to both listening states go listenForMaster(connectionToMaster) go listenForPeer() // Wait for those loops to exit <-complete <-complete fmt.Printf("%d sees data at end as: \n%v\n grid: %v\n", config.Identifier, botInfosForNeighbor(0), config.Terrain) // Confirm termination finalTally := new(ttypes.Finish) for _, s := range botStates { if !s.Dead() { finalTally.NumBots += 1 } } easynet.SendJson(connectionToMaster, finalTally) }
func getAgentInfoFromNeighbors() []ttypes.BotInfo { otherInfos := make([]ttypes.BotInfo, len(botStates), len(botStates)*len(adjsServe)) //Copy all infos from botStates into otherInfos for k, s := range botStates { otherInfos[k] = s.Info } //Get updates from neighbors for j, conn := range adjsRequest { fmt.Printf("%d turn %d, request neighbor %d\n", config.Identifier, respondingToRequestsFor, j) r := new(Request) r.Identifier = config.Identifier r.Turn = respondingToRequestsFor r.Command = "GetNodes" easynet.SendJson(conn, r) info := new(RespondNodeInfo) easynet.ReceiveJson(conn, info) otherInfos = append(otherInfos, info.BotData...) } return otherInfos }
func broadcastComplete() { note := new(Request) note.Identifier = config.Identifier note.Turn = respondingToRequestsFor note.Command = "Complete" for i, conn := range adjsRequest { fmt.Printf("%d broadcasting complete to %d\n", config.Identifier, i) easynet.SendJson(conn, note) } }
func handleRequest(data []uint8) { if processing == false { // The game's afoot! processing = true go processNodes() } r := new(Request) err := json.Unmarshal(data, r) easynet.DieIfError(err, "JSON error") switch { case r.Command == "GetNodes": fmt.Printf("%d handle GetNodes from %d\n", config.Identifier, r.Identifier) for respondingToRequestsFor < r.Turn { fmt.Printf("%d not ready for GetNodes\n", config.Identifier) time.Sleep(1000000) } fmt.Printf("%d ready for GetNodes\n", config.Identifier) info := new(RespondNodeInfo) info.Identifier = config.Identifier info.Turn = respondingToRequestsFor if lastInfoListCopied == 0 { info.BotData = botInfosForNeighbor(r.Identifier) } else { info.BotData = infoQueue[lastInfoListCopied][0:len(botStates)] } easynet.SendJson(adjsServe[r.Identifier], info) fmt.Printf("%d sent GetNodes response to %d\n", config.Identifier, r.Identifier) fmt.Printf(" and it was %v\n", info) neighborsLeftUntilUnlock -= 1 if neighborsLeftUntilUnlock <= 0 { fmt.Printf("served all requests for %d\n", lastInfoListCopied) lastInfoListCopied += 1 neighborsLeftUntilUnlock = len(adjsServe) } case r.Command == "Complete": completionsRemaining -= 1 if completionsRemaining == 0 { fmt.Println("All neighbors complete, signaling TCOMPLETE2") complete <- true } } }
func killChild(s *BotState) { req := new(ttypes.BotMoveRequest) req.Kill = true easynet.SendJson(s.Conn, req) }