cowbull

package module
v0.0.0-...-31f7bde Latest Latest
Warning

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

Go to latest
Published: Dec 3, 2016 License: Apache-2.0 Imports: 15 Imported by: 2

README

cowbull

The infamous game cows & bulls

User's guide

Running it

The game consist ot two parts - the game server and the client content. If you want to install and run it, just go get it and start the cowbull process in the root of this repo.

go get github.com/Bo0mer/cowbull
cd $GOPATH/src/github.com/Bo0mer/cowbull
cowbull

The server will be available at http://127.0.0.1:8080/ by default. If you want to fine-tune your settings, this parameters are supported during startup as command-line arguments:

 -address string
    Server address. (default "127.0.0.1:8080")
 -skip-origin-check
    Skip Origin header check upon WebSocket connection negotiation.

Example:

cowbull -address "10.244.0.34:6060"
Playing it

The game has 4 modes - you can play against the computer or a real person, and you can be either a thinker or a guesser.

You select the role of your opponent in the combo-box within the game. If you choose to play against a thinker, you must fill up the number of digits input field. Otherwise, you'll be prompted to think for a number.

ATM, if you start a game with guessers, you will be prompted to enter a list of desired opponent names. The list must be comma separated. Note also that each player will be prompted to guess your number once it's time for his turn. Unfortunately, before the first ask a player won't be notified that she is participating in a game (PRs are welcome:).

Developer's guide

Running the tests

The tests use ginkgo, so you'll need to go get-it.

go get github.com/onsi/ginkgo
cd $GOPATH/src/github.com/Bo0mer/cowbull/
ginkgo -r --race

Or, you can ofcourse use go test

go test ./...

Documentation

Overview

Package cowbull provides means to assemble a cows & bulls online real-time game.

Index

Constants

