EXAMPLES

Palamedes is still in active development. New features are being added nearly every day. So please check the NEWS file for the latest features. Recent changes may not be properly reflected in the examples below. Be patient---This file will be updated to reflect new features and changes between the current alpha stage and the beta testing stage.

Most of the examples in this file are basic. There are also separate files showing advanced usage in applications such as Bayesian belief neworks, analysis of legal evidence, modeling a complicated ancient dice game, linear regression, absorbing Markov chains, and Monte Carlo simulation.

Basic Usage

Prior to showing the examples, it's important to note that Palamedes may be used in two modes:

Dice rolls

Palamedes adheres to the Tim Toady (TMTOWTDI) philosophy. Here are 4 ways to roll one six-sided die:

    d
    d6
    1d6
    choose[1..6]

You can roll three separate six-sided dice to get an array as follows:

    3#d6

You can roll three dice six-sided dice and sum them like so:

    3d6

In OD&D, you generate a new character by rolling 3d6 six times for each of the six abilities (strength, intelligence, wisdim, constitution, dexterity, and charisma) in order and then roll for starting gold by rolling ten times 3d6. Define shorthand to do this as follows:

    SIWCDCh ← 6#3d6
    chargen ← ["str","int","wis","con","dex","cha","gp"] → SIWCDCh⊎[10*3d6]

Notice the use of Unicode symbols. Most commands have a long English name, an ascii symbol and a Unicode symbol. Here is the equivalent English:

    SIWCDCh gets 6#3d6
    chargen gets ["str","int","wis","con","dex","cha","gp"] arrow SIWCDCh concat [10*3d6]

And here is the equivalent ascii:

    SIWCDCh <- 6#3d6
    chargen <- ["str","int","wis","con","dex","cha","gp"] -> SIWCDCh ++ [10*3d6]

Now save a new character named Frobozz and display him in a table:

    set Frobozz = chargen
    table(Frobozz)

In addition to generating random variates, Palamedes can also compute and manipulate entire probability distributions easily. Find the distribution for 3d6:

  p(3d6)

This will output a JSON object representing the distribution. This is highly useful for feeding into subsequent calculations, but not for human readability. To make it readable, apply the table function:

    table(p(3d6))

The problem reading this are digits after the decimal place. After we get the distribution, but before we table it, it would be nice to format the numbers as percentages with 2 digits of precision after the decimal place:

    table(percent(p(3d6)))

This produces the output

keyvalue
3 0.46%
4 1.39%
5 2.78%
6 4.63%
7 6.94%
8 9.72%
911.57%
1012.50%
1112.50%
1211.57%
13 9.72%
14 6.94%
15 4.63%
16 2.78%
17 1.39%
18 0.46%

What if you want no digits after the decimal? percent takes an additional argument for the number of digits after the decimal you want displayed:

    table(percent(p(3d6), 0))

And what if you wanted to see the numbers formatted as rational numbers (fractions)?

    table(rational(p(3d6)))

The rational command may be abbreviated QQ.

But picture is worth a thousand words, so let's picture this distribution:

    barchart(p(3d6))
#%barchart
30.46
3
41.39
4
52.78
5
64.63
6
76.94
7
89.72
8
911.57
9
1012.5
10
1112.5
11
1211.57
12
139.72
13
146.94
14
154.63
15
162.78
16
171.39
17
180.46
18

In the examples above, we've used standard prefix notation for applying functions. There's also a postfix notation, which allows you to write the arguments first and the function last. This improves readability by focusing on what's important first. Here are the last two commands using pipe forward:

    3d6 |> p |> QQ |> table
    3d6 |> p |> barchart

There's also an alternative, Mathematica-inspired postfix notation that I find faster to type:

    3d6//p//QQ//table
    3d6//p//barchart

Calculator

Sums of numbers

Problem: You have a bunch of numbers you need to add up---maybe you need to stack a dozen bonuses, penalties, adjustments and modifiers in D&D 4E?

