The Ourania Altar, commonly referred to as ZMI (Zamorak Magical Institute), is one of the most popular Runecrafting training methods in Old School RuneScape (OSRS). Unlike traditional altars, ZMI allows players to craft a random assortment of runes from Pure Essence, providing a faster experience rate than most single-rune altars while requiring less intensity than Lava Runes.
How the ZMI Calculator Works
This tool helps you plan your grind from your current XP to your target Runecrafting level (often level 77 for Blood Runes or 99 for the cape). The calculations account for:
Dynamic XP Rates: At ZMI, the XP you gain per essence scales with your Runecrafting level. This calculator iterates through every level to provide a precise count of essence needed, rather than using a static average.
Essence Type: You can toggle between Pure Essence and Daeyalt Essence. Daeyalt Essence, obtained from the Hallowed Sepulchre or mining in the Daeyalt Essence mine (post-Sins of the Father), grants a 50% XP bonus, drastically reducing the time spent runecrafting.
Inventory Efficiency: Your "Essence Per Trip" depends on your pouches (Small, Medium, Large, Giant, Colossal) and whether you are using the Raiments of the Eye outfit (though the outfit affects rune yield, not base XP). Standard setups with Giant pouches usually carry around 45-55 essence.
Why Choose ZMI?
ZMI is often considered the "middle ground" of Runecrafting. It offers respectable XP rates (ranging from 30k to over 50k XP/hr depending on level and essence type) and is significantly more AFK than Lava Runecrafting. It is safe for Hardcore Ironmen and provides a steady supply of useful runes.
Tips for Efficiency
Ourania Teleport: Use the Lunar Spellbook for the Ourania Teleport to return to the entrance quickly.
Stamina Potions: The run is long; ensure you have a steady supply of stamina potions or use the Ring of Endurance.
Bank Fillers: Fill your bank with placeholders to deposit all runes quickly without banking your pouches or equipment.
// Standard OSRS XP Table logic to get XP for a specific level
function getXpForLevel(level) {
if (level < 1) return 0;
var total = 0;
for (var i = 1; i < level; i++) {
total += Math.floor(i + 300 * Math.pow(2, i / 7));
}
return Math.floor(total / 4);
}
// Reverse lookup: Get level from XP
function getLevelFromXp(xp) {
// Iterate levels 1 to 99 (or 126 virtual)
for (var i = 1; i xp) {
return i;
}
}
return 126;
}
// Format numbers with commas
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function calculateZMI() {
// Get Inputs
var currentXpInput = document.getElementById('currentXp');
var targetLevelInput = document.getElementById('targetLevel');
var essTypeSelect = document.getElementById('essenceType');
var essPerTripInput = document.getElementById('essPerTrip');
var tripsPerHourInput = document.getElementById('tripsPerHour');
var currentXp = parseFloat(currentXpInput.value);
var targetLevel = parseInt(targetLevelInput.value);
var xpMultiplier = parseFloat(essTypeSelect.value);
var essPerTrip = parseFloat(essPerTripInput.value);
var tripsPerHour = parseFloat(tripsPerHourInput.value);
// Validation
if (isNaN(currentXp) || currentXp < 0) {
alert("Please enter a valid current experience amount.");
return;
}
if (isNaN(targetLevel) || targetLevel 126) {
alert("Please enter a valid target level (1-99).");
return;
}
if (isNaN(essPerTrip) || essPerTrip <= 0) {
alert("Please enter a valid amount of essence per trip.");
return;
}
if (isNaN(tripsPerHour) || tripsPerHour = targetXp) {
document.getElementById('results').style.display = 'block';
document.getElementById('resEssence').innerHTML = "0";
document.getElementById('resTrips').innerHTML = "0";
document.getElementById('resHours').innerHTML = "Goal Reached";
document.getElementById('resXpDiff').innerHTML = "0";
return;
}
// Calculation Logic: Iterative approach for accuracy
// ZMI Base XP approx formula: 13 + (Level * 0.35) roughly fits observed rates
// We simulate essence by essence or block by block to account for leveling up
var totalEssenceNeeded = 0;
var tempXp = currentXp;
var xpDiff = targetXp – currentXp;
// Loop until we reach target XP
// To optimize, we calculate essence needed for each level bracket
var currentLvl = getLevelFromXp(tempXp);
while (tempXp < targetXp) {
// Determine end of this level bracket
var nextLvlXp = getXpForLevel(currentLvl + 1);
// Cap at target XP
var segmentTargetXp = (targetXp < nextLvlXp) ? targetXp : nextLvlXp;
var xpToGainInSegment = segmentTargetXp – tempXp;
if (xpToGainInSegment <= 0) {
currentLvl++;
continue;
}
// Calculate XP per Essence at this level
// Formula: Base ~ 13 + (0.35 * level)
// Note: This is an approximation of the randomized rune yield average
var baseXpPerEss = 13 + (currentLvl * 0.35);
var actualXpPerEss = baseXpPerEss * xpMultiplier;
// Calculate essence needed for this segment
var essForSegment = Math.ceil(xpToGainInSegment / actualXpPerEss);
totalEssenceNeeded += essForSegment;
// Advance XP
// We use the calculated essence to add exact XP (or close to it)
// to ensure we cross the threshold correctly
tempXp += essForSegment * actualXpPerEss;
currentLvl++;
}
var totalTrips = Math.ceil(totalEssenceNeeded / essPerTrip);
var totalHours = totalTrips / tripsPerHour;
// Render Results
document.getElementById('results').style.display = 'block';
document.getElementById('resEssence').innerHTML = formatNumber(totalEssenceNeeded);
document.getElementById('resTrips').innerHTML = formatNumber(totalTrips);
document.getElementById('resHours').innerHTML = totalHours.toFixed(2) + " hrs";
document.getElementById('resXpDiff').innerHTML = formatNumber(xpDiff);
}