code wiki / (root) / nx_soda_flavor.nx

nx_soda_flavor.nx source

↩ module page · 167 lines · 7594 B

1// nx_soda_flavor.nx -- CRAFT-SODA rung F0: the FLAVOR-DESIGN model. 2// 3// The operator's curiosity point (3): "the best flavoring like a crystallized 4// lemon/lime so it's SMOOTH + EVEN + STRONG WITHOUT sugar or other things 5// hiding it." The grounded answer (WebSearch 2026-07-10): 6// - CITRIC acid = sharp/pointy/immediate sourness (a stronger acid -> a 7// bigger [H+] spike); MALIC acid = rounded/smooth/lingering (a weaker 8// acid). BLENDING them is the craft smoothness knob. 9// - a WHISPER of sweet AROMA (vanilla/ester) triggers olfactory-gustatory 10// synergism -> the brain perceives roundness/sweetness from aroma ALONE, 11// no sugar, and aroma ENHANCES clarity rather than masking it. 12// - SUGAR mutes + hides flavor; the operator forbids it. 13// 14// This organ composes two others -- nx_taste_transduce (the sour receptor 15// Hill curve) and nx_soda_carbonation (carbonic-acid [H+]) -- so perceived 16// sourness is the real receptor response to the COMBINED acid+CO2 stimulus, 17// not a naive sum. Everything integer-exact, no float. 18// 19// MEASURED EXCEEDS (gate-checked, see nx_soda_flavor_test): 20// - MALIC IS SMOOTHER: at equal molarity malic yields strictly less [H+] 21// (a softer sour) than citric -- why it rounds a blend. 22// - THE BLEND BEATS EITHER ALONE: a ~50:50 citric:malic blend scores higher 23// roundness than pure citric (harsh/pointy) OR pure malic (flat). 24// - AROMA ROUNDS WITHOUT SUGAR: a whisper of sweet aroma raises roundness 25// while clarity stays perfect (sugar = 0). 26// - CARBONATION IS A FLAVOR LEVER: adding CO2 raises BOTH perceived sourness 27// and aroma-lifted intensity. 28// - LIAR-KILL: a recipe that reaches for SUGAR to fake smoothness is 29// rejected as dishonest -- "nothing hiding it" enforced by construction 30// (sugar earns ZERO roundness credit; it only mutes clarity). 31// 32// genealogy_id: nishi_taste_transduce_2026 + citric_malic_acidulant_profiles 33// + olfactory_gustatory_synergism + nishi_soda_carbonation_2026 34 35import "nx_syscalls.nx" 36import "nx_taste_transduce.nx" 37import "nx_soda_carbonation.nx" 38 39// ===== scaled weak-acid constants (Ka1 * 1e9) =================== 40// [H+]_uM = isqrt(Ka_scaled * conc_mM). Citric (pKa1 3.13) is a STRONGER 41// acid than malic (pKa1 3.40): more [H+] per mole -> a sharper, pointier sour. 42const SODA_CITRIC_KA_SCALED: i64 = 740000 43const SODA_MALIC_KA_SCALED: i64 = 400000 44const SODA_SUGAR_TRACE_GL: i64 = 2 // g/L: above this, "sugar-free" is a lie 45 46// ===== recipe ===================================================== 47struct NxSodaRecipe { 48 citric_mM: i64, 49 malic_mM: i64, 50 aroma_milli: i64, // sweet-aroma whisper dose (vanilla/ester) 51 sugar_g_per_l: i64, // the forbidden crutch 52 carbonation_volumes_milli: i64, 53 temp_c: i64, 54} 55 56// ===== acid -> sour stimulus ([H+], micromolar) ================= 57func soda_citric_hplus_um(conc_mM: i64) -> i64 { 58 if conc_mM <= 0 { return 0 } 59 return soda_isqrt(SODA_CITRIC_KA_SCALED * conc_mM) 60} 61func soda_malic_hplus_um(conc_mM: i64) -> i64 { 62 if conc_mM <= 0 { return 0 } 63 return soda_isqrt(SODA_MALIC_KA_SCALED * conc_mM) 64} 65 66// perceived sourness (milli) of an [H+] stimulus, via the REAL sour receptor 67// Hill curve from nx_taste_transduce (threshold + saturation, not a linear add). 68func soda_sour_from_hplus(hplus_um: i64) -> i64 { 69 let r: *NxTasteReceptor = nx_taste_receptor(NX_TQ_SOUR) 70 return nx_taste_response_milli(r, hplus_um) 71} 72 73// ===== roundness / smoothness =================================== 74// the sweet-aroma whisper: a small dose earns full roundness credit; over- 75// aromatizing reads as artificial and the credit decays (a whisper, not a wall). 76func soda_aroma_round_bonus(aroma_milli: i64) -> i64 { 77 if aroma_milli <= 0 { return 0 } 78 if aroma_milli <= 200 { return aroma_milli } 79 return 200 - (aroma_milli - 200) / 4 80} 81 82// roundness (milli): a tent peaking where malic ~= citric (the blend rounds 83// citric's point without losing its brightness) PLUS the aroma whisper. 84// Sugar earns NOTHING here -- roundness cannot be bought with sweetener. 85func soda_smoothness_milli(citric_mM: i64, malic_mM: i64, aroma_milli: i64) -> i64 { 86 let total: i64 = citric_mM + malic_mM 87 if total <= 0 { return 0 } 88 let malic_frac: i64 = malic_mM * 1000 / total 89 var dev: i64 = malic_frac - 500 90 if dev < 0 { dev = 0 - dev } 91 var blend: i64 = 1000 - 2 * dev 92 if blend < 0 { blend = 0 } 93 var s: i64 = blend + soda_aroma_round_bonus(aroma_milli) 94 if s > 1000 { s = 1000 } 95 return s 96} 97 98// clarity (milli): sugar-free water is a clean canvas (1000); every gram of 99// sugar mutes + hides the citrus, dropping clarity. 100func soda_clarity_milli(sugar_g_per_l: i64) -> i64 { 101 if sugar_g_per_l <= 0 { return 1000 } 102 var c: i64 = 1000 - sugar_g_per_l * 8 103 if c < 0 { c = 0 } 104 return c 105} 106 107// ===== LIAR-KILL: honest-sugarfree predicate ==================== 108// the operator's law: strong+smooth WITHOUT sugar hiding it. A recipe leaning 109// on sugar is rejected (0); a trace from the flavor crystals is tolerated. 110func soda_is_honest_sugarfree(sugar_g_per_l: i64) -> i64 { 111 if sugar_g_per_l <= SODA_SUGAR_TRACE_GL { return 1 } 112 return 0 113} 114 115// ===== recipe-level scores ====================================== 116func soda_recipe_sour_milli(r: *NxSodaRecipe) -> i64 { 117 let carb_co2: i64 = r.carbonation_volumes_milli * SODA_MG_PER_VOLUME / 1000 118 let hp: i64 = soda_citric_hplus_um(r.citric_mM) + soda_malic_hplus_um(r.malic_mM) + soda_hplus_um(carb_co2) 119 return soda_sour_from_hplus(hp) 120} 121func soda_recipe_smoothness_milli(r: *NxSodaRecipe) -> i64 { 122 return soda_smoothness_milli(r.citric_mM, r.malic_mM, r.aroma_milli) 123} 124func soda_recipe_clarity_milli(r: *NxSodaRecipe) -> i64 { 125 return soda_clarity_milli(r.sugar_g_per_l) 126} 127func soda_recipe_honest(r: *NxSodaRecipe) -> i64 { 128 return soda_is_honest_sugarfree(r.sugar_g_per_l) 129} 130// intensity (milli): acid load + aroma, LIFTED by carbonation (the bubbles 131// carry citrus oil to the nose) -- so more fizz = stronger flavor per gram. 132func soda_recipe_intensity_milli(r: *NxSodaRecipe) -> i64 { 133 let base: i64 = r.citric_mM * 10 + r.malic_mM * 10 + r.aroma_milli 134 let enh: i64 = 1000 + r.carbonation_volumes_milli / 10 135 return base * enh / 1000 136} 137 138// ===== GENERATIVE design ======================================== 139// design a SMOOTH, STRONG, SUGAR-FREE lemon/lime at a target sourness: hold 140// malic at ~45% (the roundness sweet-spot), grow the total acid until the 141// sour receptor reaches target, add an aroma whisper, sugar = 0 by construction. 142func soda_design_smooth(target_sour_milli: i64, temp_c: i64) -> *NxSodaRecipe { 143 let carb_vol: i64 = 4000 144 let carb_hplus: i64 = soda_hplus_um(carb_vol * SODA_MG_PER_VOLUME / 1000) 145 var a: i64 = 1 146 var chosen: i64 = 0 147 var found: i64 = 0 148 while a <= 80 { 149 let cit: i64 = a * 55 / 100 150 let mal: i64 = a * 45 / 100 151 let hp: i64 = soda_citric_hplus_um(cit) + soda_malic_hplus_um(mal) + carb_hplus 152 let sour: i64 = soda_sour_from_hplus(hp) 153 if found == 0 { 154 if sour >= target_sour_milli { chosen = a; found = 1 } 155 } 156 a = a + 1 157 } 158 if found == 0 { chosen = 80 } 159 let r: *NxSodaRecipe = (sys_mmap(48)) as *NxSodaRecipe 160 r.citric_mM = chosen * 55 / 100 161 r.malic_mM = chosen * 45 / 100 162 r.aroma_milli = 150 163 r.sugar_g_per_l = 0 164 r.carbonation_volumes_milli = carb_vol 165 r.temp_c = temp_c 166 return r 167}