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