lib

package
v0.0.0-...-8bad02d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 12, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	Rows      = 6
	Cols      = 7
	WinLength = 4
)

Variables

View Source
var (
	ErrGameNotPlaying      = errors.New("game is not in playing state")
	ErrNotYourTurn         = errors.New("not your turn")
	ErrInvalidMove         = errors.New("invalid move")
	ErrGameNotFound        = errors.New("game not found")
	ErrGameFull            = errors.New("game is full")
	ErrPlayerNotFound      = errors.New("player not found")
	ErrPlayerNotInGame     = errors.New("player not in game")
	ErrPlayerAlreadyInGame = errors.New("player already in game")
	ErrInvalidUsername     = errors.New("invalid username")
	ErrReconnectionFailed  = errors.New("reconnection failed: session not found")
	ErrInvalidMessage      = errors.New("invalid message format")
)

Functions

This section is empty.

Types

type Board

type Board struct {
	// contains filtered or unexported fields
}

Board represents the game board as a graph of connected nodes

func NewBoard

func NewBoard() *Board

NewBoard creates a new board and builds the node graph

func (*Board) CheckWin

func (b *Board) CheckWin(node *Node) bool

CheckWin checks if the last played node creates a winning condition

func (*Board) GetLastPlayedNode

func (b *Board) GetLastPlayedNode(col int) *Node

GetLastPlayedNode returns the node at the top of a column

func (*Board) GetNode

func (b *Board) GetNode(row, col int) *Node

GetNode returns the node at given position

func (*Board) IsFull

func (b *Board) IsFull() bool

IsFull checks if the board is completely full

func (*Board) Play

func (b *Board) Play(col int, player Cell) (*Node, bool)

Play drops a token in the given column for the given player

func (*Board) Reset

func (b *Board) Reset()

Reset clears the board for a new game

func (*Board) ToArray

func (b *Board) ToArray() [Rows][Cols]Cell

ToArray exports the board state as a 2D array

type Cell

type Cell uint8

Cell represents the state of a board cell

const (
	CellEmpty Cell = iota
	CellPlayer0
	CellPlayer1
)

type Client

type Client struct {
	Conn     *websocket.Conn
	SendChan chan Message
	PlayerID PlayerID
	// contains filtered or unexported fields
}

Client handles the websocket connection and implements lib.Sender

func NewClient

func NewClient(conn *websocket.Conn) *Client

NewClient creates a new client

func (*Client) Close

func (c *Client) Close()

Close closes the send channel

func (*Client) GetGameCode

func (c *Client) GetGameCode() string

GetGameCode returns the game code safely

func (*Client) Send

func (c *Client) Send(msg Message)

Send implements lib.Sender interface

func (*Client) SetGameCode

func (c *Client) SetGameCode(code string)

SetGameCode sets the game code safely

func (*Client) WritePump

func (c *Client) WritePump()

WritePump pumps messages from the hub to the websocket connection.

type Direction

type Direction uint8

Direction represents the 8 possible neighbor directions in the board graph

const (
	DirUp Direction = iota
	DirUpRight
	DirRight
	DirDownRight
	DirDown
	DirDownLeft
	DirLeft
	DirUpLeft
)

func (Direction) Opposite

func (d Direction) Opposite() Direction

Opposite returns the opposite direction

type ErrorData

type ErrorData struct {
	Message string `json:"message"`
	Code    string `json:"code,omitempty"`
}

ErrorData contains error information

type Game

type Game struct {
	Code   string
	Board  *Board
	Status GameStatus
	Result GameResult

	Players      [2]*Player
	CurrentTurn  int
	MoveCount    int
	LastPlayedAt time.Time
	CreatedAt    time.Time
	LastMove     *LastMove

	ReplayRequests [2]bool

	// Timer management
	InitialClock  time.Duration // Store initial clock for resets
	TimeRemaining [2]time.Duration
	TurnStartedAt time.Time
	Timer         *time.Timer
	TimerCallback func(string, int) // Called when timer expires with (gameCode, loserIdx)
	// contains filtered or unexported fields
}

Game represents a Connect 4 game session

