Skip to content
SorbiersPublic

About

Durak card game trainer: play podkidnoy or perevodnoy against computer opponents that cannot see hidden cards

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Дурак

A trainer for the card game Durak: you against one to three computer players, in the browser. Play it at https://synarteum.com/durak/.

The table in a four-player game: three opponents with portraits, two cards to beat, the discard pile, and the playable cards of the hand picked out

  • Подкидной and переводной, 36 cards, 2 to 4 players.
  • Nine named opponents in two styles of portrait, realistic and caricature, each with a skill rating from one to five stars. Pick one to three of them by face or by strength.
  • Optional portraits that react to the game, remarks in each character's own voice, and reading the remarks aloud.
  • A hint button that shows what the strong player would do in your seat (optional).
  • A Resign button on your turn; it asks once more before giving the game up.
  • Who leads and who defends is written above each opponent's cards, and an arrow on the table (optional) runs from the one to the other.
  • A beaten bout stays on the table until you clear it, so you can commit the cards to memory (or is cleared automatically, as an option). As a memory aid the discard pile can be laid out face up, sorted, for reading.
  • Russian, English and French.

Running it

Needs Node.js 20 or later.

On Windows, double-click serve.bat: it builds the game, serves it locally and opens the browser. Otherwise:

npm install
npm run dev

and open the address it prints. npm run build writes a static site to dist/, which any web server can host; npm run preview serves that build locally.

Is the computer playing fair?

Yes, by construction. A computer player is never handed the game. It is handed an Observation (src/engine/observe.ts): its own hand, the table, the discard pile, the trump card, how many cards everyone holds, and the cards another player was seen to pick up. The order of the deck and the other hands are not in it. In the browser the computer players run in a separate worker, and that observation is the only thing sent across.

What it does with this is what a careful human does: it counts cards. Once the deck is empty in a two-player game, counting tells each side exactly what the other holds, and the strong player then calculates the rest of the game exactly.

tests/fairness.test.ts checks that the observation does not change when the hidden cards are rearranged, and that the strong player's move depends on nothing else.

Rules as implemented

  • Six cards each; the bottom card of the deck shows the trump suit.
  • In the first game with a line-up, the holder of the lowest trump leads and shows that card, so everyone knows where it is. Later games follow one of two customs, chosen in Settings: the winner of the previous game leads (the first player to have got rid of every card), or the player on the fool's right leads at the fool.
  • A lead may be several cards of one rank. Everyone except the defender may throw in cards matching a rank on the table, the main attacker first.
  • At most six attack cards in a bout (five until the first bout has been beaten, optional), and never more open cards than the defender holds.
  • A defender who takes may be given more matching cards before picking up.
  • Переводной: before beating anything, the defender may add a card of the same rank and pass the whole attack to the next player, provided that player holds enough cards to answer it.
  • After a bout the attackers draw first, starting with whoever led; the defender draws last.
  • The last player holding cards is the fool. If the last attack is beaten with the defender's last card, nobody is.

How the strong player works

  • src/ai/heuristic.ts: rule-of-thumb play (shed cheap cards, keep trumps). This is how the one- to three-star players move, and the playout policy for the search.
  • src/ai/search.ts: information-set Monte Carlo tree search. Each iteration deals the unseen cards at random in a way consistent with the observation and plays the game out, so the choice rests on thousands of possible deals instead of one guess.
  • src/ai/endgame.ts: exact solver for two players with an empty deck.

npm run tournament -- 240 5 2 0 3 plays headless matches between ratings; the arguments are games, the rating under test, players, transfer (0 or 1) and the opponents' rating.

Opponents

Stars How they play Fool rate against three stars
1 rules of thumb, a random move about one time in three 73%
2 rules of thumb, a random move about one time in seven 60%
3 rules of thumb, no slips 50% by definition
4 looks ahead, but plays by rule of thumb one time in three 37%
5 looks ahead on every move, solves two-player endgames exactly, and leads one card at a time 18%

The rates are from two-player games of podkidnoy (2000 games for one and two stars, 240 for four and five). Each character has a usual rating, and Boris is the only one who is usually five stars; clicking a star in the roster sets any of them to any strength, and results are tallied separately for each strength. The roster, with names, usual ratings and which picture shows which mood, is src/ui/characters.ts; the remarks are in src/ui/phrases.ts.

Portraits live in public/durak/avatars/<id>/0.webp to 8.webp: nine expressions per character, cut from a three-by-three sheet. To add or replace a character, cut a new sheet the same way and add an entry to the roster.