View Source
const (
	// RoleThinker labels the thinker role.
	RoleThinker = "thinker"
	// RoleGuesser labels the guesser role.
	RoleGuesser = "guesser"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AIGuesser

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

AIGuesser is an artificial intelligence that can guess numbers.

func LocalGuesser

func LocalGuesser(n int) *AIGuesser

LocalGuesser creates new AIGuesser that guesses n-digit numbers.

func (*AIGuesser) Guess

func (g *AIGuesser) Guess(n int) (string, error)

Guess returns a guess number.

func (*AIGuesser) Tell

func (g *AIGuesser) Tell(number string, cows, bulls int) error

Tell tells the resource of a specific guess.

type AIThinker

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

AIThinker is an artificial intelligence that can think of numbers.

func LocalThinker

func LocalThinker(n int) *AIThinker

LocalThinker creates new AIThinker that thinks only of n-digit numbers.

func NewLocalThinker

func NewLocalThinker(n int, perm func(int) []int) *AIThinker

NewLocalThinker creates new AIThinker that thinks only of n-digit numbers. The perm argument specifies a function that generates permutations in the range [0, n). For more info, see the doc of rand.Perm. This method is used for testing. If you're using it, you're doing something wrong or you're trying to be clever. Remember: clear is better than clever.

func (*AIThinker) Think

func (p *AIThinker) Think() (int, error)

Think thinks of a number.

func (*AIThinker) Try

func (p *AIThinker) Try(number string) (int, int, error)

Try returns the cows and bulls for number.

type Client

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

Client is a remote client.

func NewClient

func NewClient(conn Conn, opts ...ClientOption) *Client

NewClient creates a new client based on conn and applies all options to it. After finished using a client, one should call it's Close method.

func (*Client) Close

func (c *Client) Close() error

Close frees all resources allocated by the client. Calling close twice does nothing. If there is action registered for 'disconnect' message, it will be invoked.

func (*Client) ID

func (c *Client) ID() string

ID returns the id of the client.

func (*Client) OnMessage

func (c *Client) OnMessage(name string, action func(data string))

OnMessage registers an action for handling specific messages.

func (*Client) SendMessage

func (c *Client) SendMessage(name, data string) error

SendMessage sends message to the client.

type ClientOption

type ClientOption func(c *Client)

ClientOption configures a client.

func LogTo

func LogTo(log *log.Logger) ClientOption

LogTo configures the logging destination for a client.

func ReadTimeout

func ReadTimeout(d time.Duration) ClientOption

ReadTimeout configures the ReadTimeout for the underlying connection.

func RetryCount

func RetryCount(n int) ClientOption

RetryCount configures the number of attempts when trying to read from a conn. If read fails more than n times, the conn is considered broken. Defaults to 3.

func RetryInterval

func RetryInterval(d time.Duration) ClientOption

RetryInterval configures the interval between consecutive attempts to read from a conn. Defaults to 1 second.

type Conn

type Conn interface {
	// SetReadDeadline sets the read deadline on the underlying
	// network connection.
	SetReadDeadline(t time.Time) error
	// WriteJSON writes the JSON encoding of v to the connection.
	WriteJSON(v interface{}) error
	// ReadJSON reads the next JSON-encoded message from the connection
	// and stores it in the value pointed to by v.
	ReadJSON(v interface{}) error
	// RemoteAddr should return the remote network address.
	RemoteAddr() net.Addr
	// Close should close the
	Close() error
}

Conn represents a client connection.

type GameSettings

type GameSettings struct {
	Role      string   `json:"role"`      // role of the player, either thinker or guesser
	Digits    int      `json:"digits"`    // how many digits should the number have
	AI        bool     `json:"ai"`        // whether the game is versus AI
	Opponents []string `json:"opponents"` // the opponents of the player
}

GameSettings represents settings for a game request to a Hub.

type Gamer

type Gamer interface {
	// Game should create a new game.
	Game(game.Thinker, game.Guesser) (*game.Game, error)
}

Gamer creates games.

type Hub

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

Hub represents a group of players.

func NewHub

func NewHub(gamer Gamer, log *log.Logger) *Hub

NewHub creates a brand new hub.

func (*Hub) Add

func (h *Hub) Add(p Player)

Add adds a player to the hub. Once added, it will get updates by the hub for any significant events.

func (*Hub) NewGame

func (h *Hub) NewGame(from Player, settings GameSettings) (*game.Game, error)

NewGame creates a new Game based on the provided settings.

func (*Hub) Remove

func (h *Hub) Remove(pid string)

Remove removes a player from the hub.

type Messenger

type Messenger interface {
	// ID is the messenger's id.
	ID() string
	// OnMessage registers an action for a message of a kind.
	OnMessage(kind string, action func(data string))
	// SendMessage sends a message of a kind.
	SendMessage(kind string, data string) error
}

Messenger sends, receives and acts on messages.

type MultiGuesser

type MultiGuesser struct {
	Players []Player
	// contains filtered or unexported fields
}

MultiGuesser makes multiple guessers to look like one. Each guesser will be asked to guess in turn.

func (*MultiGuesser) Guess

func (g *MultiGuesser) Guess(n int) (string, error)

Guess will ask the next player for a guess and return it.

func (MultiGuesser) Tell

func (g MultiGuesser) Tell(number string, cows, bulls int) error

Tell tells all players the result of a guess. It returns on the first non-nil error.

type Player

type Player interface {

	// ID returns the player's id. It must be unique.
	ID() string

	// Name returns the player's name.
	Name() string

	// AnnouncePlayers announces all players joined the hub.
	AnnouncePlayers([]PlayerEntry) error

	game.Thinker
	game.Guesser
}

Player represents a hub member.

type PlayerEntry

type PlayerEntry struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

PlayerEntry holds metadata for a player.

type RemotePlayer

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

RemotePlayer is a player that is away and the only way to communicate with it is via messenger.

func NewRemotePlayer

func NewRemotePlayer(m Messenger, waitTimeout time.Duration) *RemotePlayer

NewRemotePlayer creates a player based on a messenger.

func (*RemotePlayer) AnnouncePlayers

func (p *RemotePlayer) AnnouncePlayers(players []PlayerEntry) error

AnnouncePlayers sends message announcing all players specified.

func (*RemotePlayer) Guess

func (p *RemotePlayer) Guess(n int) (string, error)

Guess sends a guess message and returns its response.

func (*RemotePlayer) ID

func (p *RemotePlayer) ID() string

ID returns the remote player's id.

func (*RemotePlayer) Name

func (p *RemotePlayer) Name() string

Name returns the remote player's name. It may be empty.

func (*RemotePlayer) Tell

func (p *RemotePlayer) Tell(number string, cows, bulls int) error

Tell sends a tell message.

func (*RemotePlayer) Think

func (p *RemotePlayer) Think() (int, error)

Think sends a think messages and returns its response.

func (*RemotePlayer) Try

func (p *RemotePlayer) Try(guess string) (int, int, error)

Try sends a try message and returns its response.

type Server

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

Server implements a cowbull game server.

func NewServer

func NewServer(cfg *ServerConfig) *Server

NewServer creates a new server. After once initialized the config object should not be modified.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP serves HTTP requests.

type ServerConfig

type ServerConfig struct {
	// Path to directory from where to serve content.
	StaticFilesPath string

	// Log is used to log messages from the server and its clients.
	Log *log.Logger

	// Upgrader used for upgrading from an HTTP connection to a WebSocket
	// connection.
	Upgrader *websocket.Upgrader

	// Hub for connected players.
	Hub *Hub
}

ServerConfig holds configuration for a server.

Directories

Path Synopsis
cmd
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
gamefakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter

Jump to

Keyboard shortcuts

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