sbuttgereit

sbuttgereit

Small, beginner project idea that might give a little Elixir outreach, too

I was browsing the orange site yesterday and, as happens from time to time, the Jeff Atwood GitHub repo for “BASIC Computer Games” came up as a topic:

“Basic Computer Games (GitHub)”

In this repo, they take the classic 1973 book “101 BASIC Computer Games”, or “BASIC Computer Games” as it was later called, and rewrite those games in different computer languages. Given the relative simplicity of these games, the accessibility of BASIC as a language to define the requirements, and the challenge offered by Jeff Atwood in this repo… it struck me as a fairly interesting and unique way for someone starting with Elixir to get a problem to solve with just a touch more meat than a “hello world” or an overly prescriptive, hand holding tutorial. Also I noticed that nobody had yet contributed any Elixir, Erlang, or Other BEAM language (OK, I didn’t search exhaustively, but I didn’t see any where I looked) versions to the repo; seemed like a low-effort way to get a little more Elixir exposure in the broader world.

Finally, a note about the book, “BASIC Computer Games (Book)”. As I mentioned, it originally published in 1973 and it’s just a collection of 101 games written in the BASIC computer language as collected by David H. Ahl, specifically the flavor of BASIC that shipped with the old DEC minicomputers… think PDP-11. Later editions targeted microcomputer BASICs. The second version of the book was the first computer book to sell over one million copies. For me personally, the book was a substantial part of my introduction to programming… entering the games into my VIC-20 & C-64 and having to convert from the BASIC of the book to the BASIC of my computers… without the internet for help… built in me an understanding of the basics of computing, troubleshooting, and using documentation which I use to this day. I will often continue to use programs from this book as early learning projects when starting a new computer language.

Anyway… just a thought… adopt or ignore at your leisure!

Most Liked

codeanpeace

codeanpeace

Thanks for sharing – took a quick crack at porting the first game Acey Ducey.

Acey Ducey

This is a simulation of the Acey Ducey card game.

In the game, the dealer (the computer) deals two cards face up. You have an option to bet or not to bet depending on whether or not you feel the next card dealt will have a value between the first two.

Your initial money is set to $100; you may want to alter this value if you want to start with more or less than $100. The game keeps going on until you lose all your money or interrupt the program.

The original program author was Bill Palmby of Prairie View, Illinois.

defmodule Game do
  @deck for suit <- [:spades, :hearts, :clubs, :diamonds], value <- 1..13, do: {suit, value}

  defstruct funds: 100, deck: []

  def play(), do: play(%__MODULE__{}) # for convenience

  def play(%__MODULE__{funds: funds}) when funds <= 0, do: IO.puts("~~~ game over ~~~")
  def play(%__MODULE__{deck: deck} = game) when length(deck) < 3, do: play(%{game | deck: Enum.shuffle(@deck)})
  def play(%__MODULE__{deck: deck, funds: funds} = game) do
    IO.gets("<hit enter>\n")

    [first_card, second_card, third_card | remaining_deck] = deck

    IO.puts("~~~ new round ~~~")
    IO.puts("first card: #{format(first_card)}")
    IO.puts("second card: #{format(second_card)}\n")
    IO.puts("funds: $#{funds}")

    bet = prompt_to_place_bet(funds)
    new_funds = if win?(first_card, second_card, third_card), do: funds + bet, else: funds - bet

    IO.puts("\nthird card: #{format(third_card)}")
    IO.puts("funds: $#{funds} => $#{new_funds}")
    IO.puts("~~~ end round ~~~\n")

    play(%{game | deck: remaining_deck, funds: new_funds})
  end

  # re-prompt if invalid integer and/or out of bounds
  defp prompt_to_place_bet(funds) do
    input = IO.gets("place your bet: $")
    case Integer.parse(input) do
      {bet, _} when bet in 0..funds -> bet
      _ -> prompt_to_place_bet(funds)
    end
  end

  # for a stricter win condition (non-inclusive)
  defp win?({_, first}, {_, second}, {_, third}) when third > first and third < second, do: true
  # for a looser win condition (inclusive)
  #defp win?({_, first}, {_, second}, {_, third}) when third in first..second, do: true
  defp win?(_, _, _), do: false

  defp format({suit, value}) do
    case value do
      1 -> "ace of #{suit}"
      11 -> "prince of #{suit}"
      12 -> "queen of #{suit}"
      13 -> "king of #{suit}"
      value -> "#{value} of #{suit}"
    end
  end
end

Game.play() # equivalent to Game.play(%Game{funds: 100, deck: 100})

https://github.com/coding-horror/basic-computer-games/pull/880/files

codeanpeace

codeanpeace

For transparency and posterity’s sake, there’s a bug in win?/3. (╯°□°)╯︵ ┻━┻

The version above depends on the unfortunate and incorrect assumption that the first card’s value is less than that of the second card. The version below uses Enum.sort/1 to not rely on that assumption being true.

  # for a stricter win condition (non-inclusive)
  defp win?({_, first}, {_, second}, {_, third}) do
    [floor, ceiling] = Enum.sort([first, second])
    (floor < third) && (third < ceiling)
  end
  # for a looser win condition (inclusive)
  #defp win?({_, first}, {_, second}, {_, third}) do
    #[_, middle, _] = Enum.sort([first, second, third])
    #middle == third
  #end

Where Next?

Popular in Challenges Top

sukhmeetsd
All in all, from what I understand, it is better not to use GenServer.cast when we want some concurrent operations to happen for sure, be...
New
Aetherus
Finished Day 1 with Elixir :tada: Here’s my code: #!/usr/bin/env elixir defmodule Combination do @doc "Yields each combination of 2...
New
Aetherus
This topic is about Day 4 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
igorb
So… that’s it? Everyone is stuck on part 2? :slight_smile: I looked at Reddit hints and thought I probably wouldn’t have come up with the...
New
Aetherus
Today’s problem is really tense. I don’t think I can do it without libgraph.
New
antoine-duchenet
Everything went smoothly today. Nothing to change to solve part 2 because I already used memoization for part 1 (it looked like an AoC e...
New
rvnash
Anyone have a solution to Part 2 today? Part 1 was straight forward, but I can’t figure out a programatic way to do part 2. I understand ...
New

Other popular topics Top

grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 54006 488
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42533 114
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement