A functional programming project that implements a finite-state automaton to recognize fighting game combos and moves, inspired by Mortal Kombat's training mode.
- Overview
- Objectives
- Features
- Requirements
- Installation
- Usage
- Grammar File Format
- Project Structure
- Implementation Details
- Examples
ft_ality is a training mode simulator for fighting games that uses finite-state automata to recognize move combinations. The project demonstrates key concepts in formal language theory and compiler design:
- Finite-State Automata (FSA): The core recognition engine
- Regular Languages: Moves are regular languages that can be recognized by FSA
- Tokenization: Breaking down input sequences into recognizable tokens
- Real-time Input Processing: Interactive keyboard/gamepad input handling
Think of it as a sophisticated pattern matcher where combos are "words" made up of button presses as "symbols", and the automaton recognizes valid sequences.
This project teaches fundamental concepts in:
- Formal Grammars and the Chomsky Hierarchy
- Regular Languages (Type 3 languages)
- Finite-State Machines and automaton theory
- Functional Programming principles and best practices
- Syntactic Analysis (parsing) foundations
- Dynamic Automaton Building: Constructs a finite-state automaton from grammar files at runtime
- Real-time Input Recognition: Processes keyboard input and recognizes valid move combinations
- Automatic Key Mapping: Generates key bindings from grammar definitions
- Multiple Move Recognition: Detects when multiple moves share the same input sequence
- Grammar File Support: Flexible grammar file format for defining moves and key mappings
- Graphical Interface: SDL2-based visual display with automaton visualization
- Code Optimization: Tail-recursive functions and efficient memory management
- Functional Programming: Pure functional design with minimal mutations
- Debug Mode: Step-by-step automaton state visualization
- Gamepad Support: Optional joystick/arcade stick input handling
- GHC (Glasgow Haskell Compiler) 8.0 or higher
- SDL2 libraries (for graphical interface)
- SDL2_ttf (for text rendering)
On Ubuntu/Debian:
./haskell_install.shThis script will:
- Install GHCUP in path: .ghcup/
- Make ghcup install the recommanded version of ghc in .ghcup/
To install SDL2 locally, use the provided installation script:
bash sdl2-install.shThis script will:
- Install the latest Cabal
- Download and compile SDL2 from source
- Install SDL2_ttf
- Configure library paths
- Install Haskell SDL2 bindings
makeThis compiles the project with optimizations enabled and creates the ft_ality executable.
make clean # Remove build artifacts
make fclean # Remove build artifacts and binary
make re # Clean rebuild./ft_ality <grammar_file>./ft_ality grammars/mk1.gmr./ft_ality -h # Show help message
./ft_ality --help # Show help messageOnce running, the program will:
- Display the key mappings generated from the grammar
- Open a graphical window (SDL2)
- Wait for keyboard/gamepad input
- Recognize and display matching moves in real-time
Press keys according to the displayed mapping, and when a valid combo is executed, the move name will be displayed!
Grammar files define both key mappings and move rules using a simple text format.
[keymap]
<token> = <key>
...
[/keymap]
[grammar]
<sequence> -> <move_name>
...
[/grammar]
[keymap]
U = w
D = s
F = d
B = a
FP = j
FK = k
BK = l
BP = i
[/keymap]
[grammar]
D, B, [FP] -> Hadouken (Ryu)
D, F, [FP] -> Shoryuken (Ryu)
B, D, B, [FK] -> Tatsumaki (Ryu)
[/grammar]
- Format:
<TOKEN> = <keyboard_key> - Defines the mapping between abstract tokens and physical keyboard keys
<TOKEN>can be any string (commonly: U, D, F, B for Up, Down, Forward, Back)<keyboard_key>are single characters representing keyboard keys
- Format:
<token1>, <token2>, ... -> <move_name> - Defines move sequences using the tokens from the keymap
- Tokens in brackets
[TOKEN]represent actual button presses - Tokens without brackets (U, D, F, B) represent directional inputs
- Move names can include character names in parentheses
ft_ality/
โโโ ft_ality.hs # Main entry point
โโโ Makefile # Build configuration
โโโ sdl2-install.sh # SDL2 installation script
โโโ haskell_install.sh # Haskell installation script
โโโ grammars/ # Grammar files
โ โโโ mk1.gmr # Mortal Kombat 1 moves
โโโ srcs/ # Source modules
โโโ Automaton/
โ โโโ Build.hs # Automaton construction
โ โโโ Run.hs # Automaton runner
โ โโโ Types.hs # Automaton types definitions
โโโ Debug/
โ โโโ Debug.hs # Debug informations
โโโ Parser/
โ โโโ Grammar.hs # Grammar file parsing
โโโ Input/
โ โโโ Keyboard.hs # Input handling
โโโ UI/
โ โโโ Console.hs # Console output
โ โโโ Graphical.hs # SDL2 graphical interface
โโโ Utils/
โ โโโ Types.hs # Type definitions
โ โโโ Helpers.hs # Utility functions
โโโ ...
The automaton is formally defined as a tuple: A = โจQ, ฮฃ, Qโ, F, ฮดโฉ
- ฮฃ (Sigma): The input alphabet (button presses)
- Q: Set of states
- Qโ: Initial/starting state
- F: Set of accepting/recognition states
- ฮด (Delta): Transition function Q ร ฮฃ โ Q
- Grammar Parsing: Reads the grammar file and extracts move definitions
- Automaton Construction: Builds a finite-state machine where:
- Each move creates a path through states
- Shared prefixes reuse states (efficient)
- Terminal states are marked as accepting states with associated move names
- Input Processing:
- Reads keyboard input in real-time
- Follows transitions based on input symbols
- When an accepting state is reached, the move is recognized
- Output: Displays recognized moves through the graphical interface
This project follows functional programming best practices:
- Pure Functions: No side effects except in IO monad
- Immutability: Avoids mutable state (
ref, mutable records, arrays) - Tail Recursion: Recursive functions are tail-call optimized
- Type Safety: Leverages Haskell's strong type system
- Modular Design: Well-organized modules with clear interfaces
- Error Handling: Uses
MaybeandEithertypes instead of exceptions (only one for IO exception at start)
Key mappings:
w -> Up
s -> Down
a -> Back
d -> Forward
j -> [FP]
k -> [FK]
l -> [BK]
i -> [BP]
----------------------
When you press s, a, j in sequence:
[FP]
Hadouken (Ryu) !!
Some combos share prefixes and can recognize multiple moves:
[BP]
Claw Slam (Freddy Krueger) !!
Knockdown (Sonya) !!
Fist of Death (Liu-Kang) !!
"FINISH HIM!" - Mortal Kombat