Skip to content

Repository files navigation

UChess

An Android chess app built with Kotlin and Jetpack Compose. Play a local match against a tunable minimax AI, or drop into famous historical games a few plies from the critical position.

Features

  • Three AI levels — Casual, Standard, Expert (minimax search depth 2/3/4 with alpha-beta pruning and quiescence extension).
  • Blitz clocks — toggleable per-side timers with quick presets (1 / 3 / 5 / 10 / 15 / 30 min) and automatic timeout detection.
  • Historical battles — a bundled dataset of famous games (Fischer, Tal, …) replayed to a fork point so you can try to find the winning continuation. Pick a specific battle or leave the selection on Random.
  • Import your own PGN — paste a chess.com or Lichess export into the importer ({[%clk ...]} clock annotations are handled) and the game is saved locally and appears alongside the bundled battles.
  • Local match history — every finished or abandoned match is recorded to a private JSON file and shown on a dedicated History screen with date, time, puzzle name (if any), and result badge (Win / Loss / Draw / Abandoned).
  • Six board themes — Wood, Marble, Green, Midnight, Coral, Mono.
  • Move + haptic feedback — every move fires a sound sample and a matching vibration, chosen so the tactile weight tracks the event's importance (see the table below). The Sound switch in settings mutes the audio channel while keeping haptics on for silent play.
  • Turn-decider coin toss — randomised starting colour with a spinning king animation for non-puzzle games.
  • Abandon-match guard — back gesture and the settings button both prompt before discarding an in-progress match (the abandoned game is still recorded in history).
  • Edge-to-edge dark UI with status- and nav-bar insets respected.

Screenshots

Setup Historical battle Abandon confirmation
Chess Setup screen Tal vs Pasman puzzle Abandon match dialog
Midnight theme Match history Battle picker
Midnight theme gameplay Match history screen Historical battles picker
Import PGN Save confirmation Playing an import
Paste a PGN Saving imported PGN Playing an imported game

Sound and haptic feedback

ChessBoardState.executeMove classifies every applied move into a MoveSound and publishes it on a hot SharedFlow. The game screen collects the flow and hands each event to ChessFeedback, which plays a sample through a pre-loaded SoundPool and triggers a VibrationEffect on the device's default vibrator.

The classifier picks exactly one category per move (terminal state wins, then check, then castle, then promote, then capture, then quiet move):

Event Sample (res/raw/) Haptic pattern
MOVE — quiet move move_self.mp3 One-shot 18 ms, amplitude 80
CAPTURE — taking a piece capture.mp3 One-shot 30 ms, amplitude 160
CASTLE — king-side or queen-side castle.mp3 One-shot 40 ms, amplitude 140
PROMOTE — pawn reaches last rank promote.mp3 EFFECT_CLICK (platform predefined)
CHECK — opponent's king is attacked move_check.mp3 Waveform — two 30 ms pulses at max amplitude
GAME_OVER — checkmate / stalemate / timeout notify.mp3 EFFECT_DOUBLE_CLICK (platform predefined)

The SoundPool is allocated per-composition via rememberChessFeedback() and released through a DisposableEffect so no resources leak when navigating back to setup. Vibration requires the VIBRATE permission (no runtime prompt), declared in the manifest; devices without a vibrator silently skip the haptic half.

Architecture

The chess feature lives under app/src/main/java/com/umain/uchess/chess/ and is split into focused, single-responsibility files:

chess/
├── model/        Domain types — PieceColor, PieceType, GameStatus, Piece,
│                 Position (+ POSITIONS / getPos helper), Move, ImmutableBoard,
│                 ChessPuzzle, GameSettings, ChessScreen,
│                 MatchResult, MatchRecord
├── theme/        Design tokens (ChessPalette) and board colour themes (BoardTheme)
├── pgn/          PgnToFen replay engine (SAN + castling + promotion) and
│                 PgnImporter that parses chess.com / Lichess PGN exports
├── data/         HistoricalBattleLoader (res/raw/historical_battles.json),
│                 MatchHistoryRepository (filesDir/match_history.json),
│                 ImportedGamesRepository (filesDir/imported_games.json)
├── ai/           ChessAI — minimax, piece-square tables, quiescence search
├── state/        ChessBoardState — Compose-observable game state holder
├── feedback/     MoveSound events, ChessSoundPlayer (SoundPool),
│                 ChessHaptics (Vibrator), rememberChessFeedback()
└── ui/           Composables
    ├── ChessApp.kt           Navigation root (Settings ↔ Game ↔ History
    │                         ↔ Battles ↔ Import PGN)
    ├── board/                ChessBoard, ChessSquare
    ├── game/                 ChessGameScreen, PlayerTimer, GameOverDialog,
    │                         TurnDeciderAnimation, AbandonMatchDialog
    ├── history/              MatchHistoryScreen
    ├── battles/              HistoricalBattlesScreen picker, PgnImportScreen
    └── settings/             SettingsScreen

Every public type carries KDoc and every composable has at least one @Preview for inspection in Android Studio.

Requirements

  • Android Studio Narwhal (or newer)
  • JDK 17
  • A device or emulator running Android 13 (API 33) or later.

Build and run

./gradlew assembleDebug           # build
./gradlew installDebug            # install on a connected device

In Android Studio, just press Run ▶ after opening the project.

Credits

The core chess implementation — board rules, minimax AI, PGN replay, and the original single-file Compose UI — is derived from Kyriakos Georgiopoulos's public gist:

https://gist.github.com/Kyriakos-Georgiopoulos/8e7ac7eda4c43f719d9dcc2fdb4176fa

Licensed under the Apache License, Version 2.0. The gist has since been reorganised into the clean-architecture layout above, and extended with edge-to-edge handling, sound/haptic feedback, a local match history, an abandon-match guard, a battle picker, and chess.com / Lichess PGN import.

Full attribution and license text: THIRD_PARTY_NOTICES.md.

License

Apache License 2.0 for the derived chess module. See THIRD_PARTY_NOTICES.md for the upstream copyright notice.

About

An Android chess app built with Kotlin and Jetpack Compose.

Resources

Stars

Watchers

Forks

Contributors

Languages