Skip to content

Design decisions

Albert Julius Liu edited this page Jun 4, 2023 · 17 revisions

Programming language: Python

To be fair, a big reason Icepool is in Python is simply because I'm familiar with it. However, I do think Python has a lot going for it:

  • Popularity. As of 2022 Python seems to be held by most to be one of the top two most popular programming languages. This has several benefits:
    • Users are more likely to already know the basic syntax.
    • There is a large ecosystem of packages that could be used with Icepool.
    • The core language will continue to be improved in terms of performance and portability.
  • Favorable syntax.
    • The culture favors elegance in syntax.
    • Support for operator overloading.
  • Favorable language features.
    • Integers are arbitrary-precision by default.
    • Standard library provides much utility.
  • No need for compilation.
  • Runnable on the Web via Pyodide without any explicit installation process.

There are some downsides:

  • Performance: Python itself is not known for speed, and going through a browser / WASM adds another factor. However, constant factors are usually less important in this case: while dice problems can get large enough that exponential-time algorithms will take longer than the best constant factors can overcome, they tend to be small enough that low-order polynomial algorithms are good enough even with a poor constant factor.
  • The typing system is not great. Mypy often struggles with inference, and function signatures are not always easy to work with.

Quantity datatype: Exact fractions using BigInts

int64 won't work well because it quickly runs into overflow problems. float64 is fast, especially with math packages such as NumPy. In fact, I used NumPy in early versions of Icepool (then called hdroller). However, the final pool algorithm doesn't actually take advantage of NumPy, so I dropped it. This also has the nice side effect of noticeably decreasing loading time when run through Pyodide. Using exact fractions is more informative, makes debugging easier, and obviates any concerns about precision.

Icecup plotting: Chart.js

At first I was thinking to use Matplotlib for this purpose, which is easy to access via Pyodide. However, there are two problems:

  • Matplotlib takes a long time to load.
  • Matplotlib takes a long time to plot.

So I ended up using Chart.js instead. I considered D3.js, but despite being appropriately named for use in a dice project, I really only needed some simple line and area plots, so I considered it a bit overkill.

Eager versus lazy evaluation

For dice I used eager evaluation, since this is more conventional and makes debugging easier. The one exception are comparators, where it is unknown whether the user wants a boolean result comparing the dice objects, or a die result representing the comparison of the rolls of the dice.

Pools are lazy in the sense that they don't automatically expand to all possible rolls like they do in multiset enumeration algorithms such as those used by Troll and AnyDice. This is essential for efficient pool calculation.

Name and icon

"Icepool" is "dice pool" with the space and first letter removed.

The blue and white come from "ice".

The icon is the face of a d6, but with seven pips:

  • Seven is considered a lucky number.
  • "Icepool" has seven letters.
  • The seven pips are in the pattern of an "I", the first letter of "Icepool".
  • Seven is one higher than can be rolled on a standard d6.
    • This can be read in an aspirational sense: being one pip above the conventionally possible.
    • Or in a satirical sense: a bug in the code produces an implausible result.
  • The standard RPG dice set has seven dice.