Minimal polymorphic solitaire engine in Go, ebiten

Gilbert Oddstream's Minimal Polymorphic Solitaire 5

There's a live WASM version here.

Towards a polymorphic solitaire engine in Go+Ebiten, with help from fogleman/gg, with game variants run by (user supplied) scripts.

Variants

It will know how to play:

  • Aces and Kings
  • Algerian
  • Alhambra
  • American Toad (also The Toad)
  • Australian
  • Baker's Dozen (also Baker's Dozen Relaxed)
  • Bisley
  • Bristol (also Dover)
  • Canfield (also Acme, Storehouse)
  • Cruel, Ripple Fan
  • Duchess
  • Easy (an easy to win game, for debugging)
  • Fortune's Favor
  • Forty Thieves (also Busy Aces, Fortune's Favor, Forty and Eight, Josephine, Maria, Limited, Lucas, Red and Black)
  • Freecell (also Eight Off, Freecell Easy)
  • Klondike (also Draw One, Draw Three, Batsford, Double Klondike, Gargantua, Thumb and Pouch, Thoughtful)
  • La Belle Lucie (and Trefoil, The Fan)
  • Mistress and Mrs Mop
  • Scorpion, Wasp
  • Simple Simon
  • Spider (also Beetle, Spiderette, Spider One Suit, Spider Two Suits, Will o' the Wisp)
  • Yukon

Some variants have been tried and discarded as being a bit silly:

  • Agnes Sorel
  • Giant
  • King Albert
  • Raglan

(I don't see the point of games that you almost certainly can't win; I like ones that have a 33-66% chance of winnning.)

Some will never make it here because they are just poor games:

  • Accordian
  • Pyramid (or any card matching variant)

Other features

  • Unlimited undo, without penalty. Also, you can restart a deal without penalty.
  • Bookmarking positions (really good for games like Freecell or Simple Simon)
  • Scalable or fixed-size cards
  • Statistics (including percent complete and streaks - streaks are great)
  • Cards spin and flutter when you complete a game, so you feel rewarded and happy
  • Slightly randomized sounds
  • Automatic saving of game in progress
  • A dragable baize; if cards spill out of view to the bottom or right of the screen, just drag the baize to move them into view

Deliberate minimalism

A lot a features have been tried and discarded, in order to keep the game (and player) focused. Weniger aber besser, as Dieter Rams taught us. Design is all about saying "no", as Steve Jobs preached. Just because a feature can be implemented, does not mean it should be.

So taken out were:

  • Reporting if there were no more available moves (that's for you to puzzle over, just like in real life)
  • Reporting the number of moves made (which is arbitary - does turning a card from stock to waste count as one move, or moving a group of cards with power moves turned on count as one move or several?)
  • Movable card highlighting (the more useful a move looks, the more the card gets highlighted)
  • Turn-offable single-tap interface (ie trying to find a home for a tapped card, all this does is either try to move a stack card to the waste, or try to move the card to a foundation)
  • Choice of card sets or card backs

Solitaire is a puzzle game of sorting cards into and between piles into a certain order, and moving those cards to the foundation piles to complete the game.

Configurability is the root of all evil

Every configuration option in a program is a place where the program is too stupid to figure out for itself what the user really wants, and should be considered a failure of both the program and the programmer who implemented it.

Terminology and conventions

  • A PILE of cards

  • A CONFORMANT series of cards in a pile is called a SEQUENCE

  • A set of cards is called a PACK (not 'deck')

  • Suits are listed in alphabetic order: Club, Diamond, Heart, Spade

  • Cards changing between face down and face up is called FLIPPING.

  • The user never moves or flips a face down card, only the dealer can

  • Cards cannot be played from the foundation

  • Cell, Foundation and Waste piles only hold face up cards

  • Stock only has face down cards

  • Tableau and Reserve piles may have face up or down cards

FAQ

What makes this different from the other solitaire implementations?

This solitaire is all about Flow. Anything that distracts from your interaction with the flow of the game has been either been tried and removed or not included. Crucially, the games can be played by single-clicking the card you wish to move, and the software figures out where you want the card to go (mostly to the foundation if possible, and if not, the biggest tableau). If you don't like where the card goes, just try clicking it again or dragging it.

Also, I'm trying to make games authentic, by taking the rules from reputable sources and implementing them exactly.

Why are the graphics so basic?

Anything that distracts from your interaction with the flow of the game, or the ability to scan a deck of cards, has either been tried and removed, or not included. This includes: fancy card designs (front and back), changing the screen/baize background, animating card flips, keeping an arbitrary score, distracting graphics on the screen, and forcing you to drag the cards to move them.

The user interface tries to stick to the Material Design guidelines, and so is minimal and tactile. I looked at a lot of the other solitaire websites out there, and think how distracting some of them are. Features seem to have been added because the developers thought they were cool; they never seem to have stopped to consider that just because they could implement a feature, that they should.

Sometimes the cards are really huge or really tiny

Either resize your browser/desktop window (if using scalable cards) or change the settings to fixed size cards.

The rules for a variation are wrong

There's no ISO or ANSI or FIDE-like governing body for solitaire; so there's no standard set of rules. Other implementations vary in how they interpret each variant. For example, some variants of American Toad build the tableau down by suit, some by alternate color. So, rather than just making this stuff up, I've tried to find a well researched set of rules for each variant and stick to them, leaning heavily on Jan Wolter (RIP, and thanks for all the fish), David Parlett and Thomas Warfield. Where possible, I've implemented the games from the book "The Complete Book of Solitaire and Patience Games" by Albert Morehead and Geoffrey Mott-Smith.

Keyboard shortcuts?

  • U - undo
  • N - new deal (resign current game, if started)
  • R - restart deal
  • S - save current position ('bookmark')
  • L - load/return to a previously saved position
  • C - collect cards to the foundations
  • A - collect all cards to the foundations

What about scores?

Nope, the software doesn't keep an arbitary score. Too confusing. Just the number of moves made, number of wins, and your winning streak (streaks are great). A game isn't counted until you move a card. Thereafter, if you ask for a new deal, that counts as a loss.

You can cheat the score system by restarting a deal and then asking for a new deal.

But you can cheat

You can when playing with actual cards, too. Cheat if you like; I'm not your mother.

What about a timer?

Nope, there isn't one of those. Too stressful. Solitaire is also called patience; it's hard to feel patient when you're pressured by a clock.

What's with the settings?

Fixed cards

With this checked, the size of the cards is fixed, preventing them from scaling.

Otherwise, the size of the cards is changed dynamically so the cards fill the width of the screen. In some variants, this can cause the cards to disappear off the bottom, in which case you can drag the baize, or change the size of the window (if not running on a mobile device).

Power moves

Some variants (eg Freecell or Forty Thieves) only allow you to move one card at a time. Moving several cards between piles requires you to move them, one at a time, via an empty pile or cell. Enabling power moves automates this, allowing multi-card moves between piles. The number of cards you can move is calculated from the number of empty piles and cells (if any).

Mirror baize

Mirrors the card piles on the baize from right to left, because not everyone is right handed, or likes the stock to be on the left of the screen when they are right handed.

Mute sounds

So you can, for example, listen to an audio book while playing.

Is the game rigged?

No. The cards are shuffled randomly using a Fisher-Yates shuffle driven by a Park-Miller pseudo random number generator, which is in itself seeded by a random number. This mechanism was tested and analysed to make sure it produced an even distribution of shuffled cards.

There are 80658175170943878571660636856403766975289505440883277824000000000000 possible deals of a pack of 52 playing cards; you're never going to play the same game twice, nor indeed play the same game that anyone else ever has, or ever will.

Any hints and tips?

  • For games that start with face down cards (like Klondike or Yukon) the priority is to get the face down cards turned over.
  • For games that start with a block of cards in the tableaux and only allow single cards to be moved (like Forty Thieves), the priority is usually to open up some space (create empty tableaux piles) to allow you to juggle cards around.
  • For Forty Thieves-style games, the other priority is to minimize the number of cards in the waste pile.
  • For puzzle-type games (like Freecell, Simple Simon and Mistress Mop), take your time and think ahead.
  • For games with reshuffles (like Cruel and Perseverance) you need to anticipate the effects of the reshuffle.
  • Use undo and bookmark. Undo isn't cheating; it's improvising, adapting and overcoming.

TODO

  • Scripted game variants.
  • Get it working on Android.
  • Get the size of the executable and WASM down.
  • I'd like it to have an inter-user high scores table, but the Google Play games services interface and setup is inpenetrable to me at the moment.
  • Give up and rewrite the whole thing in Defold or C/raylib.

History

First, there was a Javascript version that used SVG graphics and ran in web browsers. Game variants were configured using static lookup tables, which I thought was a good idea at the time.

Second, there was a version in Lua, using the Solar2d game engine, that made it to the Google Play store. Game variants were configured using static lookup tables, which I still thought was a good idea.

Third, there was a version in Go, using the ebiten game engine, with help from gg/fogleman. The design was internally a mess, and the cards didn't scale, so this was abandoned. Game variants were configured using static lookup tables, which was starting to become a source of clumsiness and code smells.

Fourth, there is a version in C that uses the Raylib game engine and uses Lua to script the game variants. The design was good, but has problems with scaling cards.

Fifth, there is this version in Go, using the ebiten game engine, with help from gg/fogleman. The design is way better than the original attempt in Go, and allows the option for scripting games.

Acknowledgements

Original games by Jan Wolter, David Parlett, Paul Alfille, Art Cabral, Albert Morehead, Geoffrey Mott-Smith, Zach Gage and Thomas Warfield.

Sounds by kenney.nl and Victor Vashenko.

Owner
Oddstream
BBC Micro > games programmer > Idealist > Home Office factotum > simple 2D games for fun
Oddstream
Similar Resources

Scalable Distributed Game Server Engine with Hot Swapping in Golang

Scalable Distributed Game Server Engine with Hot Swapping in Golang

GoWorld Scalable Distributed Game Server Engine with Hot Reload in Golang Features Architecture Introduction Get GoWorld Manage GoWorld Servers Demos

Dec 25, 2022

A pure Go game engine

A pure Go game engine

Oak A pure Go game engine Table of Contents Installation Motivation Features Support Quick Start Implementation and Examples Finished Games Installati

Jan 8, 2023

Terminal-based game engine for Go, built on top of Termbox

Terminal-based game engine for Go, built on top of Termbox

Termloop Termloop is a pure Go game engine for the terminal, built on top of the excellent Termbox. It provides a simple render loop for building game

Dec 29, 2022

Tile is a 2D grid engine, built with data and cache friendly ways, includes pathfinding and observers.

Tile is a 2D grid engine, built with data and cache friendly ways, includes pathfinding and observers.

Tile: Data-Oriented 2D Grid Engine This repository contains a 2D tile map engine which is built with data and cache friendly ways. My main goal here i

Dec 26, 2022

A chess engine written in golang

A chess engine written in golang

Weasel Art graciously provided by Alex Table of Contents: About Installing and Compiling from Source Contributing License About Weasel is an 0x88 and

Dec 30, 2022

A 2D ARPG game engine.

A 2D ARPG game engine.

Abyss Engine is an ARPG game engine in the same vein of the 2000's games, and supports playing games similar to Diablo 2. The engine is written in golang and is cross platform. This engine does not ship with game specific files, and will require a game's assets in order to run.

Dec 24, 2022

A small fantasy game engine in WASM using GoLang

A small fantasy game engine in WASM using GoLang

The GoLang Fantasy Engine (GoLF Engine) is a retro game engine. It draws inspiration from fantasy console projects like pico-8, tic-80, and pyxle. Like those projects it is designed to be a retro-feeling game creation/playing tool. Unlike those projects GoLF is more minimal in scope and only provides an API and a small set of tools to help you create your games. Tools like an image editor and code editor are not built in. Despite this minimalism creating games in GoLF is still easy and should still maintain the retro game feel.

Jul 16, 2022

Currently in beta testing. A chess engine written in golang

Currently in beta testing. A chess engine written in golang

Weasel Art graciously provided by Alex Table of Contents: About Installing and Compiling from Source Contributing License About Weasel is an 0x88 and

Dec 30, 2022

golang powered game engine

golang powered game engine

Gobatch Go powered engine that offers features from low level opengl abstraction to UI framework. I created this to separate lot of logic from game am

Nov 13, 2022
Comments
  • Unexpected crash on Linux when screen locks

    Unexpected crash on Linux when screen locks

    gosol exits without saving current game when screen locks under Ubuntu 22.04.1

    Error of failed request: BadRRCrtc (invalid Crtc parameter) Major opcode of failed request: 139 (RANDR) Minor opcode of failed request: 20 (RRGetCrtcInfo) Crtc id in failed request: 0xa2c Serial number of failed request: 507536 Current serial number in output stream: 507536

Helper library to transform TMX tile maps into a simpler format for Ebiten

Ebitmx Ebitmx is a super simple parser to help render TMX maps when using Ebiten for your games. Right now is super limited to XML and CSV data struct

Nov 16, 2022
Tetra3D is a 3D software renderer written in Go and Ebiten and made for games.
Tetra3D is a 3D software renderer written in Go and Ebiten and made for games.

Tetra3D Tetra3D Docs Support If you want to support development, feel free to check out my itch.io / Steam / Patreon. I also have a Discord server her

Dec 20, 2022
A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy!
A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy!

galactic-asteroid-belt Overview A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy! Run To run, you will need Go

Dec 2, 2021
A simple breakout game made in Ebiten
A simple breakout game made in Ebiten

Ebiten Breakout Play online on itch.io A simple breakout game made in Ebiten. This is my first game made with Ebiten - a nice simple engine which allo

Nov 23, 2022
Implementation of a popular graphics benchmark written on Ebiten.
Implementation of a popular graphics benchmark written on Ebiten.

Ebiten Bunny Mark This is an implementation of the popular graphics benchmark written on Ebiten. The initial benchmark was created by Ian Lobb (code)

Dec 7, 2022
Simple 2D-grid game made with Ebiten
Simple 2D-grid game made with Ebiten

Simple 2D-grid game made with Ebiten

Mar 15, 2022
Donburi is just another Entity Component System library for Ebiten inspired by legion.
Donburi is just another Entity Component System library for Ebiten inspired by legion.

Donburi Donburi is just another Entity Component System library for Ebiten inspired by legion. It aims to be a feature rich and high performance ECS L

Dec 15, 2022
Spaceshooter - A port to go of the pygame Space Shooter game using the ebiten library
Spaceshooter - A port to go of the pygame Space Shooter game using the ebiten library

Space Shooter This is a port to go of the pygame Space Shooter (https://github.c

Sep 29, 2022
Engo is an open-source 2D game engine written in Go.

Engo A cross-platform game engine written in Go following an interpretation of the Entity Component System paradigm. Engo is currently compilable for

Dec 26, 2022
Go 3D Game Engine
Go 3D Game Engine

G3N - Go 3D Game Engine G3N (pronounced "gen") is an OpenGL 3D Game Engine written in Go. It can be used to write cross-platform Go applications that

Jan 9, 2023