### Initial UI Setup Source: https://github.com/highdiceroller/icepool/blob/main/apps/year_zero_engine.html Performs the initial setup by updating rolls, the chart, and the search query when the page loads. ```javascript updateRolls(); updateChart(); updateSearchQueryFromForms(); ``` -------------------------------- ### Initialize Pyodide and Icepool Source: https://github.com/highdiceroller/icepool/blob/main/apps/cortex_prime.html Loads Pyodide and installs the icepool library. This is the initial setup for running Python code in the browser. ```javascript setLoadingText('Loading pyodide') let pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/", }); await pyodide.loadPackage([ "micropip" ], {messageCallback : setLoadingText}); setLoadingText('Loading icepool') await pyodide.runPythonAsync( ` import micropip await micropip.install('icepool==1.6.0') import js import pyodide import icepool from bisect import bisect_left from icepool import Die, MultisetEvaluator, Order, Pool, highest, coin, multiset_function from functools import cache possible_die_sizes = [4, 6, 8, 10, 12] zero_die = Die([0]) class CortexEvaluator(MultisetEvaluator): def __init__(self, drop_lowest, keep, target_effect): # drop_lowest doesn't include the effect die # it may be negative, will be rectified at start self._drop_lowest = drop_lowest self._keep = keep self._target_effect = target_ef` ); ``` -------------------------------- ### Install Icepool Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/ironsworn.ipynb Install the icepool library using pip. This is a prerequisite for using the library's functionalities. ```python %pip install icepool ``` -------------------------------- ### Install and Import icepool Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/isaksen2016.ipynb Installs the icepool library and imports necessary modules for dice game calculations. ```python %pip install icepool import icepool from math import sqrt import time start_ns = time.perf_counter_ns() ``` -------------------------------- ### Install and Import Icepool Libraries Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/l5r.ipynb Installs necessary libraries (ipywidgets, icepool) using piplite and imports icepool and time for performance measurement. This is for environments like JupyterLite. ```Python import piplite await piplite.install("ipywidgets") await piplite.install("icepool") import icepool import time ``` -------------------------------- ### Install Icepool in JupyterLite REPL Source: https://github.com/highdiceroller/icepool/blob/main/index.html Example code to install the icepool package within a JupyterLite REPL environment. This is useful for interactive exploration of the library. ```python import piplite await piplite.install("icepool") import icepool ``` -------------------------------- ### Initialize Pyodide and Load Icepool Source: https://github.com/highdiceroller/icepool/blob/main/apps/year_zero_engine.html Sets up Pyodide, loads the micropip package, and installs the icepool library. This is the initial step for running Python code in the browser. ```javascript async function initPyodide() { setLoadingText('Loading pyodide') let pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/", }); await pyodide.loadPackage(["micropip"], {messageCallback : setLoadingText}); setLoadingText('Loading icepool') await pyodide.runPythonAsync( ` import micropip await micropip.install('icepool==1.6.0') import js import pyodide import icepool from functools import cache possible_die_sizes = [6, 8, 10, 12] ` ); } ``` -------------------------------- ### Initialize Pyodide and Load Icepool Source: https://github.com/highdiceroller/icepool/blob/main/apps/ability_scores.html Loads Pyodide, installs the 'icepool' package, and runs initial Python code. Uses 'setLoadingText' for progress updates. ```javascript async function initPyodide() { setLoadingText('Loading pyodide') let pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/", }); await pyodide.loadPackage({"micropip"}, {messageCallback : setLoadingText} ); setLoadingText('Loading icepool') await pyodide.runPythonAsync( ` import micropip await micropip.install('icepool==1.6.0') import js import pyodide import math import icepool from icepool import d4, d6, d8, d10, d12, d20 def set_rank_data(index, die): selected_dist = js.document.getElementById('rankDistSelect').value if selected_dist == 'pmf': data = [die.probability(x, percent=True) for x in range(1, 21)] else: data = [die.probability('>=', x, percent=True) for x in range(1, 21)] for i in range(1, min_ability): data[i - 1] = math.nan for i in range(max_ability + 1, 21): data[i - 1] = math.nan js.rankChart.data.datasets[index].data = pyodide.ffi.to_js(data) table_text = '%s%0.2f' % (js.rankLabels[index], die.mean()) table_text += ''.join(('' if math.isnan(x) else '%0.2f%%' % x) for x in data) js.document.getElementById('rankTableRow%d' % index).innerHTML = table_text class RankWithRestart(icepool.MultisetEvaluator): def __init__(self, rank, restart_count, restart_value): self._rank = rank self._restart_count = restart_count self._restart_value = restart_value def next_state(self, state, outcome, count): total_count, trigger, result = state or (0, 0, None) total_count += count if total_count < self._restart_count and outcome <= self._restart_value: return icepool.Reroll if total_count > self._rank and result is None: result = outcome return total_count, trigger, result def final_outcome(self, final_state): return final_state[-1] def order(self): return icepool.Order.Descending def extra_outcomes(self, outcomes): return range(1, 21) class SumWithRestart(icepool.MultisetEvaluator): def __init__(self, cost_map, restart_count, restart_value): self._cost_map = cost_map self._restart_count = restart_count self._restart_value = restart_value def next_state(self, state, outcome, count): total_count, trigger, total_cost = state or (0, 0, 0) total_cost += self._cost_map[outcome] * min(count, 6 - total_count) total_count += count if total_count < self._restart_count and outcome <= self._restart_value: return icepool.Reroll return total_count, trigger, total_cost def final_outcome(self, final_state): return final_state[-1] def order(self): return icepool.Order.Descending def extra_outcomes(self, outcomes): return range(1, 21) ` ); } ``` -------------------------------- ### Install Icepool using pip Source: https://github.com/highdiceroller/icepool/blob/main/README.md Use this command to install the Icepool package. It is a pure Python implementation and can be included directly in your project if needed. ```bash pip install icepool ``` -------------------------------- ### Serve JupyterLite Distribution Locally Source: https://github.com/highdiceroller/icepool/blob/main/index.html Instructions for serving the JupyterLite distribution on localhost. Requires navigating to the notebooks directory and installing necessary packages. ```bash cd ./notebooks pip install jupyterlab_server pkginfo pip install --pre jupyterlite jupyter lite serve ``` -------------------------------- ### Initial Setup and Periodic Updates Source: https://github.com/highdiceroller/icepool/blob/main/apps/icecup.html Performs an initial update of the log scale and sets up an interval to display the computation time. The computation time is updated every 100 milliseconds. ```javascript // Initial run. updateLogScale(); setInterval(() => { let computationTime = 0.0; if (endTime >= startTime) { computationTime = endTime - startTime; } else { computationTime = performance.now() + performance.timeOrigin - startTime; } document.getElementById("computation_time").textContent = 'Computation time: ' + (computationTime * 0.001).toFixed(3) + ' s'; }, 100) runCode(); ``` -------------------------------- ### Initial Setup and Event Listeners Source: https://github.com/highdiceroller/icepool/blob/main/apps/ability_scores.html Initializes application state by calling update functions and setting up event listeners for various user interface elements. These listeners handle changes and input events to trigger relevant updates. ```javascript let rollReadyPromise = updateRoll(); updateRankChart(); let pricesReadyPromise = updatePrices(); updatePricesChart(); updateSearchQueryFromForms(); ``` ```javascript let single_array_inputs = document.querySelector('#single_array_inputs'); single_array_inputs.addEventListener('change', validateInputsAndUpdate); single_array_inputs.addEventListener('input', updateAllIfValid); ``` ```javascript let reset_single_ability = document.querySelector('#reset_single_ability'); reset_single_ability.addEventListener('click', resetSingleArray); ``` ```javascript let multiple_array_inputs = document.querySelector('#multiple_array_inputs'); multiple_array_inputs.addEventListener('change', validateInputsAndUpdate); multiple_array_inputs.addEventListener('input', updateAllIfValid); ``` ```javascript let rank_view_select = document.querySelector('#rankDistSelect'); rank_view_select.addEventListener('input', updateRankChart); ``` ```javascript let pricing_preset_select = document.querySelector('#pricingPresetSelect'); pricing_preset_select.addEventListener('input', setPricingPreset); pricing_preset_select.addEventListener('input', updatePricesIfValid); ``` ```javascript let pricing = document.querySelector('#pricing'); pricing.addEventListener('change', validateInputsAndUpdatePrices); pricing.addEventListener('input', updatePricesIfValid); ``` ```javascript let prices_view_dist_select = document.querySelector('#pricesViewDistSelect'); prices_view_dist_select.addEventListener('input', updatePricesChart); ``` -------------------------------- ### Initialize Pyodide and Load Icepool Source: https://github.com/highdiceroller/icepool/blob/main/apps/icecup.html This script initializes Pyodide, a Python distribution that runs in the browser, and then installs and loads the Icepool package. It includes progress updates for the user. ```javascript importScripts("https://cdn.jsdelivr.net/pyodide/v0.26.0/full/pyodide.js"); async function initPyodide(){ self.postMessage({ cmd: 'setLoadingText', text: 'Loading pyodide' }); let pyodide = await loadPyodide({ indexURL : "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/", stdout: (s) => {self.postMessage({ cmd: 'appendOutput', text: s + '\n'});}, stderr: (s) => {self.postMessage({ cmd: 'appendError', text: s + '\n'});} }); await pyodide.loadPackage(["micropip"], {messageCallback : (s) => {self.postMessage({ cmd: 'setLoadingText', text: s });}} ); self.postMessage({ cmd: 'setLoadingText', text: 'Loading icepool' }); let icepool_version_request = icepool_version != "" ? "==" + icepool_version : ""; icepool_version = await pyodide.runPythonAsync( ` import micropip await micropip.install('icepool${icepool_version_request}', pre=True) import icepool icepool.__version__ ` ); self.postMessage({ cmd: 'setIcepoolVersion', text: icepool_version }); self.postMessage({ cmd: 'setLoadingText', text: '' });; return pyodide; } let pyodideReadyPromise = initPyodide(); ``` -------------------------------- ### Initialize Pyodide and Icepool Source: https://github.com/highdiceroller/icepool/blob/main/apps/legends_of_the_wulin.html Initializes Pyodide, loads the micropip package, and installs the icepool library. It also sets up a custom WulinEvaluator for scoring dice rolls. ```python async def initPyodide() { setLoadingText('Loading pyodide') let pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/", }); await pyodide.loadPackage(["micropip"], {messageCallback : setLoadingText}); setLoadingText('Loading icepool') await pyodide.runPythonAsync( ` import micropip await micropip.install('icepool==1.6.0') import js import pyodide import icepool die = icepool.d10 - 1 die_player = icepool.Die([0]) die_opposition = icepool.Die([0]) class WulinEvaluator(icepool.MultisetEvaluator): def next_state(self, state, outcome, count): if state is None: state = 0 score = count * 10 + outcome return max(state, score) evaluator = WulinEvaluator() def calc_pool(prefix): lake = [die] * int(js.document.getElementById('%slake' % prefix).value) river = sum((([n] * int(js.document.getElementById('%s%d' % (prefix, n)).value)) for n in range(10)), []) pool = icepool.Pool(lake + river) return evaluator.evaluate(pool) ` ); totalChart.options.plugins.title = { text: "", fullSize: false, display: false, }; return pyodide; } let pyodideReadyPromise = initPyodide(); ``` -------------------------------- ### Create a Deck of Numbered Cards Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c07_decks.ipynb Constructs a deck with a specified range of outcomes, each duplicated a certain number of times. Ensure 'icepool' is installed. ```python %pip install icepool from icepool import Deck, Die print(Deck(range(1, 14), times=4)) ``` -------------------------------- ### Import Icepool and Define Dice Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/stack_exchange/dependent_dice_rolls.ipynb Installs the icepool library and imports necessary components. Defines dice for damage and modifiers used in the simulation. ```python %pip install icepool import icepool from icepool import d dc = 15 dex_save_mod = 1 int_save_mod = 1 mind_sliver_damage = 2 @ d(6) meteor_damage = 2 @ d(6) ``` -------------------------------- ### Python: Early Binding Example Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c06_multiset_functions.ipynb Demonstrates early binding where a pool ('target') is bound when the multiset function is invoked. Changing 'target' after invocation does not affect the result. ```python target = [1, 2, 3] @multiset_function def early_binding_example(a): return (a & target).size() print(early_binding_example(d6.pool(3))) target = [1] print(early_binding_example(d6.pool(3))) ``` -------------------------------- ### Python: Correlated Rolls Example Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c06_multiset_functions.ipynb Shows how to achieve correlated results by passing the pool ('t') as an argument to the multiset function, ensuring the same roll is used for comparisons. ```python @multiset_function def two_vs_target(a, b, t): return a >= t, b >= t print(two_vs_target(d6.pool(6), (d6 + 6).pool(6), d12.pool(1))) ``` -------------------------------- ### Measure Time Elapsed After Loading Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/isaksen2016.ipynb Measures and prints the time elapsed in seconds since a starting point, typically after a loading or initialization phase. Useful for performance benchmarking. ```python end_ns = time.perf_counter_ns() elapsed_s = (end_ns - start_ns) * 1e-9 print(f'Elapsed time after loading: {elapsed_s:0.3f} s') ``` -------------------------------- ### Implement Largest Straight Evaluator with initial_state and final_outcome Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c08_evaluators.ipynb Use initial_state to set the starting state and reject unsupported orders. Use final_outcome to extract the desired result from the final state. ```python class LargestStraightEvaluator(MultisetEvaluator): def initial_state(self, order, outcomes, size): # Only accept ascending order. if order < 0: raise UnsupportedOrder() return 0, 0, outcomes[0] def next_state(self, state, order, outcome, count): """Increments the current run if at least one `Die` rolled this outcome, then saves the run to the state. """ best_run, run, prev_outcome = state if outcome == prev_outcome + 1 and count >= 1: run += 1 else: run = 0 return max(best_run, run), run, outcome def final_outcome(self, final_state, order, outcomes, size): # Return just the length of the best run. return final_state[0] largest_straight_evaluator = LargestStraightEvaluator() print(largest_straight_evaluator(d6.pool(5))) ``` -------------------------------- ### Create a Weighted Die from a Dictionary Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c01_creating_dice.ipynb Create a weighted die using a dictionary where keys are outcomes and values are their corresponding weights. This example creates a die where '6' has a weight of 3. ```python another_unfair_d6 = Die({1:1, 2:1, 3:1, 4:1, 5:1, 6:3}) print(another_unfair_d6) ``` -------------------------------- ### Find All Matching Sets in a Mixed Dice Pool Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/all_matching_sets.ipynb This example shows how to use the AllMatchingSets evaluator on a mixed pool of standard dice, such as 3d12, 2d10, and 1d8. This is useful for complex dice mechanics found in some tabletop games. ```python # Evaluate on a pool of 3d12, 2d10, 1d8. print(all_matching_sets.evaluate(icepool.standard_pool([12, 12, 12, 10, 10, 8]))) ``` -------------------------------- ### Handle Success Values Above 20 in Infinity Rolls Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/infinity_universe.ipynb This example shows how to handle success values (SV) greater than 20 in Infinity Universe rolls. It modifies the dice pool to cap SV at 20 and treat excess points as bonuses, effectively making rolls above 20 a critical. Use this when a player's SV is higher than a standard d20. ```python # This can be done by modifying the die that goes into the pool. # Example: a 21 SV versus a 20 SV with one die each. from icepool import d20, lowest print(InfinityUniverseEvaluator(a_sv=20, b_sv=20).evaluate(lowest(d20+1, 20).pool(1), d20.pool(1))) ``` -------------------------------- ### Implement Limited Wildcard Evaluation in Python Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/decks/limited_wildcard.ipynb This code defines a custom `EvalWildcard` class inheriting from `icepool.MultisetEvaluator` to handle wildcards. It specifies how wildcards can substitute for certain cards and how to evaluate the probability of forming a target hand. Ensure 'icepool' is installed via piplite. ```python import piplite await piplite.install("icepool") import icepool import time class EvalWildcard(icepool.MultisetEvaluator): def initial_state(self, order, *_*): # Force ascending order. if order < 0: raise icepool.UnsupportedOrder() return 0 def next_state(self, state, order, outcome, target, *counts): # state = the number of wildcards needed. total_count = sum(counts) # Final: wildcards. if outcome == 'W': if state == 'fail': return False else: return total_count >= state if state == 'fail': return state # Could potentially use wildcards. if outcome >= 'C': return state + max(target - total_count, 0) # Ineligible for wildcards. if total_count < target: return 'fail' return state def extra_outcomes(self, *_): # Always process wildcard. return ('W',) # When expressed as a sequence, each appearance counts as one card. target = list('ABBCDDEEE') # When expressed as a dict, the value gives the number of cards. deal = icepool.Deck({'A': 3, 'B': 8, 'C': 2, 'D': 3, 'E': 3, 'F': 113, 'W': 7}).deal(35) hand = list('W') evaluator = EvalWildcard() start_ns = time.perf_counter_ns() # The counts resulting from the three arguments are supplied as # the last three arguments to next_state. result = evaluator.evaluate(target, deal, hand) end_ns = time.perf_counter_ns() elapsed_ms = (end_ns - start_ns) * 1e-6 print(f'Computation time: {elapsed_ms:0.1f} ms') print(f'{result:md:o|q==|%==}') ``` ```text Computation time: 9.9 ms Die with denominator 903552809026475628595978062186780 | Outcome | Quantity | Probability | |:--------|----------------------------------:|------------:| | False | 816069609857287121983676726542308 | 90.317865% | | True | 87483199169188506612301335644472 | 9.682135% | ``` -------------------------------- ### Plot Dice Distribution with Matplotlib Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/hello_3d6.ipynb Visualizes the probability distribution of a die object using Matplotlib. Ensure Matplotlib is installed (`pip install matplotlib`). ```python # Plot using matplotlib. import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.plot(die.outcomes(), die.probabilities()) plt.show() ``` -------------------------------- ### Initialize Pyodide and Icepool Source: https://github.com/highdiceroller/icepool/blob/main/apps/honkai_star_rail_relic.html Initializes Pyodide, loads necessary packages including micropip and icepool, and sets up the Python environment for the relic calculator. It configures stat definitions and prepares the input table in the HTML. ```javascript async function initialize() { setLoadingText('Loading pyodide') let pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/", }); await pyodide.loadPackage(["micropip"], {messageCallback : setLoadingText} ); setLoadingText('Loading icepool') await pyodide.runPythonAsync( ` import micropip await micropip.install('icepool==1.7.2a1') import js import pyodide from functools import cache from icepool import Wallenius, format_probability_inverse stats = { 'spd' : ('SPD', 4), 'cr' : ('CRIT Rate', 6), 'cd' : ('CRIT DMG', 6), 'be' : ('Break Effect', 8), 'ehr' : ('Effect Hit Rate', 8), 'eres' : ('Effect Resist', 8), 'hp_pct' : ('HP%', 10), 'atk_pct' : ('ATK%', 10), 'def_pct' : ('DEF%', 10), 'hp' : ('HP', 10), 'atk' : ('ATK', 10), 'def' : ('DEF', 10), } def wanted_substat_count(haves, wants, pulls): possible_weights = [] for stat, (full_name, weight) in stats.items(): if stat not in haves: possible_weights.append((stat in wants, weight)) return Wallenius(possible_weights).deal(pulls).sum() def select_substats(wants, count): if count == 0: return () result = () for _, stat in sorted((weight, stat) for stat, (_, weight) in stats.items()): if stat in wants: result = result + (stat,) if len(result) == count: break return result input_table = js.document.getElementById('input_table') for stat, (display_string, weight) in stats.items(): row = input_table.insertRow() row.innerHTML = f'{display_string}{weight} ' row = input_table.insertRow() row.innerHTML = f'Other' ` ); let inputs = document.querySelector('#inputs'); inputs.addEventListener('input', update); return pyodide; } ``` -------------------------------- ### Expand Pool Outcomes Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c05_dice_pools.ipynb Use the `expand` method to get all possible sorted rolls from a pool. This can be inefficient for large pools. ```python print(d6.pool(3)[0, 1, 1].expand()) ``` -------------------------------- ### Python: Independent Rolls Example Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c06_multiset_functions.ipynb Illustrates independent rolls where pools not passed as arguments are rolled independently. The `>=` operator checks for superset. ```python from icepool import d12 target = d12.pool(1) # Remember, since we are dealing with multisets here, the `>=` operator means `issuperset`. @multiset_function def two_vs_target(a, b): return a >= target, b >= target print(two_vs_target(d6.pool(6), (d6 + 6).pool(6))) ``` -------------------------------- ### Evaluate 10d10 Pool Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/all_matching_sets.ipynb Evaluates a pool of 10 ten-sided dice (10d10) to determine the distribution of outcomes. This is a basic usage example. ```python print(num_pairs.evaluate(icepool.d10.pool(10))) ``` -------------------------------- ### Initialize Prices Chart with Chart.js Source: https://github.com/highdiceroller/icepool/blob/main/apps/ability_scores.html Sets up a line chart to display probability distributions. Requires a canvas element with id 'pricesChart'. ```javascript var pricesChartContext = document.getElementById('pricesChart').getContext('2d'); var pricesChart = new Chart(pricesChartContext, { type: 'line', data: { labels: [], datasets: [ { label: 'Chance', borderColor: 'rgba(0, 120, 0, 1.0)', data: [], }, ], }, options: { responsive: true, maintainAspectRatio: false, interaction: { intersect: false, }, scales: { x: { title: { display: true, text: 'Total', }, }, y: { beginAtZero: true, title: { display: true, text: 'Chance (%)', }, ticks: { callback: (val) => (val.toPrecision(3) * 1.0 + '%'), }, }, }, plugins: { title: { fullSize: true, display: true, font: { size: 36, }, }, legend: { display: false, }, tooltip: { callbacks: { label: (ctx) => ctx.dataset.label + ': ' + ctx.raw.toPrecision(3) + '%', }, }, }, }, }); ``` -------------------------------- ### Initialize Rank Chart with Chart.js Source: https://github.com/highdiceroller/icepool/blob/main/apps/ability_scores.html Sets up a line chart to display rank probabilities. Requires a canvas element with id 'rankChart'. ```javascript setInputsFromSearchQuery(); var rankChartContext = document.getElementById('rankChart').getContext('2d'); var rankChart = new Chart(rankChartContext, { type: 'line', data: { labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], datasets: [], }, options: { responsive: true, maintainAspectRatio: false, interaction: { intersect: false, }, scales: { x: { title: { display: true, text: 'Ability score', }, }, y: { beginAtZero: true, title: { display: true, text: 'Chance (%)', }, ticks: { callback: (val) => (val.toPrecision(3) * 1.0 + '%'), }, }, }, plugins: { title: { fullSize: true, display: true, font: { size: 36, }, }, tooltip: { callbacks: { label: (ctx) => ctx.dataset.label + ': ' + ctx.raw.toPrecision(3) + '%', }, }, }, }, }); let rankColors = [ 'rgba(220, 0, 240, 1.0)', 'rgba(0, 0, 240, 1.0)', 'rgba(0, 200, 240, 1.0)', 'rgba(0, 200, 0, 1.0)', 'rgba(220, 200, 0, 1.0)', 'rgba(220, 0, 0, 1.0)', 'rgba(120, 120, 120, 1.0)', ]; var rankLabels = [ 'Highest', '2nd highest', '3rd highest', '4th highest', '5th highest', '6th highest', 'Mean', ]; for (let i = 0; i < 7; i++) { rankChart.data.datasets.push({ label: rankLabels[i], borderColor: rankColors[i], backgroundColor: rankColors[i], data: rankChart.data.labels.map(x => 0.0), }); } ``` -------------------------------- ### Initialize Chart Configuration Source: https://github.com/highdiceroller/icepool/blob/main/apps/icecup.html Sets up a Chart.js instance for visualizing probability distributions. It configures the chart type, data structure, and various options for responsiveness, axes, tooltips, and legends. The logarithmic scale option is applied if the 'ls' query parameter is present. ```javascript var chartContext = document.getElementById('chart').getContext('2d'); var chart = new Chart(chartContext, { type: 'line', data: { labels: [], datasets: [], }, options: { animation: { duration: 0, }, responsive: true, maintainAspectRatio: false, interaction: { intersect: false, }, scales: { x: { title: { display: true, text: 'Outcome', }, }, y: { beginAtZero: true, title: { display: true, text: 'Probability', }, }, }, plugins: { title: { fullSize: true, display : true, font: { size: 36, }, }, legend: { labels: { usePointStyle: true, }, }, tooltip : { usePointStyle: true, callbacks: {}, }, filler: { propagate: true, }, }, elements: { point: { radius: 3, }, }, }, }); if (document.getElementById('ls').checked) { chart.options.scales.y.type = 'logarithmic'; chart.options.scales.y.ticks.callback = (val) => (val.toExponential()); } ``` -------------------------------- ### Create a Custom Die from a List Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c01_creating_dice.ipynb Create a custom die where each element in the list represents an outcome that appears once. This example creates a standard six-sided die. ```python from icepool import Die another_d6 = Die([1, 2, 3, 4, 5, 6]) print(another_d6) ``` -------------------------------- ### Initialize Ace Editor Source: https://github.com/highdiceroller/icepool/blob/main/apps/icecup.html Sets up the Ace code editor with Python mode, GitHub theme, and soft tabs. It also observes layout changes to resize the editor accordingly. The initial code is loaded from the editor's value, URL parameters, or a default string. ```javascript var editor = ace.edit("editor"); editor.setTheme("ace/theme/github"); editor.session.setMode("ace/mode/python"); editor.setOptions({"useSoftTabs" : true, "scrollPastEnd" : 1.0}); var resizer = new ResizeObserver(entries => {editor.resize();}); resizer.observe(document.getElementById("main")); var initialCode = 'from icepool import d\n\noutput(3 @ d(6))\n'; var url_code = searchParams.get('c'); if (url_code) { try { initialCode = LZString.decompressFromEncodedURIComponent(url_code); } catch (err) { document.getElementById("error").textContent = "Failed to decompress code from URL."; } } editor.setValue(initialCode, 1); ``` -------------------------------- ### Initialize Pyodide (JavaScript) Source: https://github.com/highdiceroller/icepool/blob/main/apps/year_zero_engine.html Initializes Pyodide, a Python interpreter in the browser, and returns a promise for its readiness. ```javascript let pyodideReadyPromise = initPyodide(); ``` -------------------------------- ### Element-wise Operations on Vector Dice Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c04_advanced_dice.ipynb When adding Vector-outcome dice, operations are applied element-wise, not as concatenation. This example shows the sum of two one-hot encoded dice. ```python print(die + die) ``` -------------------------------- ### Print All Action Sets Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/stack_exchange/all_action_stress.ipynb Prints all possible action sets. This can generate a large amount of output, especially with larger action pools. ```python print(result) ``` -------------------------------- ### Simulate Larger Two-Colored Dice Pool Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/stack_exchange/green_red_elimination.ipynb This example demonstrates evaluating a larger and more complex two-colored dice pool. It uses the same GreenRed evaluator defined previously. ```python # A larger calculation. print(green_red.evaluate([d12, d10, d8, d6, d4, d12, d10, d8, d6, d4], [d12, d10, d8, d6, d4, d12, d10, d8, d6, d4])) ``` -------------------------------- ### Initialize Base Case and Dice Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/stack_exchange/game_of_threes.ipynb Sets up the initial state for the game simulation and defines a standard six-sided die. ```python results = [Die([vectorize(0, 0)])] die = Die([vectorize(1, 0), vectorize(2, 0), vectorize(0, 1), vectorize(4, 0), vectorize(5, 0), vectorize(6, 0)]) ``` -------------------------------- ### Event Listeners for UI Interactions Source: https://github.com/highdiceroller/icepool/blob/main/apps/icecup.html Sets up event listeners for various UI elements including run, stop, switch to latest, keyboard shortcuts, and input changes for equation, greater/less than, log scale, and type. Also includes functionality to copy the URL. ```javascript document.getElementById("run").addEventListener("click", runCode); document.getElementById("stop").addEventListener("click", interruptExecution); document.getElementById("switch_to_latest").addEventListener("click", switchToLatest); document.body.addEventListener('keydown', function (e) { if (e.key == 'Enter' && (e.ctrlKey || e.metaKey)) { e.preventDefault(); run(); } }); document.getElementById("eq").addEventListener("change", runCode); document.getElementById("ge").addEventListener("change", runCode); document.getElementById("le").addEventListener("change", runCode); document.getElementById("ls").addEventListener("change", updateLogScale); document.getElementById("t").addEventListener("change", runCode); ``` ```javascript document.getElementById("copy_url").addEventListener("click", function (e) { navigator.clipboard.writeText(window.location.href); document.getElementById("copy_url").textContent = 'Copied!'; setTimeout( () => { document.getElementById("copy_url").textContent = 'Copy URL'; }, 1000); }); ``` -------------------------------- ### Calculate Probability of 15+ on 10+ of 17 Dice Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/stack_exchange/odds_of_rolling_high_all_the_time.ipynb Calculates the probability of rolling 15 or higher on at least 10 out of 17 dice. Requires the icepool library to be installed. ```python %pip install icepool import icepool # Dimension 0 is the number of dice that scored 15+. # Dimension 1 is the number that scored 9-. die = icepool.d20.map(lambda x: icepool.vectorize(x >= 15, x < 10)) # Roll 17 of them and sum. seventeen_rolls = 17 @ die print('Chance of rolling 15+ on at least 10 out of 17 dice:') print(seventeen_rolls.marginals[0] >= 10) ``` -------------------------------- ### Initialize and Update Pyodide Source: https://github.com/highdiceroller/icepool/blob/main/apps/honkai_star_rail_relic.html Initializes Pyodide and then calls an update function. This is typically used to set up the Python environment in the browser and trigger an initial data refresh or display. ```javascript let pyodideReadyPromise = initialize(); update(); ``` -------------------------------- ### Calculate Intersection of Pools Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c05_dice_pools.ipynb The `&` operator calculates the intersection of two pools, counting matching pairs. This example finds the number of matching pairs from two pools of 3d6. ```python print((d6.pool(3) & d6.pool(3)).size()) ``` -------------------------------- ### Dice Immutability Example Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c02_dice_operators.ipynb Illustrates that Dice objects are immutable. The '+=' operator reassigns the variable 'a' to a new Die object, leaving the original d6 Die unchanged. ```python a = d6 a += d6 # This assigns a new Die object to a. It does not modify the original Die. print(d6) # The original Die is unchanged. ``` -------------------------------- ### Create a Standard 6-Sided Die Directly Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c01_creating_dice.ipynb Import and use `d6` directly for a standard six-sided die. This is a convenient shortcut for `d(6)`. ```python from icepool import d6 print(d6) ``` -------------------------------- ### Check for Superset Roll Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c05_dice_pools.ipynb The `>=` operator checks if the roll of the left pool is a superset of the right pool's outcomes. This example checks for at least one 1 and one 2. ```python print(d6.pool(3) >= [1, 2]) ``` -------------------------------- ### Create a Deck with Mixed Duplicates Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c07_decks.ipynb Demonstrates creating a deck where some outcomes are duplicated a set number of times, and others are themselves decks that are duplicated. This differs from Die construction where weights are shared. ```python # Take a deck of 1-13, duplicate it 4 times, then throw in two 14s. deck = Deck({Deck(range(1, 14)): 4, 14: 2}) print(deck) # Roll 1d6: # On 1-4: the result is 1d13. # On 5-6: the result is 14. print(Die({Die(range(1, 14)): 4, 14: 2})) ``` -------------------------------- ### Create and Combine Dice in Python Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/hello_3d6.ipynb Shows how to create standard dice (d6, d97), define custom dice using mappings or lists, and combine them using addition or the '@' operator to represent rolling multiple dice. Includes version checks for Python and Icepool. ```python %pip install icepool import icepool import sys from importlib.metadata import version print('python version:', sys.version) print('icepool version:', version('icepool')) # Create a d6. Here's a few different ways... # Just import it. In fact, you can import any-sided standard die. from icepool import d6, d97 # Use the d() function. d6 = icepool.d(6) # Specify a mapping from outcomes to weights. d6 = icepool.Die({1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}) # Give the outcomes as separate arguments. Each will be weighted once. d6 = icepool.Die([1, 2, 3, 4, 5, 6]) # Now we want three of them added together. Here's a couple of ways to do that: # Just add them together. die = d6 + d6 + d6 # Use the @ operator, which means roll the left side, then roll the right side that many times and add. # The "3" becomes a die which always rolls the number 3. die = 3 @ icepool.d6 # The result is another die with the probability distribution of 3d6. # Print a table of the outcomes, weights, and probabilities. print(die) ``` -------------------------------- ### Calculate Push Zeros If Fail and No Initial Bane (Python) Source: https://github.com/highdiceroller/icepool/blob/main/apps/year_zero_engine.html Similar to calc_push_zeros_if_fail, but also considers the initial bane count. Pushes zeros to fail if success or bane is greater than zero, or if a win is not possible. ```python def calc_push_zeros_if_fail_and_no_initial_bane(success, bane, z6, z8, z10, z12, s10, s12): if success > 0 or bane > 0: return icepool.vectorize(success, 0) if not can_win(success, bane, z6, z8, z10, z12, 0, 0): return icepool.vectorize(success, 0) return calc_push_zeros(success, bane, z6, z8, z10, z12, s10, s12) ``` -------------------------------- ### Initial Chart and Roll Updates Source: https://github.com/highdiceroller/icepool/blob/main/apps/legends_of_the_wulin.html Initializes the calculator by performing the first updates for player roll, opposition roll, and the total chart, and synchronizes the form state with the URL query parameters. ```javascript updatePlayerRoll(); updateOppositionRoll(); updateTotalChart(); updateSearchQueryFromForms(); ``` -------------------------------- ### Define outcome distribution mapping Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/stack_exchange/game_of_threes.ipynb This code snippet illustrates the structure for mapping pool sizes to their corresponding outcome distributions. It serves as a starting point for dynamic programming or memoization approaches. ```python # Maps pool size -> outcome distribution. ``` -------------------------------- ### Generate 4d6 Keep Highest 3 Dice Distribution Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/ability_scores/completely_unfair.ipynb Installs the icepool library and creates a dice object representing the outcome of rolling 4 six-sided dice and keeping the highest 3. ```python %pip install icepool import icepool one_ability = icepool.d6.highest(4, 3) ``` -------------------------------- ### Simulate and Plot Reroll Strategies Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/broken_compass.ipynb Simulates both 'Known-difficulty' and 'Always-reroll' strategies for various pool sizes and plots the results. This helps visualize the performance differences between the strategies. ```python known_difficulty_results = [] always_reroll_results = [] for pool_size in pool_sizes: initial = pool_size @ die known_difficulty_results.append(initial.map(known_difficulty_risk)) always_reroll_results.append(initial.map(always_reroll_risk)) plot_results(known_difficulty_results, always_reroll_results) ``` -------------------------------- ### Initialize Success Chart Source: https://github.com/highdiceroller/icepool/blob/main/apps/year_zero_engine.html Initializes a Chart.js bar chart to display success probabilities. Configures axes, tooltips, and responsiveness. The chart is configured with 'y' as the index axis. ```javascript var successChartContext = document.getElementById('successChart').getContext('2d'); var successChart = new Chart(successChartContext, { type: 'bar', data: { labels: [], }, options: { indexAxis: 'y', responsive: true, maintainAspectRatio: false, animation: false, scales: { x: { title: { display: true, text: 'Chance (%)', }, stacked: true, min: 0.0, max: 100.0, ticks: { callback: (val) => (val.toPrecision(3) * 1.0 + '%'), }, }, y: { stacked: true, grid: { display: false, }, }, }, datasets: { bar: { categoryPercentage: 1.0, borderWidth: 1, }, }, plugins: { title: { fullSize: true, display: true, font: { size: 36, }, }, legend: { display: false, }, tooltip: { displayColors: false, callbacks: { label: (ctx) => ctx.dataset.label + ': ' + ctx.raw.toPrecision(3) + '%', }, position: 'barCenter', }, }, }, }); ``` -------------------------------- ### Get the Value of a Dropped Die Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c05_dice_pools.ipynb Access the outcome of a specific die within a sorted pool using a single index. This returns a `Die` representing the distribution of that specific die's value. ```python # What was the value of the dropped die? print(d6.pool(4)[0]) ``` -------------------------------- ### Reroll Specific Outcomes with Icepool Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c04_advanced_dice.ipynb Use the `Reroll` special value within `Die.map()` to reroll specified outcomes. This example rerolls 1s and 2s on a d6, effectively changing the probability distribution. ```python from icepool import Reroll, d6 d6.reroll([1, 2], depth='inf') print(d6.map({1: Reroll, 2: Reroll})) ``` -------------------------------- ### Get Highest of Two Dice Rolls Source: https://github.com/highdiceroller/icepool/blob/main/notebooks/tutorial/c03_dice_functions.ipynb Use the `highest` function to determine the maximum outcome when rolling two dice. This function returns a new Die object representing the distribution of the highest roll. ```python %pip install icepool from icepool import d6, highest, lowest, highest, lowest print(highest(d6, d6)) ```