Comment: | add beginnings of matter compiler UI, check in missing files |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
0e7832a24c7daa4240f152a584e31bbe |
User & Date: | lexi on 2024-05-04 22:41:29 |
Other Links: | manifest | tags |
2024-05-05
| ||
19:31 | better alarm LEDs, continue work on matter compiler UI, hack around gravitational horrorscape (i.e. stop shitting all over the server's `minetest.conf`), better stat interface, tweak some compute stats, be more generous with starting battery loadout, mercilessly squash numberless bugs beneath my jackbooted heel check-in: 953151446f user: lexi tags: trunk | |
2024-05-04
| ||
22:41 | add beginnings of matter compiler UI, check in missing files check-in: 0e7832a24c user: lexi tags: trunk | |
02:18 | fix colors, add grass check-in: 9d4ddb7701 user: lexi tags: trunk | |
Modified mods/starlit-electronics/init.lua from [c28c8fe2b6] to [fff344db38].
39 39 -- crafting, while programs require a certain amount of memory. 40 40 -- chips have a variable number of program slots and a single bootloader slot 41 41 -- 42 42 starlit.item.chip = lib.registry.mk 'starlit_electronics:chip' 43 43 44 44 -- software is of one of the following types: 45 45 -- schematic: program for your matter compiler that enables crafting a given item. 46 --- output: the result 46 +-- output (convertible to ItemStack): the result 47 47 -- driver: inserted into a Core to control attached hardware 48 48 -- suitPower: provides suit functionality like nanoshredding or healing 49 49 -- passive powers are iterated on suit application/configuration and upon fst-tick 50 50 -- cost: what the software needs to run. some fields are fab-specific 51 51 -- energy: for fab, total energy cost of process in joules 52 52 -- for suitPassive, added suit power consumption in watts 53 53 starlit.item.sw = lib.registry.mk 'starlit_electronics:sw' ................................................................................ 214 214 inventory_image = def.img or 'starlit-item-battery.png'; 215 215 description = starlit.ui.tooltip { 216 216 title = def.name; 217 217 desc = def.desc; 218 218 color = lib.color(0,.2,1); 219 219 props = { 220 220 { title = 'Optimal Capacity', affinity = 'info'; 221 - desc = lib.math.si('J', def.capacity) }; 221 + desc = lib.math.siUI('J', def.capacity) }; 222 222 { title = 'Discharge Rate', affinity = 'info'; 223 - desc = lib.math.si('W', def.dischargeRate) }; 223 + desc = lib.math.siUI('W', def.dischargeRate) }; 224 224 { title = 'Charge Efficiency', affinity = 'info'; 225 225 desc = string.format('%s%%', (1-def.leak) * 100) }; 226 226 { title = 'Size', affinity = 'info'; 227 - desc = lib.math.si('m', def.fab.size.print) }; 227 + desc = lib.math.siUI('m', def.fab.size.print) }; 228 228 }; 229 229 }; 230 230 _starlit = { 231 231 event = { 232 232 create = function(st, how) 233 233 --[[if not how.gift then -- cheap hack to make starting batteries fully charged 234 234 E.battery.setCharge(st, 0) ................................................................................ 274 274 -- eluthrai ("uncompromising"): high power, high quality, wildly expensive 275 275 -- firstborn ("god-tier"): exceptional 276 276 277 277 local batteryTiers = { 278 278 makeshift = { 279 279 name = 'Makeshift'; capacity = .5, decay = 3, leak = 2, dischargeRate = 1, 280 280 fab = starlit.type.fab { 281 - metal = {copper=10}; 281 + element = {copper=10}; 282 282 }; 283 283 desc = "Every attosecond this electrical abomination doesn't explode in your face is but the unearned grace of the Wild Gods."; 284 284 complexity = 1; 285 285 sw = {rarity = 1}; 286 286 }; 287 287 imperial = { 288 288 name = 'Imperial'; capacity = 2, decay = 2, leak = 2, dischargeRate = 2; 289 289 fab = starlit.type.fab { 290 - metal = {copper=15, iron = 20}; 290 + element = {copper=15, iron = 20}; 291 291 size = { print = 0.1 }; 292 292 }; 293 293 desc = "The Empire's native technology is a lumbering titan: bulky, inefficient, unreliable, ugly, and awesomely powerful. Their batteries are no exception, with raw capacity and throughput that exceed even Usukinwya designs."; 294 294 drm = 1; 295 295 complexity = 2; 296 296 sw = {rarity = 2}; 297 297 }; 298 298 commune = { 299 299 name = 'Commune'; capacity = 1, decay = .5, leak = .2, dischargeRate = 1; 300 300 fab = starlit.type.fab { 301 - metal = {vanadium=50, steel=10}; 301 + element = {vanadium = 50}; 302 + metal = {steel=10}; 302 303 size = { print = 0.05 }; 303 304 }; 304 305 desc = "The Commune's proprietary battery designs prioritize reliability, compactness, and maintenance concerns above raw throughput, with an elegance of engineering and design that would make a Su'ikuri cry."; 305 306 complexity = 5; 306 307 sw = {rarity = 3}; 307 308 }; 308 309 usukwinya = { 309 310 name = 'Usukwinya'; capacity = 2, decay = 1, leak = 1, dischargeRate = 1.5, 310 311 fab = starlit.type.fab { 311 - metal = {vanadium=30, argon=10}; 312 + element = {argon=10}; 313 + metal = {vanadium=30}; 312 314 size = { print = 0.07 }; 313 315 }; 314 316 desc = "A race of consummate value engineers, the Usukwinya have spent thousands of years refining their tech to be as cheap to build as possible, without compromising much on quality. The Tradebirds drive an infamously hard bargain, but their batteries are more than worth their meagre cost."; 315 317 drm = 2; 316 318 sw = {rarity = 10}; 317 319 complexity = 15; 318 320 }; 319 321 eluthrai = { 320 322 name = 'Eluthrai'; capacity = 3, decay = .4, leak = .1, dischargeRate = 1.5, 321 323 fab = starlit.type.fab { 322 - metal = {beryllium=20, platinum=20, technetium = 1, cinderstone = 10 }; 324 + element = {beryllium=20, platinum=20, technetium = 1}; 325 + metal = {cinderstone = 10}; 323 326 size = { print = 0.03 }; 324 327 }; 325 328 desc = "The uncompromising Eluthrai are never satisfied until every quantifiable characteristic of their tech is maximally optimised down to the picoscale. Their batteries are some of the best in the Reach, and unquestionably the most expensive -- especially for those lesser races trying to copy the designs without the benefit of the sublime autofabricator ecosystem of the Eluthrai themselves."; 326 329 complexity = 200; 327 330 sw = {rarity = 0}; -- you think you're gonna buy eluthran schematics on SuperDiscountNanoWare.space?? 328 331 }; 329 332 firstborn = { 330 333 name = 'Firstborn'; capacity = 5, decay = 0.1, leak = 0, dischargeRate = 3; 331 334 fab = starlit.type.fab { 332 - metal = {neodymium=20, xenon=150, technetium=5, sunsteel = 10 }; 335 + element = {neodymium=20, xenon=150, technetium=5}; 336 + metal = {sunsteel = 10}; 333 337 crystal = {astrite = 1}; 334 338 size = { print = 0.05 }; 335 339 }; 336 340 desc = "Firstborn engineering seamlessly merges psionic effects with a mastery of the physical universe unattained by even the greatest of the living Starsouls. Their batteries reach levels of performance that strongly imply Quantum Gravity Theory -- and several major holy books -- need to be rewritten. From the ground up."; 337 341 complexity = 1000; 338 342 sw = {rarity = 0}; -- lol no 339 343 }; ................................................................................ 367 371 368 372 complexity = 3; 369 373 }; 370 374 chemical = { 371 375 name = 'Chemical'; 372 376 desc = ''; 373 377 fab = starlit.type.fab { 374 - element = { lithium = 3}; 375 - metal = {iron = 5}; 378 + element = { lithium = 3 }; 376 379 size = {print=1.0}; 377 380 }; 378 381 sw = { 379 382 cost = { 380 383 cycles = 1e9; -- 1 bil cycles 381 384 ram = 2e9; -- 2GB 382 385 }; ................................................................................ 409 412 }; 410 413 hybrid = { 411 414 name = 'Hybrid'; 412 415 desc = ''; 413 416 capacity = 1; 414 417 fab = starlit.type.fab { 415 418 element = { 416 - lithium = 3; 417 - }; 418 - metal = { 419 - iron = 5; 419 + lithium = 10; 420 + carbon = 20; 420 421 }; 421 422 size = {print=1.5}; 422 423 }; 423 424 sw = { 424 425 cost = { 425 426 cycles = 65e9; -- 65 bil cycles 426 427 ram = 96e9; -- 96GB ................................................................................ 500 501 else 501 502 rare = bType.sw.rarity + bTier.sw.rarity 502 503 end 503 504 504 505 starlit.item.sw.link(swID, { 505 506 kind = 'schematic'; 506 507 name = name .. ' Schematic'; 508 + input = fab; 507 509 output = id; 508 510 size = bType.sw.pgmSize; 509 511 cost = bType.sw.cost; 510 512 rarity = rare; 511 513 }) 512 514 513 515 E.schematicGroupLink('starlit_electronics:battery', swID) ................................................................................ 686 688 data = {} 687 689 defOnly = true 688 690 end 689 691 def = assert(def._starlit.chip) 690 692 end 691 693 local props = { 692 694 {title = 'Clock Rate', affinity = 'info'; 693 - desc = lib.math.si('Hz', def.clockRate)}; 695 + desc = lib.math.siUI('Hz', def.clockRate)}; 694 696 {title = 'RAM', affinity = 'info'; 695 - desc = lib.math.si('B', def.ram)}; 697 + desc = lib.math.siUI('B', def.ram)}; 696 698 } 697 699 if not defOnly then 698 700 table.insert(props, { 699 701 title = 'Free Storage', affinity = 'info'; 700 - desc = lib.math.si('B', E.chip.freeSpace(ch, data)) .. ' / ' 701 - .. lib.math.si('B', def.flash); 702 + desc = lib.math.siUI('B', E.chip.freeSpace(ch, data)) .. ' / ' 703 + .. lib.math.siUI('B', def.flash); 702 704 }) 703 705 local swAffMap = { 704 706 schematic = 'schematic'; 705 707 suitPower = 'ability'; 706 708 driver = 'driver'; 707 709 } 708 710 for i, e in ipairs(data.files) do ................................................................................ 730 732 affinity = aff; 731 733 desc = name; 732 734 }) 733 735 end 734 736 else 735 737 table.insert(props, { 736 738 title = 'Flash Storage', affinity = 'info'; 737 - desc = lib.math.si('B', def.flash); 739 + desc = lib.math.siUI('B', def.flash); 738 740 }) 739 741 end 740 742 return starlit.ui.tooltip { 741 743 title = data.label and data.label~='' and string.format('<%s>', data.label) or def.name; 742 744 color = lib.color(.6,.6,.6); 743 745 desc = def.desc; 744 746 props = props; ................................................................................ 782 784 local circMat = t.circ or 'silicon'; 783 785 starlit.item.chip.link(id, { 784 786 name = t.name; 785 787 clockRate = t.clockRate; 786 788 flash = t.flash; 787 789 ram = t.ram; 788 790 powerEfficiency = t.powerEfficiency; -- cycles per joule 789 - fab = { 791 + fab = starlit.type.fab { 790 792 flag = { 791 793 silicompile = true; 792 794 }; 793 795 time = { 794 796 silicompile = t.size * 24*60; 795 797 }; 796 798 cost = { ................................................................................ 866 868 end; 867 869 open = function(self,fn) 868 870 return E.chip.fileOpen(self.chip, self.inode, fn) 869 871 end; 870 872 }; 871 873 } 872 874 873 -function E.chip.usableSoftware(chips,pgm) 875 +function E.chip.usableSoftware(chips,pgm,pred) 876 + pred = pred or function() return true end 874 877 local comp = E.chip.sumCompute(chips) 875 878 local r = {} 876 879 local unusable = {} 877 880 local sw if pgm then 878 881 if type(pgm) == 'string' then 879 882 pgm = {starlit.item.sw.db[pgm]} 880 883 end ................................................................................ 895 898 end 896 899 end 897 900 end 898 901 end 899 902 end 900 903 901 904 for _, s in pairs(sw) do 902 - if s.sw.cost.ram <= comp.ram then 905 + if s.sw.cost.ram <= comp.ram and pred(s) then 903 906 table.insert(r, { 904 907 sw = s.sw; 905 908 chip = s.chip, chipSlot = s.chipSlot; 906 909 file = s.file; 907 910 fd = E.chip.fileHandle(s.chip, s.inode); 908 911 speed = s.sw.cost.cycles / comp.cycles; 909 912 powerCost = s.sw.cost.cycles / comp.powerEfficiency;
Modified mods/starlit-electronics/mod.conf from [c7d10b71e3] to [8ba7140456].
1 1 name = starlit_electronics 2 2 title = starlit electronics 3 3 description = basic electronic components and logic 4 -depends = starlit 4 +depends = starlit, starlit_material
Modified mods/starlit-electronics/sw.lua from [eb892cff12] to [430c447d0b].
99 99 user.action.fx.shred = starlit.fx.nano.shred(user, what, prop, shredTime, node) 100 100 else 101 101 user.action.prog.shred = user.action.prog.shred + ctx.how.delta or 0 102 102 end 103 103 --print('shred progress: ', user.action.prog.shred) 104 104 if user.action.prog.shred >= shredTime then 105 105 minetest.remove_node(what) 106 + minetest.check_for_falling(what) 106 107 --print('shred complete') 107 108 user:suitSound 'starlit-success' 108 109 if fab then 109 110 local vf = fab 110 111 if vary then 111 112 local rng = (starlit.world.seedbank+0xa891f62)[minetest.hash_node_position(what)] 112 113 vf = vf + vary(rng, {})
Modified mods/starlit-material/elements.lua from [2a0859e47b] to [fb5dcf0ef1].
23 23 color = lib.color(.7,.2,.1); 24 24 }; 25 25 silicon = { 26 26 name = 'silicon', sym = 'Si', n = 14, density = 2.329; 27 27 metal = true; -- can be forged into an ingot 28 28 color = lib.color(.6,.6,.4); 29 29 }; 30 + neodymium = { 31 + name = 'neodymium', sym = 'Nd', n= 60, density = 7.01; 32 + metal = true; 33 + color = lib.color(1,1,1); 34 + }; 30 35 potassium = { 31 36 name = 'potassium', sym = 'K', n = 19, density = 0.862; 32 37 -- potassium is technically a metal but it's so soft 33 38 -- it can be easily nanoworked without high temps, so 34 39 -- ingots make no sense 35 40 color = lib.color(1,.8,0.1); 36 41 };
Modified mods/starlit-material/init.lua from [b9ae2a76fd] to [158d4b1720].
18 18 storage = {name = 'Storage Canister', vol = 16.0}; 19 19 } 20 20 21 21 starlit.mod.material = M 22 22 23 23 starlit.include 'elements' 24 24 starlit.include 'liquids' 25 +starlit.include 'metals' 25 26
Added mods/starlit-material/liquids.lua version [2d90e78ef4].
1 +local lib = starlit.mod.lib 2 +local M = starlit.mod.material 3 + 4 +starlit.world.material.liquid.meld { 5 + water = { 6 + name = 'water'; 7 + composition = starlit.type.fab { 8 + element = {hydrogen = 2.0, oxygen = 1.0}; 9 + }; 10 + density = 1.0; 11 + desc = "the sine qua non of biological life"; 12 + color = lib.color(.1,.2,1); 13 + }; 14 +}
Added mods/starlit-material/metals.lua version [3454f586c9].
1 +local lib = starlit.mod.lib 2 +local M = starlit.mod.material 3 + 4 +starlit.world.material.metal.meld { 5 + steel = { 6 + name = 'steel'; 7 + composition = starlit.type.fab { 8 + element = {iron = 2.0, carbon = 1.0}; 9 + }; 10 + density = 1.0; 11 + desc = "steel is a widely used alloy of iron and carbon"; 12 + color = lib.color(.4,.4,.4); 13 + }; 14 +}
Modified mods/starlit/element.lua from [4c0283cfa3] to [25b10aa9d6].
162 162 _starlit = { 163 163 mass = 1e3; 164 164 material = { 165 165 kind = 'metal'; 166 166 metal = id; 167 167 }; 168 168 fab = starlit.type.fab { 169 - flag = {smelt= true}; 169 + flag = {smelt=true}; 170 170 element = comp(1e3); 171 171 }; 172 172 }; 173 173 }); 174 174 175 175 176 176 end)
Modified mods/starlit/fab.lua from [800ac068f1] to [bdd1907d1f].
8 8 -- a+b = compose a new spec from the spec parts a and b. 9 9 -- this is used e.g. for creating tier-based 10 10 -- fabspecs. 11 11 -- 12 12 -- * used for determining quantities. that is, 13 13 -- f*x = spec to make x instances of f 14 14 -- 15 --- new fab fields must be defined in starlit.type.fab.opClass. 15 +-- new fab fields must be defined in starlit.type.fab.fields. 16 16 -- this maps a name to fn(a,b,n) -> quant, where a is the first 17 17 -- argument, b is a compounding amount, and n is a quantity of 18 18 -- items to produce. fields that are unnamed will be underwritten 19 19 20 20 local function fQuant(a,b,n) return ((a or 0)+(b or 0))*n end 21 21 local function fFac (a,b,n) 22 22 if a == nil and b == nil then return nil end ................................................................................ 26 26 f = (a or 1)*(b or 1) 27 27 end 28 28 return f*n 29 29 end 30 30 local function fReq (a,b,n) return a or b end 31 31 local function fFlag (a,b,n) return a and b end 32 32 local function fSize (a,b,n) return math.max(a,b) end 33 -local opClass = { 33 + 34 +local F = string.format 35 +local lib = starlit.mod.lib 36 + 37 +local fields = { 34 38 -- fabrication eligibility will be determined by which kinds 35 39 -- of input a particular fabricator can introduce. e.g. a 36 40 -- printer with a but no cache can only print items whose 37 41 -- recipe only names elements as ingredients 38 - 39 - -- ingredients 40 - element = fQuant; -- (g) 41 - gas = fQuant; -- () 42 - liquid = fQuant; -- (l) 43 - crystal = fQuant; -- (g) 44 - item = fQuant; -- n 45 - metal = fQuant; -- (g) 46 - metalIngot = fQuant; -- (g) 42 + element = { 43 + name = {"element", "elements"}; 44 + string = function(x, n, long) 45 + local el = starlit.world.material.element.db[x] 46 + return lib.math.si('g', n) .. ' ' .. ((not long and el.sym) or el.name) 47 + end; 48 + image = function(x, n) 49 + return string.format('starlit-element-%s.png', x) 50 + end; 51 + op = fQuant; 52 + }; 53 + metal ={ 54 + name = {"metal", "metals"}; 55 + string = function(x, n) 56 + local met = starlit.world.material.metal.db[x] 57 + return lib.math.si('g', n) .. ' ' .. met.name 58 + end; 59 + image = function(x, n) 60 + local met = starlit.world.material.metal.db[x] 61 + return ItemStack(met.form.ingot):get_definition().inventory_image 62 + end; 63 + op = fQuant; 64 + }; 65 + liquid = { 66 + name = {"liquid", "liquids"}; 67 + string = function(x, n) 68 + local liq = starlit.world.material.liquid.db[x] 69 + return lib.math.si('L', n) .. ' ' .. liq.name 70 + end; 71 + op = fQuant; 72 + }; 73 + gas = { 74 + name = {"gas", "gasses"}; 75 + string = function(x, n) 76 + local gas = starlit.world.material.gas.db[x] 77 + return lib.math.si('g', n) .. ' ' .. gas.name 78 + end; 79 + op = fQuant; 80 + }; 81 +-- crystal = { 82 +-- op = fQuant; 83 +-- }; 84 + item = { 85 + name = {"item", "items"}; 86 + string = function(x, n) 87 + local i = minetest.registered_items[x] 88 + return tostring(n) .. 'x ' .. i.short_description 89 + end; 90 + }; 91 + 47 92 -- factors 48 - cost = fFac; -- units vary 49 - time = fFac; -- (s) 93 + 94 + cost = {op=fFac}; -- units vary 95 + time = {op=fFac}; -- (s) 50 96 -- print: base printing time 51 - size = fSize; 97 + size = {op=fSize}; 52 98 -- printBay: size of the printer bay necessary to produce the item 53 - req = fReq; 54 - flag = fFlag; -- means that can be used to produce the item & misc flags 99 + req = {op=fReq}; 100 + flag = {op=fFlag}; -- means that can be used to produce the item & misc flags 55 101 -- print: allow production with a printer 56 102 -- smelt: allow production with a smelter 57 103 -- all else defaults to underwrite 58 104 } 59 105 60 -local F = string.format 61 -local strClass = { 62 - element = function(x, n) 63 - local el = starlit.world.material.element[x] 64 - return lib.math.si('g', n) .. ' ' .. (el.sym or el.name) 65 - end; 66 - metal = function(x, n) 67 - local met = starlit.world.material.metal[x] 68 - return lib.math.si('g', n) .. ' ' .. met.name 69 - end; 70 - liquid = function(x, n) 71 - local liq = starlit.world.material.liquid[x] 72 - return lib.math.si('L', n) .. ' ' .. liq.name 73 - end; 74 - gas = function(x, n) 75 - local gas = starlit.world.material.gas[x] 76 - return lib.math.si('g', n) .. ' ' .. gas.name 77 - end; 78 - item = function(x, n) 79 - local i = minetest.registered_items[x] 80 - return tostring(n) .. 'x ' .. i.short_description 81 - end; 82 -} 83 - 84 106 local order = { 85 107 'element', 'metal', 'liquid', 'gas', 'item' 86 108 } 87 109 88 110 local lib = starlit.mod.lib 89 111 90 112 local fab fab = lib.class { 91 113 __name = 'starlit:fab'; 92 114 93 - opClass = opClass; 94 - strClass = strClass; 115 + fields = fields; 95 116 order = order; 96 117 construct = function(q) return q end; 97 118 __index = { 98 119 elementalize = function(self) 99 120 local e = fab {element = self.element or {}} 100 121 for _, kind in pairs {'metal', 'gas', 'liquid'} do 101 122 for m,mass in pairs(self[kind] or {}) do ................................................................................ 154 175 local fml = {} 155 176 for i, v in ipairs(sub) do fml[i] = v.f end 156 177 if f then table.insert(fml, f) end 157 178 fml = table.concat(fml, ' + ') 158 179 159 180 return fml, ts 160 181 end; 182 + 183 + visualize = function(self) 184 + local all = {} 185 + for i,o in ipairs(order) do 186 + local t = {} 187 + if self[o] then 188 + for mat,amt in pairs(self[o]) do 189 + local v = {} 190 + v.id = mat 191 + v.n = amt 192 + if fields[o].string then 193 + v.label = fields[o].string(mat,amt,true) 194 + end 195 + if fields[o].image then 196 + v.img = fields[o].image(mat,amt) 197 + end 198 + table.insert(t,v) 199 + end 200 + end 201 + if fields[o].sort then 202 + table.sort(t, function(a,b) return fields[o].sort(a.id, b.id) end) 203 + end 204 + if next(t) then table.insert(all, { 205 + id=o, list=t; 206 + header=fields[o].name[t[2] and 2 or 1]; 207 + }) end 208 + end 209 + return all 210 + end; 161 211 }; 162 212 163 213 __tostring = function(self) 164 214 local t = {} 165 215 for i,o in ipairs(order) do 166 - if self[o] then 216 + if self[o] and fields[o].string then 167 217 for mat,amt in pairs(self[o]) do 168 218 if amt > 0 then 169 - table.insert(t, strClass[o](mat, amt)) 219 + table.insert(t, fields[o].string(mat, amt)) 170 220 end 171 221 end 172 222 end 173 223 end 174 224 return table.concat(t, ", ") 175 225 end; 176 - 177 226 178 227 __add = function(a,b) 179 228 local new = fab {} 180 229 for cat, vals in pairs(a) do 181 230 new[cat] = lib.tbl.copy(vals) 182 231 end 183 232 for cat, vals in pairs(b) do 184 233 if not new[cat] then 185 234 new[cat] = lib.tbl.copy(vals) 186 235 else 187 - local f = opClass[cat] 236 + local f = fields[cat].op 188 237 for k,v in pairs(vals) do 189 238 local n = f(new[cat][k], v, 1) 190 239 new[cat][k] = n > 0 and n or nil 191 240 end 192 241 end 193 242 end 194 243 return new 195 244 end; 196 245 197 246 __mul = function(x,n) 198 247 local new = fab {} 199 248 for cat, vals in pairs(x) do 200 249 new[cat] = {} 201 - local f = opClass[cat] 250 + local f = fields[cat].op 202 251 for k,v in pairs(vals) do 203 252 local num = f(v,nil,n) 204 253 new[cat][k] = num > 0 and num or nil 205 254 end 206 255 end 207 256 return new 208 257 end;
Added mods/starlit/food.lua version [c58f501acb].
1 +local F = starlit.item.food 2 +local lib = starlit.mod.lib 3 + 4 +function F.impact(stack,f) 5 + if stack and not f then f = stack:get_definition()._starlit.food end 6 + local impact = f.impact and starlit.type.impact.clone(f.impact) or starlit.type.impact{} 7 + 8 + if impact.taste then 9 + local aff = impact.taste > 0 and 'good' or 'bad' 10 + table.insert(impact, {'taste', aff, {'morale', impact.taste}}) 11 + end 12 + 13 + if stack then 14 + impact = impact:effective(stack) 15 + end 16 + 17 + return impact 18 +end 19 + 20 +local function foodTip(stack, f) 21 + local impact = F.impact(stack,f) 22 + local props = impact:propTable() 23 + 24 + if f.mass then 25 + table.insert(props, { 26 + title='Mass', affinity='info'; 27 + desc = lib.math.si('g', f.mass, nil, nil, 2); 28 + }) 29 + end 30 + 31 + return starlit.ui.tooltip { 32 + title = f.name; 33 + desc = f.desc; 34 + props = props; 35 + color = f.color; 36 + }; 37 +end 38 + 39 +F.foreach('starlit:gen-food', {}, function(id, f) 40 + minetest.register_item(id, { 41 + type = f.itemType or 'none'; 42 + inventory_image = f.tex; 43 + short_description = f.name; 44 + description = foodTip(nil, f); 45 + on_use = function(st, luser) 46 + local user = starlit.activeUsers[luser:get_player_name()] 47 + st:take_item(1) 48 + local imp = F.impact(st,f) 49 + imp:apply(user) 50 + user:suitSound 'starlit-success' -- FIXME need proper eating sound 51 + return st 52 + end; 53 + _starlit = { 54 + food = f; 55 + recover = f.recover; 56 + mass = f.mass; 57 + }; 58 + }) 59 +end) 60 + 61 +starlit.item.seed.foreach('starlit:gen-seed', {}, function(id, s) 62 + minetest.register_item(id, { 63 + type = 'none'; 64 + inventory_image = s.tex; 65 + short_description = s.name; 66 + description = starlit.ui.tooltip { 67 + title = s.name; 68 + color = s.color; 69 + desc = s.desc; 70 + }; 71 + on_place = function() 72 + -- FIXME sow 73 + end; 74 + _starlit = { 75 + seed = s; 76 + mass = s.mass; 77 + }; 78 + }) 79 +end)
Modified mods/starlit/interfaces.lua from [6c49562563] to [e3ed80cb5c].
118 118 end 119 119 120 120 local function abilityMenu(a) 121 121 -- select primary/secondary abilities or activate ritual abilities 122 122 local p = {kind = 'vert'} 123 123 for _, o in ipairs(a.order) do 124 124 local m = a.menu[o] 125 - table.insert(p, {kind='label', text=m.label, w=a.w, h = .5}) 125 + table.insert(p, {kind='hbar', fac=0.5, text=string.format("<b>%s</b>",m.label), w=a.w, h = .5}) 126 126 table.insert(p, wrapMenu(a.w, a.h, 1.2, 2, m.opts)) 127 127 end 128 128 return p 129 129 end 130 130 131 131 local function pptrMatch(a,b) 132 132 if a == nil or b == nil then return false end ................................................................................ 459 459 return true 460 460 end 461 461 end; 462 462 }; 463 463 }; 464 464 }) 465 465 466 +-- TODO destroy suit interfaces when power runs out or suit/chip is otherwise disabled 466 467 starlit.interface.install(starlit.type.ui { 467 468 id = 'starlit:compile-matter-component'; 469 + sub = { 470 + suit = function(state, user, evt) 471 + if evt.kind == 'disrobe' then state:close() 472 + elseif evt.kind == 'power' and evt.mode == 'off' then state:close() end 473 + end; 474 + playerInventory = function(state,user) 475 + -- refresh 476 + end; 477 + }; 468 478 pages = { 469 479 index = { 470 480 setupState = function(state, user, ctx) 471 - if ctx.context == 'suit' then 472 - end 473 481 state.pgm = ctx.program 482 + state.select = {} 483 + local E = starlit.mod.electronics 484 + if ctx.context == 'suit' then 485 + state.fetch = function() 486 + local cst = user.entity:get_inventory():get_list 'starlit_suit_chips' 487 + local cl = {order={}, map={}} 488 + for i, c in ipairs(cst) do 489 + if not c:is_empty() then 490 + local d = E.chip.read(c) 491 + local co = { 492 + stack = c; 493 + data = d; 494 + } 495 + table.insert(cl.order, co) 496 + cl.map[d.uuid] = co 497 + end 498 + end 499 + if state.select.chip and not cl.map[state.select.chip.data.uuid] then 500 + -- chip no longer available 501 + user:suitSound 'starlit-error' 502 + state.select = {} 503 + end 504 + state.select.chips = cl 505 + 506 + state.select.scms = {} 507 + if state.select.chip then 508 + state.select.scms = E.chip.usableSoftware({state.select.chip.stack},nil, 509 + function(s) return s.sw.kind == 'schematic' end) 510 + end 511 + end 512 + end 513 + end; 514 + 515 + onClose = function(state, user) 516 + user:suitSound 'starlit-quit' 517 + end; 518 + handle = function(state, user, q) 519 + local sel = state.select 520 + state.fetch() 521 + local chips = state.select.chips 522 + local function chirp() 523 + user:suitSound 'starlit-nav' 524 + end 525 + local function onPickChip(chip) 526 + chirp() 527 + sel.chip = chip 528 + return true 529 + end 530 + local function onPickScm(scm) 531 + chirp() 532 + sel.scm = scm 533 + return true 534 + end 535 + 536 + if sel.chip == nil then 537 + for k in next, q do 538 + local id = k:match "^chip_(%d+)$" 539 + if id then 540 + local cm = chips.map[tonumber(id)] 541 + if cm then return onPickChip(cm) end 542 + end 543 + end 544 + elseif sel.scm == nil then 545 + if q.back then chirp() sel.chip = nil return true end 546 + for k in next, q do 547 + local id = k:match "^scm_(%d+)$" 548 + if id then 549 + local cm = state.select.scms[tonumber(id)] 550 + if cm then return onPickScm(cm) end 551 + end 552 + end 553 + else 554 + if q.back then chirp() sel.scm = nil return true end 555 + end 474 556 end; 557 + 475 558 render = function(state, user) 559 + local sel, pgmSelector = state.select, {} 560 + state.fetch() 561 + 562 + local function pushSelector(id, item, label, desc, req) 563 + local rh = .5 564 + local label = {kind = 'text', w = 10-1.5, h=1.5; 565 + text = '<global valign=middle>'..label } 566 + if req then 567 + label.h = label.h - rh - .2 568 + 569 + local imgs = {} 570 + for ci,c in ipairs(req) do 571 + for ei, e in ipairs(c.list) do 572 + table.insert(imgs, {kind = 'img', w=rh, h=rh, img=e.img}) 573 + end 574 + end 575 + label = {kind = 'vert', w = 10-1.5, h=1.5; 576 + label; 577 + {kind ='hztl', w=10-1.5, h=rh; unpack(imgs); } 578 + } 579 + end 580 + table.insert(pgmSelector, {kind = 'hztl', w=10,h=1.5; 581 + {kind = 'contact', id=id, w=1.5, h=1.5; 582 + item = item; 583 + color = {hue=220, sat=0, lum=0}; 584 + desc = desc; 585 + }; 586 + label; 587 + }) 588 + end 589 + 590 + local back = {kind = 'button', id='back', label = '<- Back', w=10,h=1.2} 591 + if sel.chips == nil then 592 + table.insert(pgmSelector, {kind = 'img', img = 'starlit-ui-alert.png', w=2, h=2}) 593 + elseif sel.chip == nil then 594 + for i, c in ipairs(sel.chips.order) do 595 + -- TODO filter out chips without schematics? 596 + pushSelector('chip_' .. c.data.uuid, c.stack, c.data.label) 597 + end 598 + else 599 + if sel.scm == nil then 600 + for idx, ent in ipairs(sel.scms) do 601 + local fab = ItemStack(ent.sw.output):get_definition()._starlit.fab 602 + if fab.flag.print then 603 + local req = fab:visualize() 604 + pushSelector('scm_' .. idx, ent.sw.output, ent.sw.name, nil, req) 605 + end 606 + end 607 + table.insert(pgmSelector, back) 608 + else 609 + local output = ItemStack(sel.scm.sw.output):get_definition() 610 + local fab = output._starlit.fab 611 + local sw = sel.scm.sw 612 + table.insert(pgmSelector, {kind = 'hztl', w=10, h=1.2; 613 + {kind = 'img', item = sw.output, w=1.2, h=1.2, desc=output.description}; 614 + {kind = 'text', text = string.format('<global valign=middle><b>%s</b>', sw.name), w=10-1.2,h=1.2}; 615 + }) 616 + local inputTbl = {kind = 'vert', w=5,h=0; 617 + {kind = 'hbar', w=5, h=.5, text='Input'}}; 618 + local costTbl = {kind = 'vert', w=5,h=0; spacing=.25; 619 + {kind = 'hbar', w=5, h=.5, text='Process'}}; 620 + local reqPane = {kind = 'pane', id='reqPane', w=10, h=7; 621 + {kind = 'hztl', w=10,h=0; inputTbl, costTbl} 622 + } 623 + local req = fab:visualize() 624 + for ci,c in ipairs(req) do 625 + table.insert(inputTbl, {kind = 'label', w=4.5, h=1, x=.5; 626 + text=lib.str.capitalize(c.header)}); 627 + for ei,e in ipairs(c.list) do 628 + table.insert(inputTbl, {kind = 'hztl', w=4, h=.5, x=1; 629 + {kind='img', w=.5,h=.5, img=e.img}; 630 + {kind='label', w=3.3,h=.5,x=.2, text=e.label}; 631 + }); 632 + end 633 + end 634 + if sw.cost then 635 + local function pushCost(t, val) 636 + table.insert(costTbl, {kind='text', w=4.5,h=.5,x=.5; 637 + text=string.format('<b>%s</b>: %s',t,val); 638 + }) 639 + end 640 + if sw.cost.cycles then 641 + pushCost('Energy', lib.math.siUI('J', sel.scm.powerCost)) 642 + pushCost('Compute', lib.math.siUI({'cycle','cycles'}, sw.cost.cycles, true)) 643 + end 644 + end 645 + table.insert(pgmSelector, reqPane) 646 + table.insert(pgmSelector, {kind = 'hztl', w=10,h=1.2; 647 + {kind = 'button', id='back', label = '<- Back', w=5,h=1.2}; 648 + {kind = 'button', id='print', label = 'Print ->', w=5,h=1.2, color={hue=120,sat=0,lum=0}}; 649 + }) 650 + end 651 + end 652 + 476 653 return starlit.ui.build { 477 - kind = 'vert', padding = 0.5; w = 5, h = 5, mode = 'sw'; 478 - {kind = 'label', w = 4, h = 1, text = 'hello'}; 654 + kind = 'hztl', padding = 0.5; w = 20, h = 10, mode = 'sw'; 655 + {kind = 'vert', w = 5, h = 5; 656 + {kind = 'hbar', fac=0, w = 5, h = .5, text = '<b><left>Recent Prints</left></b>'}; 657 + }; 658 + {kind = 'vert', w = 10, h = 10; 659 + {kind = 'hbar', fac=0, w = 10, h = .5, text = '<b>Program Select</b>'}; 660 + {kind = 'pane', w = 10, h = 9.5, id='pgmSelect'; 661 + unpack(pgmSelector) 662 + }; 663 + }; 664 + {kind = 'vert', w = 5, h = 10; 665 + {kind = 'hbar', fac=0, w = 5, h = .5, text = '<b><right>Print Queue</right></b>'}; 666 + }; 479 667 } 480 668 end; 481 669 }; 482 670 }; 483 671 })
Modified mods/starlit/species.lua from [47cb5f4a38] to [34f8558850].
105 105 lungCapacity = .6; 106 106 sturdiness = 0; -- women are more fragile and thus susceptible to blunt force trauma 107 107 metabolism = .150; -- kCal/s 108 108 painTolerance = 0.4; 109 109 dehydration = 10e-4; -- L/s 110 110 speed = 1.1; 111 111 staminaRegen = 10.0; 112 - psiRegen = 1.3; 112 + psiRegen = 0.05; -- ψ/s 113 113 psiPower = 1.2; 114 114 }; 115 115 }; 116 116 male = { 117 117 name = 'Human Male'; 118 118 eyeHeight = 1.6; 119 119 stats = { ................................................................................ 126 126 health = 500; 127 127 painTolerance = 1.0; 128 128 lungCapacity = 1.0; 129 129 sturdiness = 0.3; 130 130 metabolism = .150; -- kCal/s 131 131 dehydration = 15e-4; -- L/s 132 132 speed = 1.0; 133 - psiRegen = 1.0; 133 + psiRegen = 0.025; 134 134 psiPower = 1.0; 135 135 }; 136 136 }; 137 137 }; 138 138 traits = {}; 139 139 abilities = {bioAbilities.sprint}; 140 140 };
Modified mods/starlit/stats.lua from [3922a2ec73] to [0688acc2a6].
18 18 end 19 19 end 20 20 21 21 local function C(h, s, l) 22 22 return lib.color {hue = h, sat = s or 1, lum = l or .7} 23 23 end 24 24 starlit.world.stats = { 25 - psi = {min = 0, max = 500, base = 0, desc = U('ψ', 10), color = C(320), name = 'numina'}; 26 - -- numina is measured in daψ 25 + psi = {min = 0, max = 500, base = 0, desc = U('ψ', 1), color = C(320), name = 'numina', srzType = T.decimal}; 26 + -- numina is measured in ψ 27 27 warmth = {min = -1000, max = 1000, base = 0, desc = U('°C', 10, true), color = C(5), name = 'warmth'}; 28 28 -- warmth in measured in d°C 29 29 fatigue = {min = 0, max = 76 * 60, base = 0, desc = U('hr', 60, true), color = C(288,.3,.5), name = 'fatigue', harm=true, srzType = T.decimal}; 30 30 -- fatigue is measured in minutes one needs to sleep to cure it 31 31 stamina = {min = 0, max = 10 * 20, base = true, desc = U('m', 100), color = C(88), name = 'stamina'}; 32 32 -- stamina is measured in how many 10th-nodes (== cm) one can sprint 33 33 nutrition = {min = 0, max = 8000, base = 0, desc = U('kCal', 1, true), color = C(43,.5,.4), name = 'nutrition', srzType = T.decimal};
Modified mods/starlit/ui.lua from [7085b387cd] to [81aedb85b1].
29 29 end 30 30 local created = state == nil 31 31 32 32 if not state then 33 33 state = { 34 34 page = page or 'index'; 35 35 form = self.id; 36 + self = self; 37 + close = function() self:close(user) end; 36 38 } 37 39 starlit.activeUI[user.name] = state 38 40 self:cb('setupState', user, ...) 39 41 elseif page ~= nil and state.page ~= page then 40 42 state.page = page 41 43 local psetup = self.pages[state.page].setupState 42 44 if psetup then psetup(state,user, ...) end ................................................................................ 148 150 widget('container[%s,%s]%scontainer_end[]', state.x, state.y, src) 149 151 -- TODO alignments 150 152 state.x=state.x + state.spacing + st.w 151 153 state.h = math.max(state.h, st.h) 152 154 end 153 155 state.h = state.h + state.padding 154 156 state.w = state.x + state.padding/2 157 + elseif def.kind == 'pane' then 158 + widget('scroll_container[%s,%s;%s,%s;%s;vertical]', 159 + state.x, state.y, state.w, state.h, 160 + def.id) 161 + local y = 0 162 + for _, w in ipairs(def) do 163 + local src, st = starlit.ui.build(w, state) 164 + widget('container[%s,%s]%scontainer_end[]', 0, y, src) 165 + y=y + state.spacing + st.h 166 + state.w = math.max(state.w, st.w) 167 + end 168 + widget('scroll_container_end[]') 169 + if y > state.h then 170 + widget('scrollbar[%s,%s;%s,%s;vertical;%s;]', 171 + state.x, state.y, .5, state.h, 172 + def.id) 173 + end 174 + state.w = state.w + state.padding 175 + state.h = state.h + state.padding/2 155 176 elseif def.kind == 'list' then 156 177 local slotTypes = { 157 178 plain = {hue = 200, sat = -.1, lum = 0}; 158 179 element = {hue = 20, sat = -.3, lum = 0}; 159 180 chip = {hue = 0, sat = -1, lum = 0}; 160 181 psi = {hue = 300, sat = 0, lum = 0}; 161 182 power = {hue = 50, sat = 0, lum = .2}; ................................................................................ 181 202 def.w, def.h, 182 203 def.idx)) 183 204 local sm = 1 184 205 state.w = def.w * sm + (spac * (def.w - 1)) 185 206 state.h = def.h * sm + (spac * (def.h - 1)) 186 207 elseif def.kind == 'contact' then 187 208 if def.color then table.insert(lines, btnColorDef(def.id)) end 188 - widget('image_button%s[%s,%s;%s,%s;%s;%s;%s]', 209 + local img = def.img 210 + local desc 211 + if def.item then 212 + img = ItemStack(def.item):get_name() 213 + desc = ItemStack(def.item):get_description() 214 + end 215 + widget('%simage_button%s[%s,%s;%s,%s;%s;%s;%s]', 216 + def.item and 'item_' or '', 189 217 def.close and '_exit' or '', 190 218 state.x, state.y, def.w, def.h, 191 - E(def.img), E(def.id), E(def.label or '')) 219 + E(img), E(def.id), E(def.label or '')) 220 + if desc and not def.desc then 221 + widget('tooltip[%s;%s]', E(def.id), E(desc)) 222 + end 192 223 elseif def.kind == 'button' then 193 224 if def.color then table.insert(lines, btnColorDef(def.id)) end 194 225 local label = E(def.label or '') 195 226 if state.fg then label = lib.color(state.fg):fmt(label) end 196 227 widget('button%s[%s,%s;%s,%s;%s;%s]', 197 228 def.close and '_exit' or '', 198 229 state.x, state.y, def.w, def.h, ................................................................................ 210 241 -- TODO paragraph formatter 211 242 widget('hypertext[%s,%s;%s,%s;%s;%s]', 212 243 state.x, state.y, def.w, def.h, E(def.id), E(def.text)) 213 244 elseif def.kind == 'hbar' or def.kind == 'vbar' then -- TODO fancy image bars 214 245 local cl = lib.color(state.color) 215 246 local fg = state.fg or cl:readable(.8,1) 216 247 local wfac, hfac = 1,1 217 - local clamp = math.min(math.max(def.fac, 0), 1) 248 + local clamp = math.min(math.max(def.fac or 0, 0), 1) 218 249 if def.kind == 'hbar' 219 250 then wfac = wfac * clamp 220 251 else hfac = hfac * clamp 221 252 end 222 253 local x,y, w,h = state.x, state.y, def.w, def.h 223 254 widget('box[%s,%s;%s,%s;%s]', 224 255 x,y, w,h, cl:brighten(0.2):hex()) ................................................................................ 228 259 widget('hypertext[%s,%s;%s,%s;;%s]', 229 260 state.x, state.y, def.w, def.h, 230 261 string.format('<global halign=center valign=middle color=%s>%s', fg:hex(), E(def.text))) 231 262 end 232 263 end 233 264 234 265 if def.desc then 235 - widget('tooltip[%s,%s;%s,%s;%s]', 236 - state.x, state.y, def.w, def.h, E(def.desc)) 266 + local coord 267 + if def.id then 268 + coord = E(def.id) 269 + else 270 + coord = string.format("%s,%s;%s,%s", state.x, state.y, def.w, def.h) 271 + end 272 + widget('tooltip[%s;%s;#000000;#ffffff]', coord, E(def.desc)) 237 273 end 238 274 239 275 local originX = (parent and parent.x or 0) 240 276 local originY = (parent and parent.y or 0) 241 277 local l = table.concat(lines) 242 278 -- if state.fixed and (state.w < state.x or state.h < state.y) then 243 279 -- l = string.format('scroll_container[%s,%s;%s,%s;scroll_%s;%s]%sscroll_container_end[]',
Modified mods/vtlib/math.lua from [3edc02f291] to [43eaf4251e].
38 38 {12, 'T', 'tera', true, 'p', 'pico', true}; 39 39 {9, 'G', 'giga', true, 'n', 'nano', true}; 40 40 {6, 'M', 'mega', true, 'μ', 'micro', true}; 41 41 {3, 'k', 'kilo', true, 'm', 'milli', true}; 42 42 {2, 'h', 'hecto', false, 'c', 'centi', true}; 43 43 {1, 'da','deca', false, 'd', 'deci', false}; 44 44 } 45 + 46 + local function unitForAmt(n) 47 + if type(unit)=='table' then 48 + if n == 1 49 + then return unit[1] 50 + else return unit[2] 51 + end 52 + end 53 + return unit 54 + end 55 + 45 56 for i, s in ipairs(scales) do 46 57 local amt, smaj, pmaj, cmaj, 47 58 smin, pmin, cmin = lib.tbl.unpack(s) 59 + 48 60 49 61 if math.abs(val) > 1 then 50 62 if uncommonScales or cmaj then 51 63 local denom = 10^amt 52 64 local vd = val/denom 53 65 if prec then vd = lib.math.trim(vd, prec) end 54 66 if math.abs(val) >= (10^(amt)) then 55 67 return string.format("%s%s%s", 56 - vd, (full and (' ' .. pmaj) or smaj), unit) 68 + vd, (full and (' ' .. pmaj) or smaj), unitForAmt(vd)) 57 69 end 58 70 end 59 71 elseif math.abs(val) < 1 then 60 72 if uncommonScales or cmin then 61 73 local denom = 10^-amt 62 74 local vd = val/denom 63 75 if prec then vd = lib.math.trim(vd, prec) end 64 76 if math.abs(val) <= (10^-(amt-1)) then 65 77 return string.format("%s%s%s", 66 - vd, (full and (' ' .. pmin) or smin), unit) 78 + vd, (full and (' ' .. pmin) or smin), unitForAmt(vd)) 67 79 end 68 80 end 69 81 end 70 82 end 71 83 72 - return string.format("%s%s", val, unit) 84 + return string.format("%s%s", val, unitForAmt(val)) 73 85 end 86 +function fn.siUI(u,v,f,us,...) return fn.si(u,v,f,us,2,...) end 74 87 75 88 function fn.lerp(t, a, b) return (1-t)*a + t*b end 76 89 function fn.gradient(grad, pos) 77 90 local n = #grad 78 91 if n == 1 then return grad[1] end 79 92 local op = pos*(n-1) 80 93 local idx = math.floor(op)
Added src/sfx/alarm-urgent.csd version [d5c9b81dc6].
1 +; [ʞ] alarm-urgent.csd 2 +; ~ lexi hale <lexi@hale.su> 3 +; 🄯 CC-NC-BY-SA 3.0 4 +; ? VERY angry blarp fer when the bad is done to ya 5 + 6 +<CsoundSynthesizer> 7 + 8 +<CsInstruments> 9 +#include "dqual.inc" 10 +#include "digital.orc" 11 +</CsInstruments> 12 + 13 +<CsScore> 14 +i"chirp" 0.00 0.20 0.20 30 1700 15 +i"chirp" 0.20 0.40 0.20 5 1000 16 +i"blare" 0.10 0.40 0.8 17 +i"blarp" 0.40 0.70 0.6 18 +e 0.9 19 +</CsScore> 20 + 21 +</CsoundSynthesizer>
Added src/sfx/alarm.csd version [db2a0672cb].
1 +; [ʞ] alarm.csd 2 +; ~ lexi hale <lexi@hale.su> 3 +; 🄯 CC-NC-BY-SA 3.0 4 +; ? angry blarp fer when the bad is done to ya 5 + 6 +<CsoundSynthesizer> 7 + 8 +<CsInstruments> 9 +#include "dqual.inc" 10 +#include "digital.orc" 11 +</CsInstruments> 12 + 13 +<CsScore> 14 +i"chirp" 0.00 0.40 0.20 5 1000 15 +i"blarp" 0.20 0.70 0.6 16 +e 0.9 17 +</CsScore> 18 + 19 +</CsoundSynthesizer>
Added src/sfx/quit.csd version [c4d80c8f7f].
1 +; [ʞ] quit.csd 2 +; ~ lexi hale <lexi@hale.su> 3 +; 🄯 CC-NC-BY-SA 3.0 4 +; ? choopy chorp for when ya log the off 5 + 6 +<CsoundSynthesizer> 7 + 8 +<CsInstruments> 9 +#include "dqual.inc" 10 +#include "digital.orc" 11 +</CsInstruments> 12 + 13 +<CsScore> 14 +i"chirp" 0.00 0.10 0.10 20 4000 15 +i"chirp" 0.15 0.20 0.10 20 2000 16 +e 0.3 17 +</CsScore> 18 + 19 +</CsoundSynthesizer>