diff --git a/handlers/actions.go b/handlers/actions.go index ba49f60..c5ae0ad 100644 --- a/handlers/actions.go +++ b/handlers/actions.go @@ -74,9 +74,6 @@ func saveFullInfo(fi *models.FullInfo) error { if err := saveState(fi.State.Username, fi.State); err != nil { return err } - // if fi.Room == nil { // can be null on exit - // return nil - // } if err := saveRoom(fi.Room); err != nil { return err } @@ -85,14 +82,6 @@ func saveFullInfo(fi *models.FullInfo) error { func notifyBotIfNeeded(fi *models.FullInfo) { if botName := fi.Room.WhichBotToMove(); botName != "" { - // // get bot from memcache - // bot, err := loadBot(botName, fi.Room.ID) - // if err != nil { - // log.Error("failed to load bot", "bot_name", botName, "room_id", fi.Room.ID) - // // abortWithError(w, err.Error()) - // // return - // } - // send signal to bot llmapi.SignalChanMap[botName] <- true } log.Debug("no bot", "room_id", fi.Room.ID) diff --git a/handlers/elements.go b/handlers/elements.go index 137ce78..666a71f 100644 --- a/handlers/elements.go +++ b/handlers/elements.go @@ -2,6 +2,7 @@ package handlers import ( "errors" + "fmt" "golias/llmapi" "golias/models" "html/template" @@ -147,7 +148,8 @@ func HandleAddBot(w http.ResponseWriter, r *http.Request) { } // TODO: what if bot exists already? // control number and names of bots - bot, err := llmapi.NewBot(role, team, "bot1", fi.Room.ID, cfg) + botname := fmt.Sprintf("bot_%d", len(llmapi.SignalChanMap)+1) // what if many rooms? + bot, err := llmapi.NewBot(role, team, botname, fi.Room.ID, cfg) if err != nil { abortWithError(w, err.Error()) return diff --git a/llmapi/main.go b/llmapi/main.go index 5dd5228..9860910 100644 --- a/llmapi/main.go +++ b/llmapi/main.go @@ -27,8 +27,8 @@ var ( SignalChanMap = make(map[string]chan bool) DoneChanMap = make(map[string]chan bool) // got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0 - MimePrompt = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the red team (people who would guess by your clue want open the red cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` - GuesserPrompt = `we are playing alias;\nyou are to guess words of the red team (people who would guess by your clue want open the red cards) by given clue and a number of meant guesses;\nplease return your guesses and words that you did not wish to open, but think that they could be also meant by the clue in json like:\n{\n\"guesses\": [\"word1\", \"word2\", ...],\n\"could_be\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` + MimePrompt = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the %s team (people who would guess by your clue want open the %s cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` + GuesserPrompt = `we are playing alias;\nyou are to guess words of the %s team (people who would guess by your clue want open the %s cards) by given clue and a number of meant guesses;\nplease return your guesses and words that you did not wish to open, but think that they could be also meant by the clue in json like:\n{\n\"guesses\": [\"word1\", \"word2\", ...],\n\"could_be\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` // notifier = ) @@ -142,12 +142,57 @@ func (b *Bot) StartBot() { room.MimeDone = true eventPayload = mimeResp.Clue + mimeResp.Number case models.UserRoleGuesser: - gr := GusserResp{} - if err := json.Unmarshal([]byte(sj), &gr); err != nil { - b.log.Error("failed to unmarshal guesser resp", "error", err) - return + for _, word := range tempMap["guesses"].([]string) { + color, exists := room.WCMap[word] + b.log.Debug("bot trying to open card", "word", word, "color", + color, "exists", exists) + if !exists { + return + } + room.RevealSpecificWord(word) + room.UpdateCounter() + action := models.Action{ + Actor: b.BotName, + ActorColor: b.Team, + WordColor: string(color), + Action: "guessed", + Word: word, + } + room.ActionHistory = append(room.ActionHistory, action) + // if opened card is of color of opp team, change turn + oppositeColor := room.GetOppositeTeamColor() + switch string(color) { + case "black": + // game over + room.IsRunning = false + room.IsOver = true + room.TeamWon = oppositeColor + case "white", string(oppositeColor): + // end turn + room.TeamTurn = oppositeColor + room.MimeDone = false + } + // check if no cards left => game over + if room.BlueCounter == 0 { + // blue won + room.IsRunning = false + room.IsOver = true + room.TeamWon = "blue" + } + if room.RedCounter == 0 { + // red won + room.IsRunning = false + room.IsOver = true + room.TeamWon = "red" + } + if err := saveRoom(room); err != nil { + b.log.Error("failed to save room", "room", room) + return + } } - b.log.Info("mime resp log", "guesserResp", gr) + b.log.Info("mime resp log", "guesserResp", tempMap) + eventName = models.NotifyRoomUpdatePrefix + room.ID + eventPayload = "" default: b.log.Error("unexpected role", "role", b.Role, "llmResp", sj) return @@ -157,6 +202,9 @@ func (b *Bot) StartBot() { b.log.Error("failed to save room", "error", err) return } + if botName := room.WhichBotToMove(); botName != "" { + SignalChanMap[botName] <- true + } broker.Notifier.Notifier <- broker.NotificationEvent{ EventName: eventName, Payload: eventPayload, @@ -291,11 +339,10 @@ func (b *Bot) BuildPrompt(room *models.Room) string { // Escape the JSON string for inclusion in another JSON field escapedData := strings.ReplaceAll(string(data), `"`, `\"`) if b.Role == models.UserRoleMime { - return fmt.Sprintf(MimePrompt, room.BlueCounter, room.RedCounter, escapedData) + return fmt.Sprintf(MimePrompt, b.Team, b.Team, room.BlueCounter, room.RedCounter, escapedData) } - if b.Role == models.UserRoleMime { - // TODO: - return "" + if b.Role == models.UserRoleGuesser { + return fmt.Sprintf(GuesserPrompt, b.Team, b.Team, room.BlueCounter, room.RedCounter, escapedData) } return "" } diff --git a/main.go b/main.go index 1484ec8..e4e4562 100644 --- a/main.go +++ b/main.go @@ -11,10 +11,9 @@ import ( func ListenToRequests(port string) error { mux := http.NewServeMux() server := &http.Server{ - Handler: handlers.LogRequests(handlers.GetSession(mux)), - Addr: port, - ReadTimeout: time.Second * 5, - // WriteTimeout: time.Second * 5, + Handler: handlers.LogRequests(handlers.GetSession(mux)), + Addr: port, + ReadTimeout: time.Second * 5, WriteTimeout: 0, // sse streaming } fs := http.FileServer(http.Dir("assets/")) @@ -23,7 +22,6 @@ func ListenToRequests(port string) error { mux.HandleFunc("GET /ping", handlers.HandlePing) mux.HandleFunc("GET /", handlers.HandleHome) mux.HandleFunc("POST /login", handlers.HandleFrontLogin) - // mux.HandleFunc("GET /room", handlers.HandleRoomEnter) mux.HandleFunc("POST /join-team", handlers.HandleJoinTeam) mux.HandleFunc("GET /end-turn", handlers.HandleEndTurn) mux.HandleFunc("POST /room-create", handlers.HandleCreateRoom)