Feat: guess limit
This commit is contained in:
@ -14,6 +14,11 @@
|
||||
<p>GAME OVER; team <span class="text-{{.Room.TeamWon}}-500">{{.Room.TeamWon}}</span> won! 🧚</p>
|
||||
{{else}}
|
||||
<p>Turn of the <span class="text-{{.Room.TeamTurn}}-500">{{.Room.TeamTurn}}</span> team</p>
|
||||
{{if .Room.MimeDone}}
|
||||
<p class="text-{{.Room.TeamTurn}}-500">Waiting for guessers</p>
|
||||
{{else}}
|
||||
<p class="text-{{.Room.TeamTurn}}-500">Waiting for mime</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<p>
|
||||
{{if eq .State.Team ""}}
|
||||
|
@ -112,18 +112,19 @@ func loadState(username string) (*models.UserState, error) {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func loadBot(botName, roomID string) (*llmapi.Bot, error) {
|
||||
key := "botkey_" + roomID + botName
|
||||
data, err := memcache.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := &llmapi.Bot{}
|
||||
if err := json.Unmarshal(data, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
// not used
|
||||
// func loadBot(botName, roomID string) (*llmapi.Bot, error) {
|
||||
// key := "botkey_" + roomID + botName
|
||||
// data, err := memcache.Get(key)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// resp := &llmapi.Bot{}
|
||||
// if err := json.Unmarshal(data, &resp); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return resp, nil
|
||||
// }
|
||||
|
||||
func getAllNames() []string {
|
||||
names := []string{}
|
||||
|
@ -84,6 +84,14 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
// if opened card is of color of opp team, change turn
|
||||
oppositeColor := fi.Room.GetOppositeTeamColor()
|
||||
fi.Room.OpenedThisTurn++
|
||||
if fi.Room.ThisTurnLimit >= fi.Room.OpenedThisTurn {
|
||||
// end turn
|
||||
fi.Room.TeamTurn = oppositeColor
|
||||
fi.Room.MimeDone = false
|
||||
fi.Room.OpenedThisTurn = 0
|
||||
fi.Room.ThisTurnLimit = 0
|
||||
}
|
||||
switch string(color) {
|
||||
case "black":
|
||||
// game over
|
||||
@ -96,38 +104,46 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
||||
WordColor: "black",
|
||||
Action: "game over",
|
||||
}
|
||||
fi.Room.OpenedThisTurn = 0
|
||||
fi.Room.ThisTurnLimit = 0
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
case "white", string(oppositeColor):
|
||||
// end turn
|
||||
fi.Room.TeamTurn = oppositeColor
|
||||
fi.Room.MimeDone = false
|
||||
}
|
||||
// check if no cards left => game over
|
||||
if fi.Room.BlueCounter == 0 {
|
||||
// blue won
|
||||
fi.Room.IsRunning = false
|
||||
fi.Room.IsOver = true
|
||||
fi.Room.TeamWon = "blue"
|
||||
action := models.Action{
|
||||
Actor: fi.State.Username,
|
||||
ActorColor: string(fi.State.Team),
|
||||
WordColor: "blue",
|
||||
Action: "game over",
|
||||
fi.Room.OpenedThisTurn = 0
|
||||
fi.Room.ThisTurnLimit = 0
|
||||
// check if no cards left => game over
|
||||
if fi.Room.BlueCounter == 0 {
|
||||
// blue won
|
||||
fi.Room.IsRunning = false
|
||||
fi.Room.IsOver = true
|
||||
fi.Room.TeamWon = "blue"
|
||||
action := models.Action{
|
||||
Actor: fi.State.Username,
|
||||
ActorColor: string(fi.State.Team),
|
||||
WordColor: "blue",
|
||||
Action: "game over",
|
||||
}
|
||||
fi.Room.OpenedThisTurn = 0
|
||||
fi.Room.ThisTurnLimit = 0
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
}
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
}
|
||||
if fi.Room.RedCounter == 0 {
|
||||
// red won
|
||||
fi.Room.IsRunning = false
|
||||
fi.Room.IsOver = true
|
||||
fi.Room.TeamWon = "red"
|
||||
action := models.Action{
|
||||
Actor: fi.State.Username,
|
||||
ActorColor: string(fi.State.Team),
|
||||
WordColor: "red",
|
||||
Action: "game over",
|
||||
if fi.Room.RedCounter == 0 {
|
||||
// red won
|
||||
fi.Room.IsRunning = false
|
||||
fi.Room.IsOver = true
|
||||
fi.Room.TeamWon = "red"
|
||||
action := models.Action{
|
||||
Actor: fi.State.Username,
|
||||
ActorColor: string(fi.State.Team),
|
||||
WordColor: "red",
|
||||
Action: "game over",
|
||||
}
|
||||
fi.Room.OpenedThisTurn = 0
|
||||
fi.Room.ThisTurnLimit = 0
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
}
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
}
|
||||
if err := saveFullInfo(fi); err != nil {
|
||||
abortWithError(w, err.Error())
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"gralias/models"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func HandleCreateRoom(w http.ResponseWriter, r *http.Request) {
|
||||
@ -143,6 +144,8 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
||||
fi.Room.IsRunning = true
|
||||
fi.Room.IsOver = false
|
||||
fi.Room.TeamTurn = "blue"
|
||||
fi.Room.OpenedThisTurn = 0
|
||||
fi.Room.ThisTurnLimit = 0
|
||||
loadCards(fi.Room)
|
||||
fi.Room.UpdateCounter()
|
||||
fi.Room.TeamWon = ""
|
||||
@ -226,6 +229,11 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) {
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
guessLimitU64, err := strconv.ParseUint(num, 10, 8)
|
||||
if err != nil {
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
// validations ===
|
||||
if fi.State.Team != models.UserTeam(fi.Room.TeamTurn) {
|
||||
err = errors.New("not your team's move")
|
||||
@ -253,6 +261,7 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
fi.Room.MimeDone = true
|
||||
fi.Room.ThisTurnLimit = uint8(guessLimitU64) + 1
|
||||
notify(models.NotifyBacklogPrefix+fi.Room.ID, clue+num)
|
||||
notifyBotIfNeeded(fi)
|
||||
if err := saveFullInfo(fi); err != nil {
|
||||
|
@ -2,6 +2,7 @@ package llmapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
@ -29,7 +30,7 @@ func (p *deepSeekParser) ParseBytes(body []byte) (map[string]any, error) {
|
||||
}
|
||||
if len(dsResp.Choices) == 0 {
|
||||
p.log.Error("empty choices", "dsResp", dsResp)
|
||||
err := fmt.Errorf("empty choices in dsResp")
|
||||
err := errors.New("empty choices in dsResp")
|
||||
return nil, err
|
||||
}
|
||||
text := dsResp.Choices[0].Text
|
||||
@ -37,7 +38,7 @@ func (p *deepSeekParser) ParseBytes(body []byte) (map[string]any, error) {
|
||||
ri := strings.LastIndex(text, "}")
|
||||
if li < 0 || ri < 1 {
|
||||
p.log.Error("not a json", "msg", text)
|
||||
err := fmt.Errorf("fn: ParseBytes, not a json")
|
||||
err := fmt.Errorf("fn: ParseBytes, not a json; data: %s", text)
|
||||
return nil, err
|
||||
}
|
||||
sj := text[li : ri+1]
|
||||
@ -67,7 +68,7 @@ func (p *lcpRespParser) ParseBytes(body []byte) (map[string]any, error) {
|
||||
}
|
||||
if len(resp.Choices) == 0 {
|
||||
p.log.Error("empty choices", "resp", resp)
|
||||
err := fmt.Errorf("empty choices in resp")
|
||||
err := errors.New("empty choices in resp")
|
||||
return nil, err
|
||||
}
|
||||
text := resp.Choices[0].Message.Content
|
||||
@ -75,7 +76,7 @@ func (p *lcpRespParser) ParseBytes(body []byte) (map[string]any, error) {
|
||||
ri := strings.LastIndex(text, "}")
|
||||
if li < 0 || ri < 1 {
|
||||
p.log.Error("not a json", "msg", text)
|
||||
err := fmt.Errorf("fn: ParseBytes, not a json")
|
||||
err := fmt.Errorf("fn: ParseBytes, not a json; data: %s", text)
|
||||
return nil, err
|
||||
}
|
||||
sj := text[li : ri+1]
|
||||
|
3
main.go
3
main.go
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gralias/config"
|
||||
"gralias/handlers"
|
||||
"log/slog"
|
||||
@ -19,7 +18,7 @@ func ListenToRequests(port string) error {
|
||||
mux := http.NewServeMux()
|
||||
server := &http.Server{
|
||||
Handler: handlers.LogRequests(handlers.GetSession(mux)),
|
||||
Addr: fmt.Sprintf(":%s", port),
|
||||
Addr: ":" + port,
|
||||
ReadTimeout: time.Second * 5, // TODO: to cfg
|
||||
WriteTimeout: 0, // sse streaming
|
||||
}
|
||||
|
@ -58,23 +58,25 @@ type Room struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
// RoomName string `json:"room_name"`
|
||||
RoomPass string `json:"room_pass"`
|
||||
RoomLink string
|
||||
CreatorName string `json:"creator_name"`
|
||||
PlayerList []string `json:"player_list"`
|
||||
ActionHistory []Action
|
||||
TeamTurn UserTeam
|
||||
RedTeam Team
|
||||
BlueTeam Team
|
||||
Cards []WordCard
|
||||
WCMap map[string]WordColor
|
||||
BotMap map[string]BotPlayer // key is bot name
|
||||
Result uint8 // 0 for unknown; 1 is win for red; 2 if for blue;
|
||||
BlueCounter uint8
|
||||
RedCounter uint8
|
||||
RedTurn bool // false is blue turn
|
||||
MimeDone bool
|
||||
IsPublic bool
|
||||
RoomPass string `json:"room_pass"`
|
||||
RoomLink string
|
||||
CreatorName string `json:"creator_name"`
|
||||
PlayerList []string `json:"player_list"`
|
||||
ActionHistory []Action
|
||||
TeamTurn UserTeam
|
||||
RedTeam Team
|
||||
BlueTeam Team
|
||||
Cards []WordCard
|
||||
ThisTurnLimit uint8 // how many cards guessers can open this turn
|
||||
OpenedThisTurn uint8 // how many cards have been opened this turn
|
||||
WCMap map[string]WordColor
|
||||
BotMap map[string]BotPlayer // key is bot name
|
||||
Result uint8 // 0 for unknown; 1 is win for red; 2 if for blue;
|
||||
BlueCounter uint8
|
||||
RedCounter uint8
|
||||
RedTurn bool // false is blue turn
|
||||
MimeDone bool
|
||||
IsPublic bool
|
||||
// GameSettings *GameSettings `json:"settings"`
|
||||
IsRunning bool `json:"is_running"`
|
||||
Language string `json:"language" example:"en" form:"language"`
|
||||
|
8
todos.md
8
todos.md
@ -6,10 +6,9 @@
|
||||
- invite link; +
|
||||
- login with invite link; +
|
||||
- add html icons of whos turn it is (like an image of big ? when mime is thinking);
|
||||
- there three places for bot to check if its its move: start-game; end-turn, after mime gave clue;
|
||||
- remove bot button (if game is not running, or bot already added);
|
||||
- there three places for bot to check if its its move: start-game; end-turn, after mime gave clue; +
|
||||
- remove bot button (if game is not running, or bot already added); +
|
||||
- show in backlog (and with that in prompt to llm) how many cards are left to open, also additional comment: if guess was right;
|
||||
- if bot already added; remove add bot button;
|
||||
- hide clue input for mime when it's not their turn;
|
||||
- needs resend to llm btn; +
|
||||
|
||||
@ -26,7 +25,8 @@
|
||||
### issues
|
||||
- after the game started (isrunning) players should be able join guessers, but not switch team, or join as a mime;
|
||||
- cleanup backlog after new game is started;
|
||||
- guessers should not be able to open more cards, than mime gave them +1;
|
||||
- guessers should not be able to open more cards, than mime gave them +1 (auto end turn); +
|
||||
- 0 should mean without limit;
|
||||
- sse hangs / fails connection which causes to wait for cards to open a few seconds (on local machine);
|
||||
- after starting a new game (after old one) blue mime has no clue input;
|
||||
- gameover to backlog;
|
||||
|
Reference in New Issue
Block a user