func NewGame

func NewGame(initialClock time.Duration) *Game

NewGame creates a new game with a random code

func (*Game) AddPlayer

func (game *Game) AddPlayer(player *Player) bool

AddPlayer adds a player to the game

func (*Game) Cleanup

func (g *Game) Cleanup()

Cleanup stops all timers and releases resources (idempotent)

func (*Game) Forfeit

func (g *Game) Forfeit(loserIdx int)

Forfeit handles a player forfeiting the game

func (*Game) GetPlayerIndex

func (g *Game) GetPlayerIndex(id PlayerID) int

GetPlayerIndex returns the index of the given player

func (*Game) GetPlayers

func (g *Game) GetPlayers() [2]*Player

GetPlayers returns the players in the game safely

func (*Game) GetStatus

func (g *Game) GetStatus() GameStatus

GetStatus returns the current game status

func (*Game) GetTimeRemaining

func (g *Game) GetTimeRemaining() [2]time.Duration

GetTimeRemaining returns remaining time for both players adjusted for current turn

func (*Game) HasPlayer

func (g *Game) HasPlayer(id PlayerID) bool

HasPlayer checks if a player is in this game

func (*Game) Play

func (g *Game) Play(playerIdx, col int) error

Play attempts to play a move in the given column

func (*Game) RemovePlayer

func (g *Game) RemovePlayer(id PlayerID) bool

RemovePlayer removes a player from the game (for cleanup when leaving)

func (*Game) RequestReplay

func (g *Game) RequestReplay(playerIdx int) bool

RequestReplay marks a player's desire to replay

type GameCreatedData

type GameCreatedData struct {
	Code string `json:"code"`
}

GameCreatedData sent when game is created

type GameOverData

type GameOverData struct {
	Result GameResult       `json:"result"`
	Board  [Rows][Cols]Cell `json:"board"`
}

GameOverData sent when game ends

type GameResult

type GameResult uint8

GameResult represents the outcome of a finished game

const (
	ResultNone GameResult = iota
	ResultPlayer0Win
	ResultPlayer1Win
	ResultDraw
)

type GameStartData

type GameStartData struct {
	Code          string        `json:"code"`
	CurrentTurn   int           `json:"current_turn"`
	Players       [2]PlayerInfo `json:"players"`
	TimeRemaining [2]int64      `json:"time_remaining"` // milliseconds
}

GameStartData sent when game starts

type GameStateData

type GameStateData struct {
	Code           string           `json:"code"`
	Status         GameStatus       `json:"status"`
	Result         GameResult       `json:"result"`
	Board          [Rows][Cols]Cell `json:"board"`
	Players        [2]PlayerInfo    `json:"players"`
	PlayerIdx      int              `json:"player_idx"`
	CurrentTurn    int              `json:"current_turn"`
	MoveCount      int              `json:"move_count"`
	TimeRemaining  [2]int64         `json:"time_remaining"` // milliseconds
	ReplayRequests [2]bool          `json:"replay_requests"`
	LastMove       *LastMove        `json:"last_move,omitempty"`
}

GameStateData contains full game state for reconnection

type GameStatus

type GameStatus uint8

GameStatus represents the current state of a game

const (
	StatusWaiting GameStatus = iota
	StatusPlaying
	StatusFinished
	StatusCleaned // Game has been cleaned up
)

type JoinGameData

type JoinGameData struct {
	Code string `json:"code"`
}

JoinGameData contains game join request

type LastMove

type LastMove struct {
	Col int `json:"col"`
	Row int `json:"row"`
}

LastMove represents the coordinates of the last move

type LoginData

type LoginData struct {
	Username string    `json:"username"`
	PlayerID *PlayerID `json:"player_id,omitempty"` // for reconnection
}

LoginData contains login credentials

type Message

type Message struct {
	Type MessageType `json:"type"`
	Data interface{} `json:"data,omitempty"`
}

Message represents a websocket message

type MessageType

type MessageType string

MessageType identifies the type of websocket message

