Files
tiennm99 8f739e02ae refactor(wsapi): split room.go and session.go along their seams
room.go was 1919 lines with every room concern in one file. Pure
moves, no signature or behaviour changes: room.go keeps the struct,
its constructor, the input loop and the small seat-authority helpers;
room_inputs.go the message types; room_lobby.go seating and the lobby
between games; room_game.go everything that touches a running game;
room_presence.go the reconnect window and resume; room_chat.go the
room's own conversation; bot_board.go the bot's frozen view of a
position.

session.go was two unrelated halves in one 762-line file: the socket
(session.go, kept) and the protocol (dispatch.go, new) — dispatch and
the handshake/resume flow it routes into.

Verified with go build, go vet, golangci-lint and go test -race, and
by counting: every one of the 89 room.go and 27 session.go top-level
declarations appears in the split exactly once.
2026-09-21 16:25:20 +07:00

49 lines
1.4 KiB
Go

package wsapi
import (
"iter"
"github.com/tiennm99dev/noitu/server/internal/game"
)
// The bot's read-only view of a position, frozen off the engine on the room
// goroutine before a worker goroutine exists to race it.
// frozenBoard is an immutable position for a bot worker to search.
//
// It satisfies bot.Board without holding the engine. The dictionary is safe to
// share — the store loads once at Open and is read-only thereafter — but the
// used set is engine state, so it is copied.
type frozenBoard struct {
legal []string
used map[string]struct{}
dict game.Dictionary
}
func freezeBoard(e *game.Engine) *frozenBoard {
// UsedWords already includes the opening word — it seeds the engine's own
// set — so there is nothing left to add here, and nothing to copy out of a
// history that grows with the game.
used := make(map[string]struct{})
for word := range e.UsedWords() {
used[word] = struct{}{}
}
return &frozenBoard{legal: e.LegalMoves(), used: used, dict: e.Dict()}
}
func (b *frozenBoard) LegalMoves() []string { return b.legal }
func (b *frozenBoard) Used(word string) bool {
_, ok := b.used[word]
return ok
}
func (b *frozenBoard) WordsStartingWith(syllable string) iter.Seq[string] {
return b.dict.WordsStartingWith(syllable)
}
func (b *frozenBoard) LastSyllable(word string) (string, bool) {
return b.dict.LastSyllable(word)
}