func listenForMoveRequests(conn *net.TCPConn) { listenServe := make(chan []uint8) easynet.TieConnToChannel(conn, listenServe) for data := range listenServe { r := new(ttypes.BotMoveRequest) err := json.Unmarshal(data, r) easynet.DieIfError(err, "JSON error") if r.Kill { fmt.Printf("Bot on %s received kill signal\n", os.Args[0]) os.Exit(0) } fmt.Printf("Bot at %d, %d received messages: %v\n", r.YourX, r.YourY, r.Messages) fmt.Printf(" Sees other bots: %v\n", r.OtherBots) //Do something response := new(ttypes.BotMoveResponse) if r.YourY < 5 { response.MoveDirection = "up" } else if r.YourY > 5 { response.MoveDirection = "down" } // response.BroadcastMessage = fmt.Sprintf("'I am %v at %d, %d'", os.Args[0], r.YourX, r.YourY) responseString, err := json.Marshal(response) easynet.DieIfError(err, "JSON marshal error") conn.Write(responseString) } }
// Fork a bot and open a TCP connection to it func setupBot(conf ttypes.BotConf, portNumber int) *net.TCPConn { addrString := "127.0.0.1:" + strconv.Itoa(portNumber) fd := []*os.File{os.Stdin, os.Stdout, os.Stderr} _, err := os.StartProcess(conf.Path, []string{addrString}, nil, "", fd) easynet.DieIfError(err, "Error launching bot") return easynet.Dial(addrString) }
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 } } }
// Set up incoming and outgoing TCP connections to all adjacent coordinators func connectToAdjacents(listener *net.TCPListener) chan bool { adjsServe = make(CoordMap, len(config.AdjacentCoords)) adjsRequest = make(CoordMap, len(config.AdjacentCoords)) listenServe = make(chan []uint8) serveFound := make(chan int) requestFound := make(chan int) allDone := make(chan bool) go func() { for _, adj := range config.AdjacentCoords { go func() { adjsRequest[adj.Identifier] = easynet.Dial(adj.Address) adjsRequest[adj.Identifier].Write([]uint8(strconv.Itoa(config.Identifier))) requestFound <- adj.Identifier }() go func() { newConn := easynet.Accept(listener) identifier, err := strconv.Atoi(string(easynet.ReceiveFrom(newConn))) easynet.DieIfError(err, "String conversion error") adjsServe[identifier] = newConn easynet.TieConnToChannel(newConn, listenServe) serveFound <- identifier }() } for i := 0; i < len(config.AdjacentCoords); i++ { <-requestFound <-serveFound } fmt.Printf("%d is connected to all neighbors\n", config.Identifier) allDone <- true }() return allDone }