I wanted a real burraco game, playable right away against the computer, with no sign-up and none of the intrusive ads that clutter most free alternatives online. Here's how I wrote the validation for sets and runs with wildcards, pot and hand-closing logic, and a three-tier AI opponent — all with no framework, no game library, and no build step.
Why burraco, and why from scratch
Burraco is among the most searched card games online in Italy, yet good free options are scarce: many sites require an account just to start, others push straight toward paid multiplayer, others are so full of banners the match becomes unreadable on mobile. I wanted the opposite — open the page, the computer shuffles, you play. Like the other games on my site, it's all vanilla JavaScript: no card library, no engine, just DOM, CSS, and game logic.
The interesting part isn't the interface — cards, animations, layout are mechanical work — but the rules themselves. Burraco has a set of constraints that look simple until you have to turn them into code that must always work, including the edge cases: how many runs can form with two wildcards at the ends, when the pot can be opened, what happens if nobody closes and the deck runs out.
Validating sets and runs, wildcards included
The two valid melds are sets (3+ cards of the same rank) and runs (3+ cards in sequence, same suit). 2s and jokers are wild and can replace any card in either. For a set the rule is straightforward: separate real cards from wilds, check that all real cards share the same rank, and require wilds not to outnumber real cards — otherwise the set would become "mostly wild," which classic rules don't allow.
The run is trickier. I take the real cards of the same suit, compute the span between the lowest and highest rank, and the internal "gaps" left to fill are the difference between the span and the number of real cards. If the available wilds can't cover those gaps, the run is invalid. If wilds are left over after filling internal gaps, they can extend the run past either end — but only if there's "room" toward the ace or the king, since the deck doesn't wrap around.
The case that cost me the most time: a run starting at 9 and ending at king, with one leftover wild. That wild can only extend downward (9→8) because there's no room above the king. If you don't explicitly handle the asymmetry between "room below" and "room above" the span, the validator accepts impossible runs.
The actual "burraco" — the meld that gives the game its name — is a run of at least 7 cards: clean if made of real cards only, dirty if it contains one or more wilds. It's also the condition required to close a hand: without at least one burraco on the table, melding your entire hand isn't enough to win.
The pot: a rule that depends on history, not the present
The pot is a stack of 11 cards that can be taken whole instead of drawing a single card from the deck. To open it, though, a player must have melded at least one set or one clean run — no wilds. This is the rule that forced me to rethink the game state: you can't just look at what's on the table right now, because once the pot is open it stays open even if only dirty melds follow. You need a persistent flag per player — "has already opened" — set once, on the first clean meld, and never recalculated from scratch.
Whoever takes the pot adds all 11 cards to their hand in one move: a huge advantage in terms of possible combinations, but also eleven extra cards to get rid of before closing. Deciding when it's worth taking is one of the most important calls even for a human opponent, which makes it a good lever for tuning how "aggressive" the AI plays.
A three-tier AI, no neural networks
No machine learning: the opponent runs on different heuristics per difficulty, applied at three points in the turn — whether to take the pot, searching for possible melds, and choosing which card to discard.
Easy. Takes the pot only 12% of the times it could, looks exclusively for sets already sitting in hand (no run search at all), attempts a single meld per turn and then stops, and discards a random card — even a wild if it comes up, which is objectively a weak move but realistic for a beginner tier.
Medium. Takes the pot 30% of the time and switches to a greedy loop: looks for sets, then runs, then tries adding cards to melds already on the table, repeating until it finds something to play or hits a safety iteration cap. For the discard, it picks the highest-value non-wild card, to shed the risk of being stuck with heavy cards at the end of the hand.
Hard. Takes the pot 65% of the useful times, runs the same greedy loop as medium but also reuses leftover wilds to extend its own runs toward a burraco (7 cards), and crucially chooses its discard by reading the table: it computes which suits and ranks the human opponent is actually using in their melds, and avoids discarding cards they'd need, keeping wilds as a last resort.
The result is an opponent that, on the same codebase, behaves noticeably differently just by changing a handful of numeric thresholds and adding a couple of targeted heuristics — without the complexity of a real search engine.
Closing a hand, scoring, and what gets saved
A hand ends when a player melds their last card with no discard left, having already made at least one burraco — or in a stalemate if the deck runs out before anyone closes. Scoring sums the value of each player's melded cards and subtracts whatever's left in hand, with dedicated bonuses for clean and dirty burracos. Match history and total score are saved in localStorage: no account, but also no syncing across devices — a choice consistent with the "open and play" goal, worth revisiting only if real multiplayer with a backend becomes necessary.
I'd already used the same installable, zero-dependency PWA approach for Neon Breakout: the nature of the problem changes — real-time physics and collisions on canvas there, discrete rule validation and heuristic AI here — but the underlying philosophy stays the same: a self-contained HTML file, installable as an app, with no build step.
FAQ
How do you validate a run of cards with wildcards in JavaScript?
Separate real cards from wilds, compute the span between the lowest and highest rank of the same suit, and check that internal gaps are covered by the available wilds. Leftover wilds can then extend the run past either end, as long as it stays within the ace-to-king range.
How do you code an AI opponent for a card game like burraco?
No neural networks or exhaustive search needed: different heuristics per difficulty tier, applied to pot-taking probability, a greedy search for possible melds, and discard choice based on what the opponent is using.
Can you play free online burraco without signing up?
Yes: open the page and play right away against the computer, no account needed. Match history and score are saved locally in the browser via localStorage.
How does the pot work in burraco, and why is it the trickiest rule to code?
It opens when a player melds their first set or first clean run, with no wilds. It's tricky because it depends on that player's meld history, not the current table state: you need a persistent flag set only once.
Should you write a card game in vanilla JavaScript or use a framework?
For a card game with a classic HTML/CSS interface and validation logic, a framework adds complexity with no real benefit. It only starts paying off with real-time multiplayer or complex shared state.
You can play the finished game at roversia.it/giochi/burraco.
Top comments (0)