Solution: Just enter the numbers, separated by spaces, hit enter, and Palamedes will sum them for you. Summation is what Palamedes does by default...

    In[7]  := 5.5 -11 21 50% -2/3 0.666666666666667
    Out[7] := 16

Notice the numbers can be positive or negative; integers, fractions, percentages or decimals.

What's really going on is much deeper though:

    In[8]  := history
    Out[8] :=
    key     value
      ...
      7     base * (base * (base * (base * (base * 5.5 - 11) + 21) + 0.5) - 0.6666666666666666) + 0.666666666666667
    In[9]  := base
    Out[9] := 1

So what Palamedes is really doing is iteratively taking each number (starting from the far right and working to the left) and adding it to the next number multiplied by the base, which is initially set to one. By changing the base, you can convert between number systems...

Convert binary to decimal

Problem: You have a binary number 10010110 and you want to know what it is in decimal.

Solution: Change the base to 2 and then enter the binary digits, separated by spaces, and hit enter:

    In[10]  := base <- 2
    Out[10] := base
    In[11]  := 1 0 0 1 0 1 1 0
    Out[11] := 150

We can see how Palamedes did the calculation by using the history command:

    In[12]  := history
    Out[12] :=
    key     value
    ...
     10     base ← 2
     11     base * (base * (base * (base * (base * (base * (base * 1 + 0) + 0) + 1) + 0) + 1) + 1) + 0

Convert minutes and seconds to seconds

Convert 30 minutes and 30 seconds to seconds. Same trick as before, using base 60:

    In[15]  := base <- 60
    Out[15] := base
    In[16]  := 30 30
    Out[16] := 1830

Sum of Squares

The sum of the squares of 1--10 is 385.

The JavaScript code is [1,2,3,4,5,6,7,8,9,10].map(function(x){return x*x;}).reduce(function(x,y){return x+y;}); using a map-reduce algorithm.

In Palamedes, you could simply write Σ([1..10]^2) --- somewhat shorter and more readable than the JavaScript.

If you really wanted to be verbose, and imitate the JavaScript, you could write: 1--10||>map(_^2)||>reduce(_1+_2). Two dashes -- are a range constructor. The special pipe forward ||> operator pipes a value into the second parameter of a function that takes two arguments. The _^2 is an anonymous function that squares its argument. and the _1+_2 is an anonymous function of two arguments that adds them together.

set versus gets

The set command immediately evaluates the expression on its right and assigns it to the identifier on its left. There are several ways to write set. The first two use English, the next ascii, the last Unicode:

    attack_roll set d20
    set attack_roll = d20
    attack_roll <~ d20
    attack_roll ↜ d20

The gets command assigns the expression on the right to the identifier on the left without performing any evaluation. This is useful for defining functions and synonyms. When you later use the identifier, it will evaluate the expression. To see the unevaluated expression assigned to an identifier, you the define command which may be abbreviated by an apostrophe '

Let's define the "meets or beats" function that tells us the probability of hitting or exceeding a target value. These three definitions are equivalent. The first two use English, the next ascii, the last Unicode:

    mob gets 1 - cdf + p
    let mob = 1 - cdf + p
    mob <- 1 - cdf + p
    mob ← 1 - cdf + p

Now let's review the definition. These two statements are equivalent (English and ascii):

    define mob
    'mob

Now let's see a table of values for mob applied to 3d6:

    tab(mob 3d6)

Note that mob is pre-defined for you and tab is pre-defined as table(percent).

Important: If you generate a random variate, store it in an identifier and compare it to some other values in a conditional, always use set, never use gets. The reason is that gets generates a new variate each time you do a comparison, while set only generates the variate once (what you want in this case):

    result <- {attack_roll <~ d20; if [attack_roll=20, "critical success", attack_roll=1,"critical failure",attack_roll>=target,"hits", otherwise, "miss"]}


AUTHORS BUGS DISCUSSION LICENSE NAME NEWS README SOURCE TODO TRY VERSION

Last update: Fri Sep 23 2016