Triple Fortune
Triple Fortune is a small hobby project made with Python and Pygame.
It is an unofficial homage to the classic German slot machine game “Alles Spitze”. I wanted to recreate the basic feeling of building prize towers, collecting a cashpot, and risking winnings on a ladder while learning more about Python, Pygame, browser builds, controller support, and Batocera.
Triple Fortune is an independent fan project. It is not affiliated with or endorsed by the original developers, manufacturers, publishers, or rights holders of “Alles Spitze”.
Gameplay
Each spin costs EUR 0.10.
The reel contains the following results:
- Ladybug
- Coin
- Clover
- Sun
- Devil
- Nothing
Ladybug, Coin, and Clover increase their matching prize tower by one level.
The Sun increases all three towers.
The Devil resets all towers and removes the current cashpot. Money already stored in the bank is not affected.
Nothing means the reel stops clearly between two symbols. The spin cost is lost, but nothing else happens.
The combined value of all three towers forms the cashpot. The player can collect this cashpot and transfer it to the bank.
Full Towers
Each tower has five levels.
When a tower has already reached its highest level and the matching symbol appears again, the maximum tower value is paid directly into the bank. The tower remains full.
The same rule applies individually to every full tower affected by the Sun.
Risk Ladder
After collecting a cashpot, the player can either continue with the normal game or risk the collected amount on the risk ladder.
The collected amount is rounded down to the nearest available ladder value. Any remaining cents are forfeited.
Example:
Collected amount: EUR 1.50
Risk ladder starting value: EUR 1.20
Remaining EUR 0.30 is forfeited
The ladder values are:
EUR 140.00
EUR 84.00
EUR 52.00
EUR 32.00
EUR 20.00
EUR 12.00
EUR 8.00
EUR 4.00
PAYOUT
EUR 2.40
EUR 1.20
EUR 0.60
EUR 0.30
EUR 0.10
EUR 0.00
Lower ladder
On the lower ladder, each risk attempt can either:
- move one step upward
- lose the complete ladder amount
Winning from EUR 2.40 starts the payout animation. After the animation, the ladder continues from EUR 4.00.
Upper ladder
At EUR 4.00, the possible results are:
- EUR 8.00
- complete loss
From EUR 8.00 onward, a failed risk attempt moves the player one monetary step downward instead of immediately losing everything.
The player can accept the currently active ladder value at any time.
Reaching EUR 140.00 automatically pays the maximum ladder prize into the bank.
Controls
Browser and desktop keyboard
| Action | Key |
|---|---|
| Start game | Space |
| Spin | Space |
| Collect cashpot | Enter |
| Accept ladder value | Enter |
| Start or continue risk ladder | R |
| End current game | Escape |
| Play again after Game Over | Space |
After collecting a cashpot:
- press
Rto enter the risk ladder - press
Spaceto reject the risk ladder and continue playing normally
Batocera controller
The exact button names can vary depending on the controller and Batocera mapping.
The currently tested Batocera layout is:
| Action | Button |
|---|---|
| Start game | B |
| Spin | B |
| Collect cashpot | A |
| Accept ladder value | A |
| Start or continue risk ladder | R |
| End current game | L |
| Play again after Game Over | B |
Playing in a Browser
Requirements
- Python 3
pygame-cepygbag
The tested package versions are listed in requirements.txt.
Install the dependencies:
python -m pip install -r requirements.txt
Build the browser version:
rm -rf build
python -m pygbag --build .
Start a local web server:
python -m http.server 8000 \
--bind 0.0.0.0 \
--directory build/web
Open the local address in a browser:
http://localhost:8000
When using GitHub Codespaces, open the forwarded port for port 8000 instead.
The game initializes audio after the first keyboard or controller input because browsers may block sound before the user interacts with the page.
Playing on Batocera
Triple Fortune includes a native Batocera entry file:
Triple Fortune.pygame
To play on Batocera, download the .zip-File from: https://github.com/DerFerdi/pygame_triple_fortune/releases/tag/v1.0.0
Extract the .zip-File and copy the complete contents of the extracted pygame folder into your rom-structure.
The final structure should look like this:
roms/
└── pygame/
└── Triple Fortune/
├── Triple Fortune.pygame
├── audio.py
├── background.py
├── controller.py
├── game.py
├── graphics.py
├── reel.py
├── risk_graphics.py
├── risk_ladder.py
├── rules.py
├── screens.py
├── settings.py
└── statistics.py
Do not copy only the ZIP file. Batocera needs the extracted files.
Refresh the Batocera game list
After copying the files:
Main Menu
→ Game Settings
→ Update Game Lists
Triple Fortune should then appear in the Pygame system.
Current Features
- three progressive prize towers
- bank and cashpot system
- direct payouts from full towers
- Sun, Devil, and Nothing results
- animated reel with visible gaps
- configurable result probabilities
- risk ladder from EUR 0.10 to EUR 140.00
- payout reveal animation
- keyboard and controller support
- generated sound effects
- resizable browser and desktop display
- native Batocera fullscreen mode
- session statistics and Game Over screen
- Pygbag browser build
- Batocera packaging script
Project Status
Triple Fortune is a personal learning and hobby project, not a commercial gambling product.
The gameplay, probabilities, graphics, sounds, and controller mappings may continue to change during development.
The goal is not to create a perfect reproduction, but to build my own small interpretation of a game concept I remember fondly.
Probabilities and Balancing
All game probabilities can be adjusted in settings.py.
Triple Fortune uses two separate probability systems:
- Reel result weights for the main game
- Success chances for the risk ladder
Main Game Probabilities
The reel uses the RESULT_WEIGHTS dictionary:
RESULT_WEIGHTS = {
"LADYBUG": 4,
"COIN": 6,
"CLOVER": 13,
"SUN": 2,
"DEVIL": 11,
"NOTHING": 64,
}
The numbers are relative weights. Because the current weights add up to 100, they also represent the approximate percentage chance of each result:
| Result | Weight | Approximate Chance |
|---|---|---|
| Ladybug | 4 | 4% |
| Coin | 6 | 6% |
| Clover | 13 | 13% |
| Sun | 2 | 2% |
| Devil | 11 | 11% |
| Nothing | 64 | 64% |
The weights do not need to add up to 100.
For example:
RESULT_WEIGHTS = {
"LADYBUG": 2,
"COIN": 4,
"CLOVER": 8,
"SUN": 1,
"DEVIL": 5,
"NOTHING": 30,
}
These values add up to 50, so a weight of 5 represents a probability of:
5 / 50 = 10%
To make a result more common, increase its weight. To make it less common, decrease its weight.
A weight should remain greater than or equal to zero. Setting a result to 0 prevents it from being selected.
Risk Ladder Probabilities
The risk ladder uses the RISK_SUCCESS_CHANCES dictionary:
RISK_SUCCESS_CHANCES = {
10: 0.90,
30: 0.85,
60: 0.82,
120: 0.80,
240: 0.78,
400: 0.72,
800: 0.65,
1200: 0.38,
2000: 0.34,
3200: 0.30,
5200: 0.27,
8400: 0.24,
}
Each key is the current ladder value in cents. Each decimal is the probability of moving upward.
Examples:
0.90 = 90%
0.65 = 65%
0.38 = 38%
The current ladder chances are:
| Current Value | Upward Chance | Failure Result |
|---|---|---|
| EUR 0.10 | 90% | EUR 0.00 |
| EUR 0.30 | 85% | EUR 0.00 |
| EUR 0.60 | 82% | EUR 0.00 |
| EUR 1.20 | 80% | EUR 0.00 |
| EUR 2.40 | 78% | EUR 0.00 |
| EUR 4.00 | 72% | EUR 0.00 |
| EUR 8.00 | 65% | EUR 4.00 |
| EUR 12.00 | 38% | EUR 8.00 |
| EUR 20.00 | 34% | EUR 12.00 |
| EUR 32.00 | 30% | EUR 20.00 |
| EUR 52.00 | 27% | EUR 32.00 |
| EUR 84.00 | 24% | EUR 52.00 |
The EUR 2.40 success result starts the payout reveal and places the player at EUR 4.00.
The EUR 140.00 step is the maximum and is paid automatically, so it does not require another success probability.
To change a ladder chance, edit the decimal for that value:
RISK_SUCCESS_CHANCES = {
10: 0.60,
30: 0.55,
60: 0.50,
# Other ladder values...
}
Values should normally remain between:
0.0 = 0%
1.0 = 100%
Important Balancing Note
The reel probabilities alone do not determine the complete return to the player.
The final result also depends on:
- when the player collects the cashpot
- which tower levels have been reached
- direct payouts from full towers
- whether the risk ladder is used
- how long the player continues risking
- when a ladder value is accepted
For this reason, changing one probability can have a much larger effect than expected. Large balancing changes should ideally be checked with a simulation over many games.


