Let's write some card games in Ruby!

Hey all! I have a CardsLib gem I’ve written and I would love to have people design their own card games with it. I’ve got one in the making and I would love to share techniques and designs. Also if you want to contribute to the CardsLib project that would be awesome as well. The README doesn’t contain any documentation yet, but the tests do a pretty good job of showing how everything works.

Currently there’s Deck implementation with shuffling and seeding (for testing purposes). The Deck is an immutable order for protecting the deck throughout usage.

The Card object keeps track of the face, rank, and suit. Also there is an evaluator object for comparing card ranks and checking if the cards are sequential.

These are really big building blocks in getting any card game started. Some default cards are generated whether you want character representation or the actual ASCII art.

We can all learn a lot from each other by exercising or coding experience through this fun outlet of card game design. So lets get programming and sharing. This is fun! And I would love to share that fun with all of you.

5 Likes

If you want to create beautiful looking cards to use then Squib looks like a great Ruby library to use for it.



require 'squib'

light = '#F3EFE3'
dark = '#230602'
Squib::Deck.new(cards: 2, width: 825, height: 1125) do
  background color: dark

  text str: %w( Attack Defend ),
       color: light, font: 'ChunkFive Roman,Sans 72',
       y: '2.5in', width: '2.75in', align: :center

  svg file: %w(attack.svg defend.svg),
      width: 500, height: 500,
      x: 150, y: 250 # icons adapted from game-icons.net

  save_png prefix: 'better_'
end


3 Likes

Lets get the conversation going. What card game do you like and what are the challenges you think you may have in starting to write the game?

Here’s an example of card selection being done with a form’s checkboxes which I made a few years ago. I wrote it with Django with some CSS and JavaScript:

1 Like

I haven’t written a card game before, so finding the right game to get started with would be the challenge…What do you think of blackjack or solitaire? If we have to come up with our own original card game, that would be another challenge…

2 Likes

BlackJack is great! I’ve written a JavaScript version in my blog post: “Vanilla JavaScript – Stepping into the language”. It doesn’t have splitting cards and doubling down though. Solitaire would probably be easier.

There’s also

  • War
  • Kings in the Corner
  • Gin
  • Rummy
  • Poker Stud/Draw
  • Texas Hold’em
  • Memory
  • Slap Jack
  • Spit
  • Pit

Coming up with an original would be more difficult for sure. War would be the easiest game of them all, Memory would probably be second. But Solitaire is a solid choice.

My favorite game I’m working on is called Tonk. :smiley:

Cards game development is the best with TDD! Write the test of what you expect (you don’t have to care about how to design it) and then just make the test pass. Then repeat until done.

2 Likes

I have been thinking about making my own card games. I’ve been riffing on card dueling games, like Magic. I’ve been starting from a simple ruleset, like war, and then tweaking the game play to allow more strategy to be involved. It’s been pretty fun (when I have time for it).

2 Likes

Very interesting! How did your design flow start out?

With my Tonk game I built the deck first, then started with “game should add players”. And from there it’s just been dealing cards, and evaluation.

I’m on a rewrite. The first implementation had no tests at start and didn’t have a separation of concerns. It ended up with code knowing to much about each other part, a mess of state and a flow based method system which couldn’t individually be tested. I couldn’t replicate what the order of cards were for testing and had to step through each part of the game to try and see if changes worked. So that was a mess.

I kept a dozen tests that I had and threw away all of the old code. I created my rewrite in purely test driven fashion using the tests from before as a map to start the project. All Objects keep a pure separation of concerns and are individually testable. The CardsLib library I created allows you to reuse the same shuffled order so you can fully test any scenario.

The CardsLib gem (cards_lib) is meant to be fully customizable. It doesn’t have to be a regular deck of cards, you could (ideally) even create a game like Magic. Although I don’t have experience in that game so I’m not sure how much that entails, I’d love for anyone who would like to participate in the CardsLib project to suggest and improve upon the library.

I’m sure I’ll be writing more than one card game over time. I’d have even more fun working together with someone on projects.

1 Like

I used to be a pretty big magic the gathering geek, I’m still fond of that genre of card games. I’d be interested in taking a shot at that, but there are an insane amount of mechanics to code!

This is a very cool project, as a whole, nice work!

2 Likes