Russian remarks are spoken from clips in public/durak/voices/, recorded ahead of time by a free speech engine running locally. npm run voices records whatever is missing after lines are added or edited; the casting and setup notes are at the top of scripts/voices.mjs. Two engines are supported:

  • Silero (the default), through the environment set up in the Gogol project, looked for in ../Gogol/app/tts or wherever DURAK_SILERO_DIR points. Five voices, two male and three female, each at one of five pitches. The text is marked up the way Gogol does it: stress from its dictionary, written as a plus sign before the stressed vowel, and punctuation turned into SSML pauses. Words the dictionary cannot settle are ruled on in the script; npm run voices -- --show prints the marked-up lines so the stress can be checked by eye.
  • Piper (--engine piper), installed under tools/, which is not committed. Four voices, three male and one female, told apart by pitch and pace.

English remarks, and any line without a clip, are read by the browser's built-in voices.

Sound follows three rules. Nothing is fetched unless speech is switched on, and then only the clips of the opponents at the table. A clip is played only if it has already arrived. And voices never overlap or queue: while one remark is being spoken, another goes unspoken.

Languages

Russian, English and French, picked from the browser on a first visit and switched from the bar. The interface, the About text and the remarks, shared and each character's own, are in all three. The recorded voices are Russian; the other languages fall back to the browser's speech.

Options

All in Settings. The display options take effect at once.

  • Opponent on a first visit: Lev, at his usual four stars.
  • Portraits: off, still, or reacting to the game (the default), and large (on by default).
  • Opponents make remarks (on by default); speak the remarks aloud (off by default).
  • The next game is led by the winner, or at the fool (the default).
  • Thinking time: quick, normal or deep (the default).

The rest are off unless noted:

  • Show cards you have already seen (a memory aid): the ones picked up into opponents' hands, and the discard pile, which then lies face up and can be looked through by clicking its label. Without it the discard pile stays shut.
  • Clear beaten cards automatically (on). Without it a beaten bout waits for the Clear button.
  • Offer hints.
  • Highlight the cards you can play (on). Without it the hand looks plain and an illegal card is refused with a small shake.
  • Arrow from whoever leads to whoever defends.
  • Mark trump cards with a brass band.

Deploying

The site is https://synarteum.com, served as static files by nginx: the front page of SynArteum at the root and the game in /durak/. deploy.bat (or ./deploy.sh) builds the site, uploads it over SSH and swaps it into /opt/durak/web. The server, key and port come from deploy.env, which is not committed; copy deploy.env.example and fill it in.

deploy/synarteum.conf is only the bootstrap nginx site. The live copy in /etc/nginx/conf.d has since been edited by certbot for HTTPS, and the deploy script leaves it alone, so changes to headers must be made on the server.

The site and search engines

The repository builds two pages. index.html is the front page of SynArteum (a SYNthetic ART musEUM): three halls, of which this game is the first; its code is in src/landing/. durak/index.html is the game, and its pictures and sounds are in public/durak/.

Each of the two is written out at four addresses: its own folder, which picks the language from the browser, and ru/, en/ and fr/ inside it, one language each. Every address has its own title, description and texts in its HTML, names the others as translations, and is listed in sitemap.xml, which the build also writes. The texts and the site's address live in src/seo.ts; vite.config.ts puts them into the pages. public/robots.txt points at the sitemap, and the og-*.jpg files are the pictures shown when a link is shared.

Card pictures

The jacks, queens, kings and aces in public/durak/cards/ are the Russian «атласные» designs drawn by Dmitry Fomin, released into the public domain (CC0) on Wikimedia Commons, cut out of his sheet "Atlasnye playing cards deck.svg". A card is named rank_suit.svg or rank_suit.png, for example king_hearts.svg. Replace a file to change a picture; delete it and the card falls back to a plain drawn face.

Credits

  • Card pictures: the «атласные» jacks, queens, kings and aces by Dmitry Fomin, public domain (CC0), from Wikimedia Commons.
  • Voices: recorded with Silero text-to-speech. Its models carry their own licence, which restricts commercial use; check it before using the clips in public/durak/voices/ for anything commercial.
  • Portraits: generated images of people who do not exist.
  • Fonts: Oranienbaum and Golos Text, under the SIL Open Font License.

Licence

The code is under the MIT licence; see LICENSE. The card pictures and voice clips keep the terms noted under Credits.

Tests

npm test

About

Durak card game trainer: play podkidnoy or perevodnoy against computer opponents that cannot see hidden cards

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages