A lighthearted Python package with mini games.
Project description
Golden Eagles - Python game modules
Lightweight, reusable Python game modules built as an installable package.
This repository is in active development for the course package exercise.
Planned Game Modules
- Blackjack: Plays a simple game of blackjack within the terminal given the user and an AI dealer
- Tetris:A terminal-based Tetris module with reusable core logic for board creation, piece spawning, rotation, placement, collision checks, row clearing, and a playable curses-based demo.
- Snake: Grid-based snake movement with growth, food spawning, and collision rules.
- Minefield: Minefield is a puzzle game in which players reveal squares on a grid and use number clues to identify and avoid hidden mines. The objective is to clear all safe squares without triggering a mine.
- Dino Game: Plays the out-of-internet dinosaur game on the terminal with selectable difficulty (speed)
Current Progress
blackjacknearly completed, missing two special functions surrounding split hands and the acecoredefault library containing basic class and functions for simple 2d games to run on the terminalminefieldmodule exists with core functions and a terminal game loop.snakemodule exists with importable core logic, unit tests coverage, and a terminal playable version.tetrismodule exists with importable core logic, row-clearing behavior, pytest coverage, and a terminal playable version.dinoGamemodule imports from core default library and currently only supports windows os
Module Details
Core Library (src/core)
The core library provides a reusable foundation for building terminal-based 2D games.
Overview
Sprite- represents any drawable object (player, obstacle, etc.)Board&ScrollingBoard- manages a 2D grid and renders sprites, andScrollingBoardextendsBoardwith side-scrolling behavior
Sprite
The Sprite class represents an object/actor on the board.
- Stores:
- position -
row,col - shape -
mask - dimensions -
height,width
- position -
- Does not render itself — only holds state
Functions
-
__init__(row, col, mask, fill=" ")
Initialize a sprite with position, shape (mask), and fill character. -
move(direction, steps=1)
Moves the sprite in a given direction (up,down,left,right). -
alter(newMask, startingPoint="topLeft")
Changes the sprite’s shape while preserving alignment based on a reference point (e.g., center, corners). -
stringToMask(s)(static)
Converts a multi-line string into a 2D mask (list of character lists). -
maskToString(mask)(static)
Converts a 2D mask back into a printable string format.
Board
The Board class represents the game environment and handles rendering.
Functions
-
__init__(rows, cols, fill=" ")
Creates a board with given dimensions and default fill character. -
redraw()
Clears the grid and redraws all sprites onto the board. -
setFill(fill)
Updates the default fill character for empty cells. -
reset(clearSprites=False)
Clears the grid and optionally removes all sprites. -
setCell(row, col, val)
Sets a specific cell value (ignores out-of-bounds). -
getCell(row, col)
Returns the value of a specific cell. -
getArea(row, col, height=1, width=1)
Returns a sub-area of the board as a 2D list. -
clearArea(row, col, height=1, width=1)
Clears a region of the board back to the fill value. -
addSprite(sprite, redraw=True)
Adds a sprite to the board and optionally redraws. -
removeSprite(sprite)
Removes a sprite and redraws the board. -
overlay(row, col, mask, fill=" ")
Draws a mask onto the board at a given position. -
spritesCollide(sprite1, sprite2)
Checks if two sprites overlap (ignores transparent cells). -
printBoard(row=0, col=0, height=20, width=50)
Prints a portion of the board to the terminal. -
copy()
Returns a copy of the board grid.
ScrollingBoard
Extends Board to support side-scrolling behavior.
Functions
-
__init__(rows, cols, fill=" ", loadingZone=10)
Initializes a board with an additional off-screen loading zone. -
isOffScreenLeft(sprite)
Checks if a sprite has moved completely off the left side. -
inLoadingZone(sprite)
Checks if a sprite is fully within the right-side loading zone. -
scrollLeft(step=1, exclude=None)
Moves all sprites left and removes off-screen sprites. -
addSpriteToLoadingZone(sprite, offset=0)
Adds a sprite just outside the visible board for later entry.
Dino Game
The Dino Game builds on the core library’s scrolling and sprite-based rendering system.
Instead of moving the player forward, the environment scrolls left, creating an endless runner effect while the dino remains mostly fixed horizontally.
Core Mechanics
-
Jump Behavior (
jump)
Applies an upward velocity to the dino when grounded, followed by gravity each tick to simulate a smooth jump arc. -
Cactus Spawning (
spawnCactus,canSpawnCactus)
Obstacles are spawned randomly in the loading zone.
A minimum gap (minGap) is enforced to prevent overlapping or unfair spawns. -
Collision Detection (
checkCollision)
Uses the core library’s sprite collision system to detect overlap between the dino and cacti.
Ends the game immediately on collision. -
Scrolling Behavior
The board continuously shifts left each tick, moving all sprites except the dino.
Off-screen objects are automatically removed. -
Rendering Priority (
prioritizeDino)
Ensures the dino is always drawn on top of other sprites.
Game Logic
Each tick:
- Handle input (jump)
- Possibly spawn a cactus (with spacing check)
- Scroll the environment left
- Update dino position (velocity + gravity)
- Check for collisions
- Redraw the board and update score
Dino & Cactus Sprites
Dino (Alive)
___
/ o_|
<=/__/>>
⌄ ⌄
Dino (Dead)
___
/ x_|
<=/__/>>
⌄ ⌄
Cactus 1
__
|^^| _
|^^|//
|^^|/
Cactus 2
__
|^ |/
| ^|
Cactus 3
__
\|^ |
| ^|
Cactus 4
__
_ |^^| _
\\|^^|//
\|^^|/
Installation / Setup (Windows PowerShell)
To run the Dino Game, first set the src folder as the Python module path for the current terminal session:
$env:PYTHONPATH = "src"
Running the Game
- To start the game:
python -m src.dinoGame.game
- To start the game with specified difficulty:
python -m src.dinoGame.game [low|high|ramp]
BlackJack
A command-line implementation of the card game Blackjack. Players play against a dealer with blackjack rules like hand splitting, ace value adjustment (1 or 11), and blackjack win conditions or tie conditions.
Documentation
- Card
-
Constructor- Card(suit, number) Creates a standard card with specific checks for attributes is_ace and is_face(J, Q, K)
-
Card.generate_deck()- Static- Returns a generated a full deck of 52 cards with suits and numbers
suits = ["Hearts", "Diamonds", "Clubs", "Spades"]
# remember an Ace is 1 or 11
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
deck = []
for suit in suits:
for num in nums:
card = Card(suit, num)
deck.append(card)
return deck
-
Card.blackjack_value(deck)- Static- Changes deck to turn all face cards to a number value of 10
-
Card.pick_card(deck)- Static- Removed a Card from the deck and returns the Card
-
Card.print_card()- Return a nicely formatted card with suit and number in ASCII
print(ace.print_card())
# Output:
# ┌───────────┐
# │A A│
# │♥ ♥│
# │ │
# │ │
# │ │
# │♥ ♥│
# │A A│
# └───────────┘
Card.print_blank()- Static- Return blank variation
# Output:
# ┌───────────┐
# │ │
# │ │
# │ │
# │ │
# │ │
# │ │
# │ │
# └───────────┘
- Game
-
check_player_total(player_total)- could be improved- Prints player bust if player_total > 21
- Prints player blackjack if player_total == 21
- Returns player_total
-
check_dealer_total(dealer_total)- Prints "Dealer Blackjack!" and returns 21 if dealer_total == 21
- Prints "Dealer Bust. You win!" and returns True if dealer_total > 21
- Returns False otherwise
-
check_dealer_natural(dealer_cards)- Checks if dealer's first 2 cards total 21
- Prints "Dealer has a natural Blackjack" if true
- Returns: bool
-
check_natural_tie(player_total, dealer_cards)- Compares player blackjack with dealer's natural blackjack
- Prints "Tough tie!" or "You win this hand!"
- Returns None
-
check_winner(player_total, dealer_total)- Prints both player and dealer totals
- Returns "Your hand busts. You lose" if player_total > 21
- Returns "Your hand wins!" if player_total > dealer_total
- Returns "Dealer wins!" if player_total < dealer_total
- Returns "A tie is practically a loss" if equal
-
pause()- Prints "Press Enter to continue..."
- Waits for user to press Enter
-
print_dealer_hand(dealer_cards, players_turn=False)- Prints dealer's cards in ASCII art
- If players_turn=True, hides second card with blank
- If players_turn=False, shows all cards
-
print_player_hand(player_cards)- Prints single player hand in ASCII art
- Example:
print_player_hand([Card("Hearts", 5), Card("Clubs", 8)])
-
print_split_hand(player_cards)- Prints multiple split hands with "Playing hand {hand_num}" labels
- Example:
print_split_hand(hands)
-
print_table(player_cards, dealer_cards, players_turn=False)- Master print function, displays dealer + player cards
- Automatically handles single hands (1D) and split hands (2D)
- Example:
print_table(player_cards, dealer_cards, True)
-
change_ace_value(total, cards, is_dealer=False)- Adjusts ace from 1 to 11 if improves hand without busting
- If is_dealer=True, uses dealer rules (must be between 17-21)
- Returns: int (adjusted total)
- Modifies card.num in-place
- Example:
new_total = change_ace_value(11, [ace, ten])
-
change_ace_value_split(hands_totals, hands)- Adjusts aces for multiple split hands
- Modifies hands_totals list in-place
- Example:
change_ace_value_split(hand_totals, player_cards)
-
split_hand(player_cards, deck)- Recursively splits matching pairs into separate hands
- Prompts user "Split the pair or Double Down? (A-split/D-double down)"
- If "A", recursively calls split_hand on each new hand
- If "D", returns [player_cards] without splitting
- Returns: list of hands
- Example:
hands = split_hand([Card("Hearts", 5), Card("Clubs", 5)], deck) hand = [[Card("Hearts", 5), (random picked card)], [Card("Clubs", 5), (random picked card)]]
-
player_hit_stand(player_total, player_cards, deck)- Prompts user "Hit or Stand? (A-hit/D-stand)"
- If "A", draws card from deck, adds to hand, returns new total
- If "D", prints "You stand" and returns same total
- Loops if invalid input
- Returns player_total (updated)
- Example:
new_total = player_hit_stand(13, hand, deck)
-
player_turn(player_cards, dealer_cards, deck)- Calculates initial hand total
- Calls change_ace_value() to adjust aces
- Calls check_player_total() - returns 21 if blackjack
- Loops player_hit_stand(), adjusts aces , checks total
- Returns total if >= 21 or stand
- Returns: int (player_total)
- Example:
total = player_turn(hand, dealer_cards, deck)
-
dealer_hit_stand(dealer_cards, dealer_total, deck)- Single decision: hits if dealer_total < 17, stands if >= 17
- If hits: draws card, prints "Dealer hits", returns new total
- If stands: prints "Dealer stands", returns same total
- Returns: int (updated total)
- Example:
new_total = dealer_hit_stand(dealer_cards, 15, deck)
-
dealer_turn(player_cards, dealer_cards, deck)- Calculates initial dealer total
- Calls change_ace_value() with is_dealer=True
- Loops: calls dealer_hit_stand(), adjusts aces, prints table
- Calls check_dealer_total() - returns None if bust/blackjack
- Ends loop if dealer_total >= 17
- Returns: int (player_total) or None is bust
- Example:
dealer_total = dealer_turn(player_cards, dealer_cards, deck)
Run game
PYTHONPATH=src pipenv run python -m blackjack
Run tests
PYTHONPATH=src pipenv run python -m pytest tests/test_blackjack.py
Minesweeper
The Minesweeper module provides reusable core functions for Minesweeper game logic, this includes board creation, cell revealing, and win-condition checking
Functions
-
create_board(rows, cols, num_mines)Creates an empty grid for the minefield/ -
reveal_board(rows, cols)Creates the player's visible board with all cells hidden -
count_adjacent_mines(board,row,col)Returns the number of mines adjacent to a given cell. -
reveal_cell(board, visible_board, row, col)Reveals a selected cell on the visible board and returns whether the move was safe or not -
check_win(board, visible_board)Returns whether all non-mine cells have been revealed
Run Minesweeper
PYTHONPATH=src pipenv run python -m minefield
Controls
The game displays a grid with row and column numbers. Enter the row and column of the cell you want to reveal.
Example:
0 1 2 3 4 5
0 # # # # # #
1 # # # # # #
2 # # # # # #
3 # # # # # #
4 # # # # # #
5 # # # # # #
Example Input:
2 3
Result: This reveals the cell located at Row 2, Column 3.
Test Minesweeper
PYTHONPATH=src pipenv run pytest tests/test_minefield.py -v
Snake
The Snake module provides reusable core functions for classic Snake game logic and includes a terminal playable version using curses.
Functions
-
create_game_state(width, height, start_length=3, seed=None)
Create the initial snake game state. -
spawn_food(width, height, snake, random_generator)
Pick a random unoccupied board cell for food. -
change_direction(current_direction, requested_direction)
Snake direction change, disallowing immediate reversal. -
tick(state, requested_direction=None)
Advance the game by one tick and returns the next state, checking for out-of-bounds walls, self-collision, and eating food.
Example
from snake.core import create_game_state, tick
state = create_game_state(10, 10, start_length=3)
state = tick(state, requested_direction="UP")
print("Snake:", state["snake"])
print("Food:", state["food"])
print("Score:", state["score"])
print("Game Over:", state["game_over"])
Run Snake
PYTHONPATH=src pipenv run python -m snake
Controls: Arrow Keys = move, Q = quit.
Test Snake
PYTHONPATH=src pipenv run pytest tests/test_snake_core.py -v
Tetris
The Tetris module provides reusable core functions for Tetris-style game logic and includes a terminal playable version using curses.
Functions
-
create_board(rows, cols)
Create an empty Tetris board filled with zeros. -
spawn_piece(piece_type)
Return a copy of a Tetris piece matrix such as"I","O","T","L","J","S", or"Z". -
rotate_piece(piece)
Rotate a piece 90 degrees clockwise. -
is_valid_position(board, piece, row, col)
Check whether a piece can be placed at the given board position. -
place_piece(board, piece, row, col, value=1)
Place a piece on the board and return a new board. -
clear_full_rows(board)
Clear all full rows and return(new_board, cleared_count).
Example
from tetris.core import (
clear_full_rows,
create_board,
is_valid_position,
place_piece,
rotate_piece,
spawn_piece,
)
board = create_board(6, 6)
piece = spawn_piece("T")
rotated_piece = rotate_piece(piece)
if is_valid_position(board, rotated_piece, 0, 2):
board = place_piece(board, rotated_piece, 0, 2)
board, cleared = clear_full_rows(board)
print("Board:", board)
print("Rows cleared:", cleared)
Run Tetris
PYTHONPATH=src pipenv run python -m tetris
Controls: A = left, D = right, S = down, W = rotate, Q = quit.
If the terminal window is too small, the game will display a warning instead of crashing.
Test Tetris
PYTHONPATH=src pipenv run pytest tests/test_tetris.py -v
Example Programs
You can find example Python programs in the examples/ directory that demonstrate each function's operations. Currently available:
Prerequisites
- Install Python (use the version required by this project)
- Install pipenv:
python -m pip install pipenv
Setup
-
Clone the repository:
git clone https://github.com/swe-students-spring2026/3-package-golden-eagles.git cd 3-package-golden-eagles
-
Install dependencies using pipenv:
pipenv install --dev
-
Activate the environment:
pipenv shell -
Run the test suite:
pytest
-
Build the package:
python -m build
Environment Variables & Starter Data
Currently, there are no strict imports or secret .env variables required for the project.
Coming Next
- Add full packaging metadata for publishing to PyPI.
- Add CI workflow to test/build on multiple Python versions.
- Expand examples and function-level documentation for each game.
Team
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file golden_eagles_games-0.1.2.tar.gz.
File metadata
- Download URL: golden_eagles_games-0.1.2.tar.gz
- Upload date:
- Size: 39.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4f44f7bdfe6a82ae09d65db74b810f328fa28e5946a79a56a7e4092aa93c522
|
|
| MD5 |
1ad1b79d93bd894372a7428a196bd86e
|
|
| BLAKE2b-256 |
54f4b42f4e9bd39afaed83c50174a925c12625209a3c669fed979dfd278617e1
|
File details
Details for the file golden_eagles_games-0.1.2-py3-none-any.whl.
File metadata
- Download URL: golden_eagles_games-0.1.2-py3-none-any.whl
- Upload date:
- Size: 39.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fd50b393c9f4fc194f4f53a02ad2036d216debaa656d6d2288b933e53b458ac
|
|
| MD5 |
f492109fc5fa4cf5a7e037faec736124
|
|
| BLAKE2b-256 |
b3ebcb8d7d3395502bb04c353a5cf8cc06daaab6fb84433336d6aa240e2b2d10
|