const (
	// Client to Server
	MsgLogin            MessageType = "login"
	MsgCreateGame       MessageType = "create_game"
	MsgJoinGame         MessageType = "join_game"
	MsgPlay             MessageType = "play"
	MsgReplay           MessageType = "replay"
	MsgForfeit          MessageType = "forfeit"
	MsgLeaveLobby       MessageType = "leave_lobby"
	MsgJoinMatchmaking  MessageType = "join_matchmaking"
	MsgLeaveMatchmaking MessageType = "leave_matchmaking"

	// Server to Client
	MsgWelcome              MessageType = "welcome"
	MsgGameCreated          MessageType = "game_created"
	MsgGameStart            MessageType = "game_start"
	MsgGameState            MessageType = "game_state"
	MsgMove                 MessageType = "move"
	MsgGameOver             MessageType = "game_over"
	MsgReplayReq            MessageType = "replay_request"
	MsgError                MessageType = "error"
	MsgMatchmakingSearching MessageType = "matchmaking_searching"
	MsgQueueUpdate          MessageType = "queue_update"
)

type MoveData

type MoveData struct {
	PlayerIdx     int              `json:"player_idx"`
	Column        int              `json:"column"`
	Row           int              `json:"row"`
	Board         [Rows][Cols]Cell `json:"board"`
	NextTurn      int              `json:"next_turn"`
	TimeRemaining [2]int64         `json:"time_remaining"` // milliseconds
}

MoveData broadcasts a move to both players

type Node

type Node struct {
	Row       int
	Col       int
	Owner     Cell
	Neighbors [dirCount]*Node
}

Node represents a cell in the board as a graph node

func NewNode

func NewNode(row, col int) *Node

NewNode creates a new empty node at given position

func (*Node) CheckWin

func (n *Node) CheckWin(winLength int) bool

CheckWin checks if placing a token at this node creates a winning sequence

func (*Node) GetNeighbor

func (n *Node) GetNeighbor(dir Direction) *Node

GetNeighbor returns the neighbor in the given direction, or nil if none

func (*Node) IsEmpty

func (n *Node) IsEmpty() bool

IsEmpty checks if the node has no owner

func (*Node) SetNeighbor

func (n *Node) SetNeighbor(dir Direction, neighbor *Node)

SetNeighbor sets the neighbor in the given direction

func (*Node) SetOwner

func (n *Node) SetOwner(player Cell)

SetOwner sets the owner of this node

type PlayData

type PlayData struct {
	Column int `json:"column"`
}

PlayData contains a move request

type Player

type Player struct {
	sync.RWMutex
	ID       PlayerID
	Username string

	Remaining time.Duration
	LastSeen  time.Time
	// contains filtered or unexported fields
}

Player represents a connected player

func NewPlayer

func NewPlayer(username string, initialClock time.Duration) *Player

NewPlayer creates a new player with a unique ID

func (*Player) GetLastSeen

func (p *Player) GetLastSeen() time.Time

GetLastSeen returns the last seen timestamp

func (*Player) IsConnected

func (p *Player) IsConnected() bool

IsConnected checks if the player has an active sender

func (*Player) Send

func (p *Player) Send(msg Message)

Send sends a message to the player if connected

func (*Player) SetSender

func (p *Player) SetSender(s Sender)

SetSender sets the network sender for this player

type PlayerID

type PlayerID string

PlayerID uniquely identifies a player session

type PlayerInfo

type PlayerInfo struct {
	ID        PlayerID `json:"id"`
	Username  string   `json:"username"`
	Connected bool     `json:"connected"`
}

PlayerInfo contains public player information

type QueueUpdateData

type QueueUpdateData struct {
	PlayersInQueue int `json:"players_in_queue"`
}

QueueUpdateData contains matchmaking queue information

type ReplayRequestData

type ReplayRequestData struct {
	PlayerIdx int `json:"player_idx"`
}

ReplayRequestData sent when a player requests replay

type Sender

type Sender interface {
	Send(Message)
}

Sender interface abstracts the network layer

type WelcomeData

type WelcomeData struct {
	PlayerID PlayerID `json:"player_id"`
	Username string   `json:"username"`
}

WelcomeData sent after successful login

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL