Calculator for magic item creation in RPG I have created a simple calculator that will assist in creating magic items from the tabletop RPG Pathfinder. Here are the full requirements, and if you want a more concise version, here is a player generated summary of the process.

I have been trying to get into F# and functional programming in general. I come from a strong object-oriented background and it has been difficult in ignoring those habits. Please focus on whether or not this is idiomatic F#. I would love to hear if there is a better way to write any of it. And, if you find bug, I'd be happy to know that too.

Questions

A couple of things specifically that I feel could be better would be the DC calculation. I wasn't sure how to approach applying the rush function only if the item was rushed. I also tried finding a place where I could apply functional composition, but I think I needed all the intermediate steps that I stop on.

Code

let baseDC casterLevel =
    5 + casterLevel

let rush dc =
    dc + 5

let ignoreRequirements requirements dc =
    dc + (5 * requirements)

let getBuildPrice basePrice =
    basePrice * 0.5

let getTime basePrice =
    floor (8.0 * basePrice / 1000.0)

let getMinBonusForNoCursed dc =
    dc - 6

let buildDaysWhileAdventuring isRushed buildTime =
    let adventuringBuildTime = buildTime / 4.0
    floor (if isRushed then adventuringBuildTime else adventuringBuildTime * 2.0)

[&lt;EntryPoint&gt;]
let main argv = 
    printfn "%A" argv

    let isRushed = true
    let casterLevel = 1
    let requirementsIgnored = 1

    let basePrice = 5000.0
    let buildPrice = getBuildPrice basePrice

    let buildTime = getTime basePrice
    let daysAdventuring = buildDaysWhileAdventuring isRushed buildTime

    let DC = 
        match isRushed with
        | false -&gt; baseDC casterLevel |&gt; ignoreRequirements requirementsIgnored
        | true -&gt; baseDC casterLevel |&gt; ignoreRequirements requirementsIgnored |&gt; rush

    let minDC = getMinBonusForNoCursed DC

    printfn "Min/DC: %i/%i Cost: %.2f Days/Hours: %.1f/%.1f" minDC DC
        buildPrice daysAdventuring buildTime

    0 // Return code
I see a few problems with this, most notably, you have a plethora of magic numbers.


let baseDC casterLevel =
    5 + casterLevel

let rush dc =
    dc + 5

let ignoreRequirements requirements dc =
    dc + (5 * requirements)

let getBuildPrice basePrice =
    basePrice * 0.5

let getTime basePrice =
    floor (8.0 * basePrice / 1000.0)

let getMinBonusForNoCursed dc =
    dc - 6

let buildDaysWhileAdventuring isRushed buildTime =
    let adventuringBuildTime = buildTime / 4.0
    floor (if isRushed then adventuringBuildTime else adventuringBuildTime * 2.0)



In order, I see:


5 + casterLevel: what is 5?
dc + 5: what is 5? Is it the same as #1?
5 * requirements: what is 5? Is it the same as #1 or #2?
basePrice * 0.5: what is 0.5? Is it 1 / 2 or something different?
8.0 * basePrice: what is 8.0?
#5 / 1000.0: what is 1000.0?
dc - 6: what is 6?
buildTime / 4.0: what is 4.0?
adventuringBuildTime * 2.0: what is 2.0, is it 4.0 / 2, is it the 4.0 from #8 / 2?




For a functional program, it's not too bad. I don't like how many times you use if (I always prefer match), but when dealing with boolean types it does quite fine.