lib

package
v0.0.0-...-494cba1 Latest Latest
Warning

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

Go to latest
Published: Jan 9, 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")
)

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
	GameCode string
}

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) Send

func (c *Client) Send(msg Message)

Send implements lib.Sender interface

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) IsDiagonal

func (d Direction) IsDiagonal() bool

IsDiagonal checks if direction is diagonal

func (Direction) IsHorizontal

func (d Direction) IsHorizontal() bool

IsHorizontal checks if direction is horizontal (left or right)

func (Direction) IsVertical

func (d Direction) IsVertical() bool

IsVertical checks if direction is vertical (up or down)

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

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) IsFull

func (g *Game) IsFull() bool

IsFull checks if the game has 2 players

func (*Game) Play

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

Play attempts to play a move in the given column

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
)

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
	// 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) 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