Skip to content

Commit b6b0e64

Browse files
Add word guess, higher lower, custom instructions and update CI workflow (#14)
* Add copilot instructions for GitHub game development guidelines * Add Higher or Lower and Word Guess games; update CI workflow - Implemented a new Higher or Lower number guessing game. - Added a Word Guess game where players guess GitHub-related terms. - Updated the CI workflow to include linting and formatting checks. - Removed the Whoami command and refactored the root command initialization. - Added tests for the new games and updated existing tests for consistency. - Updated Go module to use Go 1.24 and removed unnecessary seeding in random number generation. * Add tests for edge cases in Word Guess game and enhance game logic validation * Refactor test setup functions to include testing.T parameter for better error handling * Remove unused init function from root command * Remove unnecessary comments about seeding in Go 1.20+ from game files * Remove unnecessary file path comments from wordguess package and test files * Enhance mock prompter implementations across game tests with detailed comments for clarity and maintainability * Refactor PlayGame test comments for clarity and improved understanding of test purpose * Run go fmt
1 parent 8586e17 commit b6b0e64

File tree

19 files changed

+1597
-87
lines changed

19 files changed

+1597
-87
lines changed

.github/copilot-instructions.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# GitHub Game - Copilot Instructions
2+
3+
## Project Overview
4+
This is a GitHub CLI Extension written in Go that allows users to play various games (coin toss, rock paper scissors, tic tac toe) through the GitHub CLI. It's built using Go and the GitHub CLI extension framework, leveraging the Cobra command library for CLI functionality and Charm libraries for terminal UI rendering.
5+
6+
## Code Standards
7+
8+
### Required Before Commit
9+
- All tests must pass: `go test ./...`
10+
- Code must be properly formatted: `go fmt ./...`
11+
- Linting must pass: `golangci-lint run`
12+
- Ensure documentation is up-to-date for any new commands or features
13+
- Verify that any new game implementation follows the established patterns
14+
15+
### Go Patterns
16+
- Follow standard Go idioms and best practices
17+
- Use GoDoc comments for all exported functions, types, and packages:
18+
```go
19+
// FunctionName does something specific
20+
// with these parameters and returns this result
21+
func FunctionName() {}
22+
```
23+
- Error handling should follow Go conventions (return errors rather than using exceptions)
24+
- Use meaningful variable and function names that describe their purpose
25+
- Keep functions small and focused on a single responsibility
26+
- Separate interface definitions from implementations where appropriate
27+
28+
## Development Flow
29+
30+
- Build: `go build`
31+
- Test: `go test ./...`
32+
- Lint: `golangci-lint run`
33+
- Format: `go fmt ./...`
34+
- Run: `gh game <subcommand>` (e.g., `gh game cointoss`)
35+
36+
## Repository Structure
37+
- `/cmd`: Main command implementations and CLI structure
38+
- Command files for each game and core CLI functionality
39+
- `/internal`: Internal packages not intended for external use
40+
- Game logic implementations
41+
- Utility functions
42+
- `/pkg`: Public libraries that could potentially be used by other projects
43+
- `/test`: Test utilities and fixtures
44+
- `main.go`: Entry point for the application
45+
- `README.md`: Project documentation
46+
- `LICENSE`: MIT license file
47+
- `go.mod` & `go.sum`: Go module declarations and dependency tracking
48+
49+
## Key Guidelines
50+
51+
1. **User Experience Focus**:
52+
- Games should be intuitive and easy to play
53+
- Provide clear instructions and feedback to the user
54+
- Handle errors gracefully with helpful messages
55+
56+
2. **Command Structure**:
57+
- New games should be added as subcommands to the main `gh game` command
58+
- Maintain consistency in command structure and naming
59+
60+
3. **Terminal UI**:
61+
- Use the Charm libraries (lipgloss, etc.) for consistent UI rendering
62+
- Ensure games are playable in different terminal environments
63+
- Consider accessibility in UI design (e.g., color contrast)
64+
65+
4. **Testing**:
66+
- Write unit tests for game logic
67+
- Include integration tests for command behavior
68+
- Mock external dependencies when testing
69+
70+
5. **Documentation**:
71+
- Update README when adding new games or features
72+
- Include usage examples for each game
73+
- Document any complex algorithms or design decisions

.github/workflows/ci.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,31 @@ jobs:
1414
build:
1515
runs-on: ubuntu-latest
1616
steps:
17-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
1818

1919
- name: Set up Go
20-
uses: actions/setup-go@v5
20+
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b
2121
with:
2222
go-version: '1.24' # You can change this to your desired Go version
2323

24+
- name: Install golangci-lint
25+
uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd
26+
with:
27+
version: latest
28+
2429
- name: Build
2530
run: go build -v ./...
2631

32+
- name: Lint
33+
run: golangci-lint run
34+
35+
- name: Format Check
36+
run: |
37+
go fmt ./...
38+
if [ -n "$(git diff)" ]; then
39+
echo "Code is not properly formatted. Please run 'go fmt ./...'"
40+
exit 1
41+
fi
42+
2743
- name: Test
2844
run: go test -v ./...

README.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@ gh game cointoss heads # or tails
2020

2121
The game will continue as long as you keep guessing correctly, allowing you to build up a streak. You can quit at any time by selecting "Quit" when prompted for your next guess.
2222

23+
### Higher or Lower
24+
25+
Play a number guessing game where you predict if the next random number will be higher or lower than the current one. See how long you can maintain your streak of correct guesses!
26+
27+
```sh
28+
gh game higherlower
29+
```
30+
31+
Optional flags:
32+
- `--min` or `-m`: Set the minimum possible number (default: 1)
33+
- `--max` or `-M`: Set the maximum possible number (default: 100)
34+
35+
Example with custom range:
36+
```sh
37+
gh game higherlower --min 1 --max 1000
38+
```
39+
2340
### Rock Paper Scissors
2441

2542
Play Rock Paper Scissors against the computer. Best of 3, 5, 7, or 9 rounds.
@@ -43,14 +60,16 @@ gh game tictactoe
4360

4461
The game provides an interactive interface where you can select positions on the board using numbers 1-9, corresponding to the grid positions from left to right, top to bottom.
4562

46-
### Whoami
63+
### Word Guess
4764

48-
Display information about the currently authenticated GitHub user.
65+
Play a word guessing game where you guess a GitHub-related term one letter at a time. Try to reveal the word before running out of guesses!
4966

5067
```sh
51-
gh game whoami
68+
gh game wordguess
5269
```
5370

71+
The game selects a random GitHub-related term, and you need to guess it by suggesting one letter at a time. Each correct letter is revealed in its position. Each incorrect guess reduces your remaining guesses. You win by guessing the complete word before making 6 incorrect guesses.
72+
5473
## Development
5574

5675
### Prerequisites

cmd/higherlower.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
6+
"github.com/chrisreddington/gh-game/internal/higherlower"
7+
userPrompt "github.com/cli/go-gh/v2/pkg/prompter"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var (
12+
minNumber int
13+
maxNumber int
14+
)
15+
16+
var higherLowerCmd = &cobra.Command{
17+
Use: "higherlower",
18+
Short: "Play Higher or Lower",
19+
Long: `Play a Higher or Lower number guessing game.
20+
21+
A number will be shown and you need to guess whether the
22+
next number will be higher or lower than the current number.
23+
24+
The game continues until you make an incorrect guess. How long of a streak
25+
can you get?
26+
27+
Example usage:
28+
gh game higherlower
29+
gh game higherlower --min 1 --max 1000`,
30+
Args: cobra.NoArgs,
31+
Run: func(cmd *cobra.Command, args []string) {
32+
input := userPrompt.New(os.Stdin, os.Stdout, os.Stderr)
33+
higherlower.PlayGame(input, minNumber, maxNumber)
34+
},
35+
}
36+
37+
func init() {
38+
higherLowerCmd.Flags().IntVarP(&minNumber, "min", "m", 1, "Minimum possible number")
39+
higherLowerCmd.Flags().IntVarP(&maxNumber, "max", "M", 100, "Maximum possible number")
40+
41+
rootCmd.AddCommand(higherLowerCmd)
42+
}

cmd/root.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,3 @@ var rootCmd = &cobra.Command{
1313
func Execute() error {
1414
return rootCmd.Execute()
1515
}
16-
17-
func init() {
18-
rootCmd.AddCommand(whoamiCmd)
19-
rootCmd.AddCommand(cointossCmd)
20-
rootCmd.AddCommand(tictactoeCmd)
21-
rootCmd.AddCommand(rockPaperScissorsCmd)
22-
}

cmd/tictactoe.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,7 @@ Choose between two game modes:
9898
}
9999
},
100100
}
101+
102+
func init() {
103+
rootCmd.AddCommand(tictactoeCmd)
104+
}

cmd/whoami.go

Lines changed: 0 additions & 28 deletions
This file was deleted.

cmd/wordguess.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
6+
"github.com/chrisreddington/gh-game/internal/wordguess"
7+
userPrompt "github.com/cli/go-gh/v2/pkg/prompter"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var wordguessCmd = &cobra.Command{
12+
Use: "wordguess",
13+
Short: "Play Word Guess",
14+
Long: `Start a game of Word Guess where you guess a GitHub-related term one letter at a time.
15+
16+
The rules are simple:
17+
1. A random word will be selected
18+
2. Guess one letter at a time
19+
3. If the letter is in the word, it will be revealed
20+
4. If not, you lose one of your available guesses
21+
5. You win by guessing the word before running out of guesses
22+
6. You lose if you make 6 incorrect guesses`,
23+
Run: func(cmd *cobra.Command, args []string) {
24+
input := userPrompt.New(os.Stdin, os.Stdout, os.Stderr)
25+
wordguess.PlayGame(input)
26+
},
27+
}
28+
29+
func init() {
30+
rootCmd.AddCommand(wordguessCmd)
31+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module github.com/chrisreddington/gh-game
22

33
go 1.23.3
4+
45
toolchain go1.24.1
56

67
require (

internal/cointoss/cointoss.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"math/rand"
66
"strings"
7-
"time"
87
)
98

109
// Game represents the state of a coin toss game
@@ -27,7 +26,6 @@ func NewGame() *Game {
2726

2827
// TossCoin is a variable so it can be replaced in tests
2928
var TossCoin = func() string {
30-
rand.Seed(time.Now().UnixNano())
3129
if rand.Float32() < 0.5 {
3230
return "heads"
3331
}
@@ -85,7 +83,7 @@ func PlayGame(p prompter, initialGuess string) {
8583
for keepPlaying {
8684
game.Play(guess)
8785
fmt.Println(game.GetResult())
88-
86+
8987
if game.PlayerGuess == game.Result {
9088
streak++
9189
fmt.Printf("Streak: %d\n", streak)

0 commit comments

Comments
 (0)