An interactive visual novel experience exploring mathematical paradoxes through hand-drawn art, storytelling, and gameplay
Ever wondered why math can feel so contrary to common sense? That's exactly what this project is about! Contrary is a cozy, hand-drawn web experience where mathematical paradoxes come alive through interactive storytelling. Think of it as a visual novel meets math class, but way more fun. I built this with Flask and vanilla JavaScript, drawing every asset myself in MS Paint (or Canva with a MOUSE) to create that warm, sketchbook vibe. Each paradox is its own little adventure with custom artwork, curated music from Kirby and Zelda games (i love those), and sound effects that make every click feel satisfying. Whether you're choosing doors in the Monty Hall problem or watching traffic pile up in Braess's paradox, the goal is simple: make counterintuitive math concepts feel approachable and honestly kind of magical. It's designed to feel like flipping through a friend's notebook full of doodles and discoveries, with handwritten fonts, soft peachy colors, and rounded corners everywhere. No intimidating textbooks here just curious exploration of why our intuition sometimes gets things wonderfully wrong.g.
- Contrary is Live at LINK
- Demo Video: Google Drive Link
- Interactive Paradox Simulations - Five fully playable mathematical paradoxes with visual novel storytelling
- Hand-Drawn Art Style - Custom MS Paint artwork for all UI elements, characters, and environments
- Dynamic Background Music - Curated soundtrack featuring Kirby and Zelda themes for each paradox
- Sound Effects System - Contextual audio feedback for all interactions (door opens, car drives, party horns, etc.)
- Visual Statistics - Real-time graphs and charts that illustrate paradox outcomes and probability distributions
- Responsive Controls - Intuitive button-based interactions with visual feedback
- Audio Settings - Global volume control for music and sound effects with persistent preferences
- Mathematical Explanations - Detailed breakdowns of the logic and math behind each paradox with external references
- Warm Aesthetic Design - Sketchbook-themed UI with lined paper textures and handwriting fonts
Explore the counterintuitive probability that two people in a room share the same birthday. Invite guests to a party, watch as birthdays are revealed, and see the math unfold in real-time statistics.
Features:
- Interactive party room with animated guests
- Dynamic person spawning with birthday generation
- Real-time match detection with visual highlighting
- Statistical probability graphs and calculations
- Confetti celebration effects on matches
Step into the famous game show scenario where switching doors dramatically changes your odds of winning. Play multiple rounds, track your strategy performance, and discover why switching is always better.
Features:
- Animated game show host sprite
- Three-door selection interface with reveal mechanics
- Stay vs. Switch decision system
- Win/loss tracking with aggregate statistics
- Visual probability explanations
Witness how adding a new road to a traffic network can paradoxically increase overall travel time. Simulate traffic flow, add/remove roads, and observe the emergence of Nash equilibrium.
Features:
- Grid-based traffic network visualization
- Animated car sprites with pathfinding
- Road construction/removal mechanics
- Traffic flow simulation with congestion modeling
- Before/after comparison statistics
Experience the classic game theory scenario where cooperation and betrayal lead to different outcomes. Make choices, see consequences, and understand why rational actors might choose suboptimal strategies.
Features:
- Animated prisoner characters with emotional states
- Cooperate vs. Betray decision interface
- Outcome matrix with payoff calculations
- Multi-round gameplay with strategy tracking
- Game theory explanation with Nash equilibrium analysis
Manage two hospitals treating patients with different medications and discover how aggregate statistics can reverse when data is combined. Assign patients, track success rates, and uncover the statistical illusion.
Features:
- Hospital management interface with patient queues
- Mild vs. Severe case classification system
- Treatment A vs. Treatment B comparison
- Auto-run simulation mode for rapid testing
- Detailed success rate breakdowns showing the reversal
Frontend
- HTML5 - Semantic markup structure
- CSS3 - Custom styling with gradient backgrounds and animations
- Vanilla JavaScript - ES6+ for game logic and DOM manipulation
- Canvas API - For dynamic visualizations and particle effects
- Web Audio API - For music and sound effect management
Backend
- Flask (Python 3.8+)
- Jinja2 - Template rendering
Design Assets
- MS Paint - All custom artwork and UI elements
- Hand-drawn Graphics - Buttons, characters, backgrounds, and icons
- JSON Data - Paradox content and configuration storage
Audio
- Music Credits:
- Landing: Kirby Star Allies - Main Menu
- Paradoxes Menu: Kirby's Epic Yarn - Butter Building
- Monty Hall: Sonic Unleashed - Werehog Battle Theme
- Birthday: Kirby Dream Land - Theme Song
- Braess: Zelda - Saria's Song (Lost Woods)
- Prisoner: Zelda BOTW - Kass' Theme
- Simpson: Kirby's Dream Land 3 - Ripple Field 1
- Settings: Zelda OOT - Kaepora Gaebora's Theme
- Sound Effects: Pixabay.com (click, woosh, door-open, car-drive, etc.)
Typography
- Cabin Sketch - Primary handwriting font
- Patrick Hand - Secondary handwriting font
- Architects Daughter - Accent font for playful elements
- Scene Initialization: Each paradox loads its specific HTML template with embedded Canvas elements
- Asset Loading: Preload all images, audio files, and JSON configuration data
- Game Loop: RequestAnimationFrame-based rendering at 60fps for smooth animations
- State Management: JavaScript objects track game state, player decisions, and simulation parameters
- Event Handling: Click/touch events trigger state transitions and visual updates
- Audio Management: Web Audio API handles music playback, crossfading, and sound effect mixing
- Person Generation: Creates random birthdays (1-365) for each new guest
- Collision Detection: Compares each new birthday against existing birthdays in O(n) time
- Probability Calculation: Uses formula
1 - (365!/(365^n * (365-n)!))for theoretical probability - Visual Updates: Renders person sprites on canvas with birthday labels
- Match Highlighting: Applies glow effects to matching birthday pairs
- Statistics Display: Updates real-time graphs showing probability curves
- Setup Phase: Randomly places car behind one of three doors, goats behind others
- Player Selection: Records initial door choice
- Host Reveal: Opens a door with a goat (never the car or player's choice)
- Decision Phase: Presents Stay vs. Switch options
- Outcome Resolution: Reveals chosen door contents, determines win/loss
- Statistics Tracking: Maintains running tallies of Stay/Switch strategies and win rates
- Probability Visualization: Shows 1/3 vs. 2/3 odds with visual diagrams
- Network Initialization: Creates node-based traffic graph with weighted edges
- Pathfinding: Implements Dijkstra's algorithm for shortest path calculation
- Traffic Flow: Spawns car entities with origin/destination pairs
- Congestion Modeling: Increases edge weights based on car density using function
t = tβ(1 + 0.15 * (flow/capacity)) - Road Management: Allows dynamic addition/removal of edges, recalculates paths
- Equilibrium Detection: Monitors until all cars settle into stable routes
- Comparison Analysis: Displays average travel times before/after network changes
- Choice Interface: Presents Cooperate and Betray buttons
- Opponent AI: Uses mixed strategy (random, tit-for-tat, or always defect)
- Payoff Calculation: Applies standard game theory matrix:
- Both Cooperate: 3/3
- Both Betray: 1/1
- One Betrays: 5/0
- Animation System: Shows prisoner emotional states (happy, sad, thinking)
- Round History: Maintains log of choices and outcomes
- Strategy Analysis: Calculates optimal strategies and Nash equilibrium
- Patient Generation: Creates patients with severity classification (mild 70%, severe 30%)
- Treatment Assignment: Routes patients to Treatment A or B at selected hospital
- Success Calculation: Applies differential success rates:
- Large Hospital: Higher volume, lower individual rates
- Small Hospital: Lower volume, higher individual rates
- Data Aggregation: Computes both disaggregated and aggregated success rates
- Reversal Detection: Identifies when aggregate contradicts subgroup trends
- Visual Presentation: Tables and charts show the statistical reversal clearly
Contrary/
βββ static/
β βββ assets/ # Images and visual elements
β β βββ birthday/ # Birthday paradox assets
β β β βββ birthday-cake.png
β β β βββ button-invite.png
β β β βββ button-reset.png
β β β βββ button-start-party.png
β β β βββ confetti.png
β β β βββ party-room-background.png
β β β βββ person-1.png
β β β βββ person-2.png
β β β βββ person-3.png
β β βββ braess/ # Braess paradox assets
β β β βββ button-add-road.png
β β β βββ button-remove-road.png
β β β βββ button-reset.png
β β β βββ button-simulate.png
β β β βββ car-blue.png
β β β βββ car-red.png
β β β βββ car-yellow.png
β β β βββ end-point.png
β β β βββ intersection.png
β β β βββ road-horizontal.png
β β β βββ road-vertical.png
β β β βββ start-point.png
β β β βββ traffic-light.png
β β βββ monty-hall/ # Monty Hall problem assets
β β β βββ button-play.png
β β β βββ button-stay.png
β β β βββ button-switch.png
β β β βββ car.png
β β β βββ dialogue-box.png
β β β βββ door-closed.png
β β β βββ door-open.png
β β β βββ goat.png
β β β βββ host-sprite.png
β β β βββ stage-background.png
β β βββ prisoner/ # Prisoner's dilemma assets
β β β βββ button-betray.png
β β β βββ button-cooperate.png
β β β βββ prisoner-happy.png
β β β βββ prisoner-sad.png
β β β βββ prisoner-thinking.png
β β βββ simpson/ # Simpson's paradox assets
β β β βββ button-assign-patient.png
β β β βββ button-auto-run.png
β β β βββ button-reset.png
β β β βββ button-show-stats.png
β β β βββ button-stop.png
β β β βββ failure-x.png
β β β βββ hospital-large.png
β β β βββ hospital-small.png
β β β βββ mild-case-badge.png
β β β βββ patient-sick.png
β β β βββ patient-treated.png
β β β βββ patient-waiting.png
β β β βββ pill-a-red.png
β β β βββ pill-b-blue.png
β β β βββ severe-case-badge.png
β β β βββ success-checkmark.png
β β βββ paradoxes/ # Paradox selection menu assets
β β β βββ arrow-left.png
β β β βββ arrow-right.png
β β β βββ birthday-art.png
β β β βββ braess-art.png
β β β βββ monty-hall-art.png
β β β βββ play-button.png
β β β βββ prisoner-art.png
β β β βββ simpson-art.png
β β βββ landing/ # Landing page assets
β β β βββ math-divide.png
β β β βββ math-integral.png
β β β βββ math-multiply.png
β β β βββ math-pi.png
β β β βββ math-plus.png
β β β βββ math-sqrt.png
β β β βββ github-logo.png
β β βββ music/ # Background music tracks
β β β βββ landingmusic.mp3
β β β βββ birthday-music.mp3
β β β βββ braess-music.mp3
β β β βββ monty-hall-music.mp3
β β β βββ prisoner-music.mp3
β β β βββ simpson-music.mp3
β β β βββ settings.mp3
β β β βββ journal-music.mp3
β β βββ favicon.ico
β βββ css/ # Stylesheets
β β βββ landing.css # Landing page styles
β β βββ paradoxes.css # Paradox selection menu styles
β β βββ birthday.css # Birthday paradox styles
β β βββ braess.css # Braess paradox styles
β β βββ monty-hall.css # Monty Hall styles
β β βββ prisoner.css # Prisoner's dilemma styles
β β βββ simpson.css # Simpson's paradox styles
β β βββ settings.css # Settings page styles
β β βββ 404.css # 404 error page styles
β βββ js/ # JavaScript modules
β β βββ landing.js # Landing page interactions
β β βββ paradoxes.js # Paradox selection logic
β β βββ birthday.js # Birthday paradox game logic
β β βββ braess.js # Braess traffic simulation
β β βββ monty-hall.js # Monty Hall game mechanics
β β βββ prisoner.js # Prisoner's dilemma AI
β β βββ simpson.js # Simpson's hospital simulation
β β βββ settings.js # Audio/settings management
β β βββ 404.js # 404 page animations
β βββ sfx/ # Sound effects
β β βββ car-drive.mp3
β β βββ car-start.mp3
β β βββ click.mp3
β β βββ confettipop.mp3
β β βββ construction.mp3
β β βββ door-open.mp3
β β βββ goat.mp3
β β βββ horn-short.mp3
β β βββ hospital-ding.mp3
β β βββ lose.mp3
β β βββ page-turn.mp3
β β βββ party-horn.mp3
β β βββ pop.mp3
β β βββ prison-door.mp3
β β βββ sweep.mp3
β β βββ win.mp3
β β βββ woosh.mp3
β βββ paradoxes.json # Paradox data and descriptions
βββ templates/ # HTML templates
β βββ index.html # Landing page
β βββ paradoxes.html # Paradox selection menu
β βββ birthday.html # Birthday paradox page
β βββ braess.html # Braess paradox page
β βββ monty-hall.html # Monty Hall page
β βββ prisoner.html # Prisoner's dilemma page
β βββ simpson.html # Simpson's paradox page
β βββ settings.html # Settings page
β βββ 404.html # 404 error page
βββ app.py # Flask application
βββ requirements.txt # Python dependencies
βββ .gitignore # Git ignore rules
βββ LICENSE # MIT License
βββ README.md # This file
rements.txt # Python dependencies
βββ .gitignore # Git ignore rules
βββ LICENSE # MIT License
βββ README.md # This file
- Python 3.8 or higher (i used 3.13.5)
- pip (Python package manager)
- A Browser
- Clone the repository
git clone https://github.com/Rexaintreal/Contrary.git
cd Contrary- Create virtual environment (not many packages tho still venv might be a good idea!)
python -m venv venv
source venv/bin/activate # for windows only- Install dependencies
pip install -r requirements.txt- Run the application
python app.py- Access the application
Open your browser and navigate to:
http://localhost:5000
Audio Settings (adjustable in-app):
- Music Volume: 0% - 100% (default: 70%)
- Sound Effects Volume: 0% - 100% (default: 80%)
- Settings persist across sessions via localStorage
Landing Page:
- Click "Explore Paradoxes" button to enter the paradox selection menu
- View GitHub repository link in footer
Paradox Selection:
- Use left/right arrow buttons to browse paradoxes
- Click "Play" button to start selected paradox
- Access settings via gear icon
In-Game Controls:
- All interactions are button-based with visual hover effects
- Click game-specific buttons to make choices and advance simulation
- Reset buttons return to initial state for replay
- Back button returns to paradox selection menu
Birthday Paradox:
- Click "Start Party" to initialize the room
- Click "Invite Guest" to add people one at a time
- Watch for matching birthdays (highlighted with confetti)
- Click "Reset" to start over with a new party
Monty Hall:
- Click a door to make your initial choice
- Host reveals a goat behind another door
- Choose "Stay" or "Switch" strategy
- View outcome and updated statistics
- Click "Play Again" for another round
Braess's Paradox:
- Click "Simulate" to start traffic flow
- Observe travel times with current road network
- Click "Add Road" to create the paradoxical shortcut
- Run simulation again and compare results
- Use "Remove Road" and "Reset" to experiment
Prisoner's Dilemma:
- Choose "Cooperate" or "Betray" for your prisoner
- AI opponent makes simultaneous choice
- View outcome and payoff matrix
- Play multiple rounds to explore strategies
- Check statistics to see optimal behavior
Simpson's Paradox:
- Click "Assign Patient" to manually add patients
- Choose hospital (Large/Small) and treatment (A/B)
- Or use "Auto-Run" to simulate many patients quickly
- Click "Show Stats" to reveal the paradox
- Reset and try different assignment patterns
- Landing Page - Kirby Star Allies - Main Menu
- Paradox Menu - Kirby's Epic Yarn - Butter Building
- Monty Hall - Sonic Unleashed - Werehog Battle Theme
- Birthday - Kirby Dream Land - Theme Song
- Braess - Zelda - Saria's Song (Lost Woods)
- Prisoner - Zelda: Breath of the Wild - Kass' Theme
- Simpson - Kirby's Dream Land 3 - Ripple Field 1
- Settings - Zelda: Ocarina of Time - Kaepora Gaebora's Theme
- All sound effects sourced from Pixabay.com
- Cabin Sketch - Google Fonts
- Patrick Hand - Google Fonts
- Architects Daughter - Google Fonts
- All visual assets created by MEEEE using a mouse :>gt;
Birthday Paradox:
Monty Hall Problem:
Braess's Paradox:
Prisoner's Dilemma:
Simpson's Paradox:
- Resonate - Real-time Audio Analysis Toolkit for Musicians
- LeetCohort - Free Competitive Python DSA Practice Platform
- Sorta - Sorting Algorithm Visualizer
- Ziks - Physics Simulator with 21 Simulations
- Eureka - Discover Local Hidden Spots
- DawnDuck - USB HID Automation Tool
- Lynx - OpenCV Image Manipulation WebApp
- Libro Voice - PDF to Audio Converter
- Snippet Vision - YouTube Video Summarizer
- Syna - Social Music App with Spotify
- Apollo - Minimal Music Player
- Notez - Clean Android Notes App
Feel free to submit a pull request
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Saurabh Tiwari
- Portfolio: saurabhcodesawfully.pythonanywhere.com
- Email: [email protected]
- Twitter: @Saurabhcodes01
- Instagram: @saurabhcodesawfully
- GitHub: @Rexaintreal