Skip to content

ADP424/CardGaming

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CardGaming

A Hearthstone-inspired digital card game built with Java/Spring Boot and React/TypeScript.

Prerequisites

  • Docker Desktop
  • Java 21 + Maven 3.9
  • Node.js 20+

Running the full stack with Docker

docker-compose up --build
Service URL
Frontend http://localhost
Backend http://localhost:9000
pgAdmin http://localhost:5050

Subsequent runs (no code changes): docker-compose up.
Tear down: docker-compose down.
Reset database: docker-compose down -v.


Local development

1. Start the database

docker-compose up -d postgres pgadmin

2. Start the backend

cd backend
mvn spring-boot:run

API at http://localhost:8080.

3. Start the frontend

cd frontend
npm install
npm run dev      # http://localhost:5174

Running tests

cd backend
mvn test         # 362 tests

Code formatting

Backend — Google Java Format via Spotless

cd backend
mvn spotless:apply   # reformat
mvn spotless:check   # CI check

Frontend — Prettier

cd frontend
npm run format
npm run format:check

First run

  1. Register an account at /register
  2. Account starts with 150 Lato Coins
  3. Buy packs in the Shop; open them to add cards to your collection
  4. Build a deck in Collection → My Decks
  5. Host or join a game in Play

Game Mechanics

Closely follows Hearthstone's rules:

  • 30-card decks, 30 HP heroes, 7-slot shared board (minions + locations combined)
  • 10 mana crystals max, gaining 1 per turn
  • Mulligan phase: 3 cards first player, 4 + The Coin second
  • Hand limit: 10 cards; deck size: 30

Implemented keywords: Battlecry, Deathrattle, Combo, Choose One, Discover, Overload, Taunt, Divine Shield, Stealth, Charge, Rush, Windfury, Lifesteal, Poisonous, Silence, Freeze, Secrets, Enrage, Spell Damage, Armor

Notable behavior divergences from Hearthstone

  • Buffs persist through zone transitions — a bounced minion keeps its attack/health buffs and damage taken. Aura buffs (Raid Leader, etc.) are stripped on bounce since they depend on board context.
  • Rush vs Charge — Rush minions can only attack other minions on the turn they enter play; they may attack heroes from the next turn onward.
  • Batched death processing — deathrattles fire after all simultaneous deaths are collected, rather than one at a time (simpler and more predictable).
  • Locations share the board with minions in the same 7-slot row.

Project Structure

CardGaming/
├── docker-compose.yml
├── backend/                        Spring Boot 3 + Java 21
│   └── src/main/java/com/cardgame/
│       ├── game/
│       │   ├── action/             Sealed action hierarchy (PlayCard, Attack, DiscoverChoice …)
│       │   ├── card/
│       │   │   ├── base/           Minion, Spell, Weapon, Location, HeroCard, Enchantment …
│       │   │   └── definitions/    Individual card classes (vanilla/, testing/, tokens/)
│       │   ├── discover/           DiscoverPool, DiscoverDestination, PendingDiscover
│       │   ├── engine/             GameEngine, GameState, PlayerState, GameEventBus
│       │   ├── entity/             Hero, GameEntity
│       │   ├── heropower/          Hero power implementations
│       │   ├── targeting/          TargetFilter, TargetFilters factory
│       │   └── util/               MinionCopier
│       ├── dto/game/               DTOs sent to frontend
│       ├── registry/               CardRegistry, PackDefinitionRegistry
│       ├── service/                GameService, ShopService, DeckService, AuthService
│       └── controller/             REST + WebSocket endpoints
└── frontend/src/
    ├── pages/Game/
    │   ├── board/                  GameBoard, BoardRow (minions + locations in one row)
    │   ├── cards/                  CardOnBoard, CardInHand, previews
    │   └── overlays/               ChooseOneModal, DiscoverModal, SecretRevealedToast …
    ├── store/gameSlice.ts          Redux state + animation queue
    ├── types/                      TypeScript DTO types
    └── websocket/                  STOMP client + hooks

Adding a New Card

  1. Create a class in backend/src/main/java/com/cardgame/game/card/definitions/<set>/<type>/ extending Minion, Spell, Weapon, Location, or HeroCard
  2. Call super(definitionId, name, text, manaCost, heroClass, rarity, category, ...)definitionId must be unique (e.g. "MAGE_FIREBALL")
  3. Override only the lifecycle hooks you need: onBattlecry, onDeathrattle, onMinionEnteredPlay, onSpellCast, onTurnEnded, etc.
  4. For engine operations inside a card, use GameEngineHolder.get() — never inject GameEngine directly
  5. Register in CardRegistry: register("MAGE_FIREBALL", Fireball::new)

See CLAUDE.md for full architecture notes, the two-UUID system, Discover usage, board structure, and coding conventions.


Adding a New Expansion

  1. Add a value to CardCategory.java
  2. Register a PackDefinition in PackDefinitionRegistry.java
  3. Tag new cards with that category

About

Hearthstone-style digital card game client.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages