run file "core.nom" run file "lib/secrets.nom" with secrets: rule: pending proposal ..=: secret %pending rule: propose source %src ..=: secret %pending =: %src say ".." |Proposal\%src\ macro block: propose %action ..=: ".." |compiler:call("propose source %", \repr (%action's "src")\) rule: approve ..=: if (pending proposal): say ".." |Running\pending proposal\ do (..) eval ".." |return: \pending proposal\ ..else: say "No action pending" propose: say "motion passed." rule: fart ..=: say "poot" approve fart # Users: with secrets: secret %users =: lua expr "require('users')" rule: find user %name ..=: lua expr "secrets.users.by_name(vars.name) or compiler:error('Failed to find user: '..tostring(vars.name))" rule: add user %name ..=: lua expr "secrets.users.add(vars.name)" macro: @ %name_block ..=: %name_str =: lua expr "vars.name_block.value.value.src" ".."|compiler:call("find user %", \repr %name_str\) say ".."|A user looks like: \@:spill\ say ".."|A user looks like: \@:spill\ add user "dave" say ".."|A user looks like: \@:dave\ add user "moloch" say ".."|A user looks like: \@:moloch\ add user "bruce" # Inventory: with secrets: secret %inventory =: lua expr ".." |setmetatable({}, {__index=function(self,key) | local t = {} | self[key] = t | return t |end}) with secrets: lua block ".." |local endings = setmetatable({x="es",c="es",s="es"}, {__index=function() return "s" end}) |secrets.plurals = setmetatable({}, {__index=function(self,key) | return key..endings[key:sub(-1)] |end}) |secrets.singulars = setmetatable({}, {__index=function(self,key) | if key:sub(-2) == "es" and rawget(endings, key:sub(-3,-3)) then return key:sub(1,-3) end | if key:sub(-1) == "s" then return key:sub(1,-2) end | return key |end}) |secrets.canonicals = setmetatable({}, {__index=function(self,key) | if key:sub(-1) == "s" then return secrets.singulars[key] end | return key |end}) rule: the plural of %singular is %plural ..=: (secret %plurals)->%singular =: %plural (secret %singulars)->%plural =: %singular (secret %canonicals)->%plural =: %singular rule: singular %plural ..=: %plural in (secret %singulars) rule: plural %singular ..=: %singular in (secret %plurals) rule: canonicalize %item-name ..=: %item-name in (secret %canonicals) rule: %person's inventory ..=: (secret %inventory)->%person rule: %person's stock of %item ..=: %item =: canonicalize %item ((%person's inventory)->%item) or 0 rule: %person's stock of %item as str ..=: %item =: canonicalize %item %count =: %person's stock of %item ".." |\%count\ \(singular %item) if (%count == 1) else (plural %item)\ rule: give %person %count %item ..=: %item =: canonicalize %item (%person's inventory)-> %item =: (%person's stock of %item) + %count rule: give %person %count %item from %donor ..=: %item =: canonicalize %item if ((%donor's stock of %item) < %count): say ".." |\%donor\ does not have enough \%item\ to transfer ..else: (%person's inventory)->%item =: (%person's stock of %item) + %count (%donor's inventory)->%item =: (%donor's stock of %item) - %count rule: %person has %item %person has a %item %person has an %item ..=: (%person's stock of %item) > 0 give (@:bruce) 3 "hats" give (@:bruce) 3 "hats" give (@:dave) 1 "hat" from (@:bruce) say ".."|Bruce has \(@:bruce)'s stock of "hats" as str\ say ".."|Dave has \(@:dave)'s stock of "hats" as str\ give (@:dave) 1 "box" say ".."|Dave has \(@:dave)'s stock of "boxes" as str\ the plural of "goose" is "geese" give (@:dave) 1 "goose" say ".."|Dave has \(@:dave)'s stock of "geese" as str\ give (@:dave) 1 "goose" say ".."|Dave has \(@:dave)'s stock of "geese" as str\ do: lua block "math.randomseed(os.time())" repeat until ((random number) < 0.01): say "tick" say "tock" # A basic key-value store that's only accessible through these functions: lua block ".." |do -- Use a closure to hide this behind the accessor rules | local relations = setmetatable({}, {__index=function(self,key) | local t = {} | self[key] = t | return t | end}) | compiler:def("%key %relation ?", function(_,vars) | return relations[vars.relation][vars.key] | end) | compiler:def("%key %relation = %value", function(_,vars) | relations[vars.relation][vars.key] = vars.value | end) | compiler:def("* %relation = %value", function(_,vars) | local result = {} | for k,v in pairs(relations[vars.relation]) do | if utils.equivalent(v, vars.value) then | table.insert(result, k) | end | end | return result | end) |end rule "set all * %relation = %value": for "key" in (* %relation = %value): %key %relation = %value rule "you": lua expr "(you or 'Anonymous')" rule ["make %person %action", "make %person do %action"]: lua block ".." |do | local old_you = you | you = vars.person | ret = compiler:call('do %', vars.action) | you = old_you |end say "====================================================" say " NEW GAME" say "====================================================" rule "everyone approves %action": yes rule "with everyone's approval %action": if (everyone approves %action): do %action ..else: say "You do not have the will of the people! >:(" restrict "rule % %" to within "with everyone's approval %" restrict "make % %" to within "with everyone's approval %" restrict "set all * % = %" to within "with everyone's approval %" restrict "% % = %" to within "with everyone's approval %" restrict "restrict % to within %" to within "with everyone's approval %" with everyone's approval: rule "propose %action": if ("pending proposal" "is" ?): say "Sorry, an action is already pending." ..else: say "Proposing..." "pending proposal" "is" = %action rule "unpropose": let "pending" = ("pending proposal" "is" ?) set all * %pending = (nil) "pending proposal" "is" = (nil) rule "mark %who as approving %action": %who %action = "approved" rule "mark %who as rejecting %action": %who %action = "rejected" rule ["approve", "vote yes", "vote yea"]: let "pending" = ("pending proposal" "is" ?) if (%pending == (nil)): say "Nothing is currently pending!" return mark (you) as approving %pending if (everyone approves %pending): say "The motion passes!" with everyone's approval %pending unpropose ..else: let "approvers" = (number of (* %pending = "approved")) let "num-players" = (number of (players)) say ".." |\number of (* %pending = "approved")\/\number of (players)\ players have approved. rule ["reject", "vote no", "vote nay", "veto", "disapprove"]: let "pending" = ("pending proposal" "is" ?) if (%pending == (nil)): say "Nothing is currently pending!" return mark (you) as rejecting %pending unpropose rule ["players", "everyone", "everybody", "all players"]: * "is a player" = (yes) rule "join": (you) "is a player" = (yes) say ".." |Welcome to the game, \you\! allow "unpropose" to use "set all * % = %" allow ["join", "mark % as approving %", "mark % as rejecting %", "propose %", "unpropose"] to use "% % = %" restrict "unpropose" to within ["approve", "reject"] restrict "mark % as approving %" to within ["propose %", "approve"] restrict "mark % as rejecting %" to within ["propose %", "reject"] rule "everyone approves %action": (number of (players)) == (number of (* %action = "approved")) join propose: say "fart" approve propose: "democracy" "is possible" = (yes) if ("democracy" "is possible" ?): say "DEMOCRACY WORKS!!!" approve propose: rule "fart": say "poot" say "fart should have been defined" approve say "doop" fart propose: rule "open election %candidates": if ("candidates" "are" ?): say "An election is already in progress." ..else: "candidates" "are" = %candidates rule "close the election": set all * "votes for" = (nil) "candidates" "are" = (nil) rule "vote for %candidate": (you) "votes for" = %candidate let "vote-percent" = ((number of (* "votes for" = %candidate)) / (number of (players))) say ".." |Vote cast. \%candidate\ now has \100 * %vote-percent\% of the votes. if (%vote-percent > 0.5): say ".."|The winner of the election is: \%candidate\ close the election allow ["open election %", "close the election", "vote for %"] to use ["% % = %"] allow ["close the election"] to use ["set all * % = %"] approve propose: rule "as bill %action": if ((you) == "Anonymous"): make "bill" do %action ..else: say ".."|Who do you think you are, \you\? allow ["as bill %"] to use ["make % %"] approve as bill: join propose: rule "as dave %action": if ((you) == "Anonymous"): make "dave" do %action ..else: say ".."|Who do you think you are, \you\? allow ["as dave %"] to use ["make % %"] approve as bill: approve as dave: join open election ["tom", "dick", "harry"] vote for "dick" as bill: vote for "dick" propose: rule "take a shit": say "shit taken." approve as bill: approve as dave: approve take a shit say "Done."