
function nDm( n, f )
    return callFM( "nDm", 2, n, f )
end

function max(a, b)
    str = "max(" .. a .. "," .. b .. ")"
    if a > b then
	return a, str
    end
    return b, str
end

function printhash( hash )
    print( "hash = [" )
    for k, v in pairs( hash ) do
	print( "" .. k .. " * " .. v .. ", " )
    end
    print( "]" )
end

function countRoll( n, f )
    local nums = {}
    for i = 1, n do
	local v = nDm( 1, f )
	if nums[v] then
	    nums[v] = 1 + nums[v]
  	else
	    nums[v] = 1
	end
    end
    return nums
end

function countnum( h )
    local ret = 0
    for k,v in pairs( h ) do
	ret = ret + v
    end
    return ret
end

function countsum( h )
    local ret = 0
    for k,v in pairs( h ) do
	ret = ret + k * v
    end
    return ret
end

function countsHash( hash, f, plus )
    local total = 0
    local str = ""
    local isFirst = true
    local spc = ""
    for k,v in pairs( hash ) do
	if isFirst then
	    spc = ""
	    isFirst = false
	else
	    spc = " + "
	end
	if v == 1 then
	    str = str .. spc .. string.format("%d", k)
	elseif v > 1 then
	    str = str .. spc .. string.format("%d * %d", k, v)
	end
	if v > 1 then
	    local t, s = zorotasiRoll( v + plus, f, plus )
	    total = total + t
	    str = str .. " + " .. t .. "[" .. s .. "]"
	end
	total = total + k * v
    end
    return total, str
end

function zorotasiRoll( n, f, plus )
    local hash = countRoll( n, f )
    local t, s = countsHash( hash, f, plus )
    return t, s
end

function forceZorotasiRoll( n, f, plus )
    if n < 2 then return nDm(1,f) end
    local hash = countRoll( n, f )
    local existZoro = false
    local min1 = 0
    local min2 = 0
    for k,v in pairs( hash ) do
	if v > 1 then
	    existZoro = true
	    break
	end
	if k < min1 and v > 0 then
	    min2 = min1
	    min1 = k
	end
    end
    if not existZoro then
	if min2 > 0 then
	    hash[min2] = hash[min2] - 1
	    hash[min1] = hash[min1] + 1
	end
    end
    local t, s = countsHash( hash, f, plus )
    return t, s
end

function httHyperRoll( n )
    return zorotasiRoll( n, 6, 0 )
end

function httBerserkRoll( n )
    return zorotasiRoll( n, 6, 1 )
end