Thanks! Hey @smotchkkiss, want to share a challenge to the mechanics? We can try to solve it here for fun. :yum:

1 Like

I started out by making generic cards out of card stock. Then I would play test ideas with my daughters. I would start with a familiar ruleset, but then I would describe a few rule differences. For example, I might say “We’ll play this game like war, but you can keep 5 cards in your had at a time, and pick which card you want to play from that.” From this, I could see which ideas might work, and which ones were obviously bad.

After that, I could just start coding up some specs and worked from there. I never reached game mechanics as complex as Magic, but that was the basic flow.

2 Likes

I’ve released a big feature in CardsLib!

gem install 'cards_lib'

Now you can check for card sets in a few cards based on some simple rules. Current rules available are :unique, :ordered, :suited, :paired and specs of :min, :max.

Default check is for :unique and :paired. Here’s the source file for Set Verification and see the test examples on usage.

I’ve also added a Macro to convert an Array of string representations of a cards face values into Card instances. For example: CardsLib::Cards["Ah","2h","3h"] returns an Array of Card instances.

2 Likes

Oh! And I just learned how to play 22 at a local poker event! Definitely going to write a game of it as well. Now I have 3 games to write.

2 Likes

I went ahead and wrote Poker hand verification methods https://github.com/danielpclark/CardsLib/blob/master/lib/cards_lib/standard/rules/poker.rb … I’d really like to get some feedback on this gem. It handles Deck/Card building and evaluation. Game logic is left up to the programmers who use the gem.

I apply all the best practices I know to this gem and each feature has had a LOT of thought put into it. Just look at how the Deck works. It’s designed with an immutable deck to draw from or return cards to. You can even seed it to write robust tests and get the same results time after time. Card evaluation is written in a functional way that allows, and is optimized for, lazy evaluation. The set verification I mentioned in the last post is as simple as handing it some cards and the names of the rules to apply.

I’m willing to bet you that there is no other Ruby card game library out there as easy to use, as well thought out, and as simple to understand as mine. Come on, I dare you to use it and review it! :wink:

1 Like

Does it assume 5 card hands only? 2 pairs looks like it wouldn’t work in a hand larger then 5.

What about a low hand rule?

The code is easy to read and I can pretty much follow it without leaving that class. :+1:

I think if I was using this library, I’d wrap these rules in a resolver object that takes the game state (the cards) and returns a result object. Small surface error. Simple interface.

2 Likes

Thank you!!! :smile: Thanks for checking it out and getting back to me. :smile:

It is implemented to check the exact number: eg 2 pair needs 4 cards. I’d written the poker hand verification in an explicit “these exact cards make” kind of way. It was my intention to have the methods checked in order of precedence and return the first rule that matches. But with the current implementation you need to something like “from Texas Hold’em hand of seven cards, does any combination(5) make the hands-rules of 5”. So there’s still work to be done for those who use it.

I’m thinking of writing a “builder state” alternative for poker hands. It will be a way to have cards added one by one and return what cards are towards completing the hand and what cards would complete the hand. I will have to think on this one. But it’s perfect for having statistics in a game of likelihood of winning.

Truthfully I wrote the Poker “Standard Rules” methods for two reasons. One as a publicity feature that will draw in more users, and another as a way to more thoroughly test my library.

It would be very simply to implement this. But I don’t think that is a standard poker rule.

def low_card(cards)
  cards.drop_while{|c|
    # Ace is the current low card in CardsLib
    # But not in Poker value
    c.rank[/\AA/]

  }.sort.shift
end

As far as determining high hand that’s currently left for the dev who uses the gem to implement with their own hand/card comparison.

1 Like

You know that might be a good thing to implement next. A Hand object that will properly be comparable.

1 Like

A jQuery card library for spreading cards: Baraja

And a JavaScript library for flipping cards: FlipCard.js

A 3 part tutorial on CSS and jQuery full deck of cards animations Animating Playing Cards using JQuery and CSS

3 Likes

I wrote a simple card flip animation in pixi.js once: http://kofno.github.io/pixi-dust/flip-png/

I’m thinking about taking this back up, but doing it all in Elm. I’m reminded that I owe my youngest daughter a “Go Fish” game.

3 Likes

Low hand shows up in Omaha

The library I have decided to use for animating cards is KUTE.js

2 Likes