there are fancy formal languages for this sort of thing, mainly from Planning, e.g.\nTLA (temporal language of action)\nsituation calculus\nevent calculus\n\nthese are modal logics where truth is indexed by time\n<<continue "}}}>>\nthey usually don't give you a "frame rule" for free, so at each time step you have to update everything that doesn't change:\n\nA[t] -> A[t+1]\n\nLinear Logic solves this problem\n(exposit)\n<<continue "}}}">>\nBut PROBLEMS:\n\nit doesn't give us a natural way for encoding actions, loci of control\n\n<pre>do/murder \n: anger C C' * anger C C' * anger C C' * anger C C' *\n at C L * at C' L * has C weapon\n -o {at C L * !dead C' * \n !murdered C C' * has C weapon}.\ndo/thinkVengefully\n: at C L * at Killer L' * \n philia C Dead * murdered Killer Dead\n -o {at C L * at Killer L' * philia C Dead *\n anger C Killer * anger C Killer}.</pre>\n\n*when* can an agent (human or programmatic) interrupt execution? answer in my thesis proposal: <<replace "phases.">>(the ability to partition a logic program into named rulesets, between which control is transfered at <i>quiescence</i>)<<endreplace>>
I. [[The Interactive Simulation]] <<if $part1>>[✓]<<endif>>\nII. [[Simulations in Linear Logic Programming]]<<if$part2>>[✓]<<endif>>\nIII. [[~Interactivity~]]<<if $part3>>[✓]<<endif>>\nIV. [[Pie in the Sky]]<<if$part4>>[✓]<<endif>>\nV. <a href="https://docs.google.com/document/d/1GoROPk65NFGuXF5HwEPyzBmDieVgXrDSnzWc-6g1UWU/edit?usp=sharing">Discussion</a>
(function(){version.extensions.replaceMacrosCombined={major:1,minor:1,revision:1};\nvar nullobj={handler:function(){}};function showVer(n,notrans){n.innerHTML="";\nnew Wikifier(n,n.tweecode);n.setAttribute("data-enabled","true");\nn.style.display="inline";n.classList.remove("revision-span-out");\nif(!notrans){n.classList.add("revision-span-in");if(n.timeout){clearTimeout(n.timeout)\n}n.timeout=setTimeout(function(){n.classList.remove("revision-span-in");\nn=null},1)}}function hideVer(n,notrans){n.setAttribute("data-enabled","false");\nn.classList.remove("revision-span-in");if(n.timeout){clearTimeout(n.timeout)\n}if(!notrans){n.classList.add("revision-span-out");n.timeout=setTimeout(function(){if(n.getAttribute("data-enabled")=="false"){n.classList.remove("revision-span-out");\nn.style.display="none";n.innerHTML=""}n=null},1000)}else{n.style.display="none";\nn.innerHTML="";n=null}}function tagcontents(b,starttags,desttags,endtags,k){var l=0,c="",tg,a,i;\nfunction tagfound(i,e){for(var j=0;j<e.length;j++){if(a.indexOf("<<"+e[j],i)==i){return e[j]\n}}}a=b.source.slice(k);for(i=0;i<a.length;i++){if(tg=tagfound(i,starttags)){l++\n}else{if((tg=tagfound(i,desttags))&&l==0){b.nextMatch=k+i+tg.length+4;\nreturn[c,tg]}else{if(tg=tagfound(i,endtags)){l--;if(l<0){return null\n}}}}c+=a.charAt(i)}return null}var begintags=[];var endtags=[];\nfunction revisionSpanHandler(g,e,f,b){var k=b.source.indexOf(">>",b.matchStart)+2,vsns=[],vtype=e,flen=f.length,becomes,c,cn,m,h,vsn;\nfunction mkspan(vtype){h=insertElement(m,"span",null,"revision-span "+vtype);\nh.setAttribute("data-enabled",false);h.style.display="none";h.tweecode="";\nreturn h}if(this.shorthand&&flen){while(f.length>0){vsns.push([f.shift(),(this.flavour=="insert"?"gains":"becomes")])\n}}else{if(this.flavour=="insert"||(this.flavour=="continue"&&this.trigger=="time")){vsns.push(["","becomes"])\n}}if(this.flavour=="continue"&&flen){b.nextMatch=k+b.source.slice(k).length;\nvsns.push([b.source.slice(k),vtype])}else{becomes=["becomes","gains"];\nc=tagcontents(b,begintags,becomes.concat(endtags),endtags,k);\nif(c&&endtags.indexOf(c[1])==-1){while(c){vsns.push(c);c=tagcontents(b,begintags,becomes,endtags,b.nextMatch)\n}c=tagcontents(b,begintags,["end"+e],endtags,b.nextMatch)}if(!c){throwError(g,"can't find matching end"+e);\nreturn}vsns.push(c);if(this.flavour=="continue"){k=b.nextMatch;\nb.nextMatch=k+b.source.slice(k).length;vsns.push([b.source.slice(k),""])\n}}if(this.flavour=="remove"){vsns.push(["","becomes"])}cn=0;m=insertElement(g,"span",null,e);\nm.setAttribute("data-flavour",this.flavour);h=mkspan("initial");\nvsn=vsns.shift();h.tweecode=vsn[0];showVer(h,true);while(vsns.length>0){if(vsn){vtype=vsn[1]\n}vsn=vsns.shift();h=mkspan(vtype);h.tweecode=vsn[0]}if(typeof this.setup=="function"){this.setup(m,g,f)\n}}function quantity(m){return(m.children.length-1)+(m.getAttribute("data-flavour")=="remove")\n}function revisionSetup(m,g,f){m.className+=" "+f[0].replace(" ","_")\n}function keySetup(m,g,f){var fl=this.flavour,key=f[0];m.setEventListener("keydown",function l(e){var done=!revise("revise",m);\nif(done){m.removeEventListener("keydown",l)}})}function timeSetup(m,g,f){function cssTimeUnit(s){if(typeof s=="string"){if(s.slice(-2).toLowerCase()=="ms"){return Number(s.slice(0,-2))||0\n}else{if(s.slice(-1).toLowerCase()=="s"){return Number(s.slice(0,-1))*1000||0\n}}}throwError(g,s+" isn't a CSS time unit");return 0}var fl=this.flavour;\nvar tm=cssTimeUnit(f[0]);setTimeout(function timefn(){var done=!revise("revise",m);\nif(!done){setTimeout(timefn,tm)}},tm)}function hoverSetup(m){m.onmouseover=function(){revise("revise",this)\n};m.onmouseout=function(){revise("revert",this)};m=null}function mouseSetup(m){var fl=this.flavour,evt=(window.onmouseenter===null?"onmouseenter":"onmouseover");\nm[evt]=function(){var done=!revise("revise",this);if(done){this[evt]=null\n}};m=null}function linkSetup(m,g,f){var fl=this.flavour,l=Wikifier.createInternalLink(),p=m.parentNode;\nl.className="internalLink replaceLink";p.insertBefore(l,m);l.insertBefore(m,null);\nl.onclick=function(){var p,done=false;if(m&&m.parentNode==this){done=!revise("revise",m);\nscrollWindowTo(m)}if(done){this.parentNode.insertBefore(m,this);\nthis.parentNode.removeChild(this)}};l=null}function visitedSetup(m,g,f){var i,done,shv=state.history[0].variables,os="once seen",d=(m.firstChild&&(this.flavour=="insert"?m.firstChild.nextSibling:m.firstChild).tweecode);\nshv[os]=shv[os]||{};if(d&&!shv[os].hasOwnProperty(d)){shv[os][d]=1\n}else{for(i=shv[os][d];i>0&&!done;i--){done=!revise("revise",m,true)\n}if(shv[os].hasOwnProperty(d)){shv[os][d]+=1}}}[{name:"insert",flavour:"insert",trigger:"link",setup:linkSetup},{name:"timedinsert",flavour:"insert",trigger:"time",setup:timeSetup},{name:"insertion",flavour:"insert",trigger:"revisemacro",setup:revisionSetup},{name:"later",flavour:"insert",trigger:"visited",setup:visitedSetup},{name:"keyinsert",flavour:"insert",trigger:"key",setup:keySetup},{name:"replace",flavour:"replace",trigger:"link",setup:linkSetup},{name:"timedreplace",flavour:"replace",trigger:"time",setup:timeSetup},{name:"mousereplace",flavour:"replace",trigger:"mouse",setup:mouseSetup},{name:"hoverreplace",flavour:"replace",trigger:"hover",setup:hoverSetup},{name:"revision",flavour:"replace",trigger:"revisemacro",setup:revisionSetup},{name:"keyreplace",flavour:"replace",trigger:"key",setup:keySetup},{name:"timedremove",flavour:"remove",trigger:"time",setup:timeSetup},{name:"mouseremove",flavour:"remove",trigger:"mouse",setup:mouseSetup},{name:"hoverremove",flavour:"remove",trigger:"hover",setup:hoverSetup},{name:"removal",flavour:"remove",trigger:"revisemacro",setup:revisionSetup},{name:"once",flavour:"remove",trigger:"visited",setup:visitedSetup},{name:"keyremove",flavour:"remove",trigger:"key",setup:keySetup},{name:"continue",flavour:"continue",trigger:"link",setup:linkSetup},{name:"timedcontinue",flavour:"continue",trigger:"time",setup:timeSetup},{name:"mousecontinue",flavour:"continue",trigger:"mouse",setup:mouseSetup},{name:"keycontinue",flavour:"continue",trigger:"key",setup:keySetup},{name:"cycle",flavour:"cycle",trigger:"revisemacro",setup:revisionSetup},{name:"mousecycle",flavour:"cycle",trigger:"mouse",setup:mouseSetup},{name:"timedcycle",flavour:"cycle",trigger:"time",setup:timeSetup},{name:"keycycle",flavour:"replace",trigger:"key",setup:keySetup}].forEach(function(e){e.handler=revisionSpanHandler;\ne.shorthand=(["link","mouse","hover"].indexOf(e.trigger)>-1);\nmacros[e.name]=e;macros["end"+e.name]=nullobj;begintags.push(e.name);\nendtags.push("end"+e.name)});function insideDepartingSpan(elem){var r=elem.parentNode;\nwhile(!r.classList.contains("passage")){if(r.classList.contains("revision-span-out")){return true\n}r=r.parentNode}}function reviseAll(rt,rname){var rall=document.querySelectorAll(".passage ."+rname),ret=false;\nfor(var i=0;i<rall.length;i++){if(!insideDepartingSpan(rall[i])){ret=revise(rt,rall[i])||ret\n}}return ret}function revise(rt,r,notrans){var ind2,curr,next,ind=-1,rev=(rt=="revert"),rnd=(rt.indexOf("random")>-1),fl=r.getAttribute("data-flavour"),rc=r.childNodes,cyc=(fl=="cycle"),rcl=rc.length-1;\nfunction doToGainerSpans(n,fn){for(var k=n-1;k>=0;k--){if(rc[k+1].classList.contains("gains")){fn(rc[k],notrans)\n}else{break}}}for(var k=0;k<=rcl;k++){if(rc[k].getAttribute("data-enabled")=="true"){ind=k\n}}if(rev){ind-=1}curr=(ind>=0?rc[ind]:(cyc?rc[rcl]:null));ind2=ind;\nif(rnd){ind2=(ind+(Math.floor(Math.random()*rcl)))%rcl}next=((ind2<rcl)?rc[ind2+1]:(cyc?rc[0]:null));\nvar docurr=(rev?showVer:hideVer);var donext=(rev?hideVer:showVer);\nvar currfn=function(){if(!(next&&next.classList.contains("gains"))||rnd){docurr(curr,notrans);\ndoToGainerSpans(ind,docurr,notrans)}};var nextfn=function(){donext(next,notrans);\nif(rnd){doToGainerSpans(ind2+1,donext,notrans)}};if(!rev){currfn();\nnextfn()}else{nextfn();currfn()}return(cyc?true:(rev?(ind>0):(ind2<rcl-1)))\n}macros.revert=macros.revise=macros.randomise=macros.randomize={handler:function(a,b,c){var l,rev,rname;\nfunction disableLink(l){l.style.display="none"}function enableLink(l){l.style.display="inline"\n}function updateLink(l){if(l.className.indexOf("random")>-1){enableLink(l);\nreturn}var rall=document.querySelectorAll(".passage ."+rname),cannext,canprev,i,ind,r,fl;\nfor(i=0;i<rall.length;i++){r=rall[i],fl=r.getAttribute("data-flavour");\nif(insideDepartingSpan(r)){continue}if(fl=="cycle"){cannext=canprev=true\n}else{if(r.firstChild.getAttribute("data-enabled")==!1+""){canprev=true\n}if(r.lastChild.getAttribute("data-enabled")==!1+""){cannext=true\n}}}var can=(l.classList.contains("revert")?canprev:cannext);(can?enableLink:disableLink)(l)\n}function toggleText(w){w.classList.toggle(rl+"Enabled");w.classList.toggle(rl+"Disabled");\nw.style.display=((w.style.display=="none")?"inline":"none")}var rl="reviseLink";\nif(c.length<2){throwError(a,b+" macro needs 2 parameters");return\n}rname=c.shift().replace(" ","_");l=Wikifier.createInternalLink(a,null);\nl.className="internalLink "+rl+" "+rl+"_"+rname+" "+b;var v="";\nvar end=false;var out=false;if(c.length>1&&c[0][0]=="$"){v=c[0].slice(1);\nc.shift()}switch(c[c.length-1]){case"end":end=true;c.pop();break;\ncase"out":out=true;c.pop();break}var h=state.history[0].variables;\nfor(var i=0;i<c.length;i++){var on=(i==Math.max(c.indexOf(h[v]),0));\nvar d=insertElement(null,"span",null,rl+((on)?"En":"Dis")+"abled");\nif(on){h[v]=c[i];l.setAttribute("data-cycle",i)}else{d.style.display="none"\n}insertText(d,c[i]);l.appendChild(d)}l.onclick=function(){reviseAll(b,rname);\nvar t=this.childNodes,u=this.getAttribute("data-cycle")-0,m=t.length,n,lall,i;\nif((end||out)&&u==m-(end?2:1)){if(end){n=this.removeChild(t[u+1]);\nn.className=rl+"End";n.style.display="inline";this.parentNode.replaceChild(n,this)\n}else{this.parentNode.removeChild(this);return}}else{toggleText(t[u]);\nu=(u+1)%m;if(v){h[v]=c[u]}toggleText(t[u]);this.setAttribute("data-cycle",u)\n}lall=document.getElementsByClassName(rl+"_"+rname);for(i=0;i<lall.length;\ni++){updateLink(lall[i])}};l=null}};macros.mouserevise=macros.hoverrevise={handler:function(a,b,c,d){var endtags=["end"+b],evt=(window.onmouseenter===null?"onmouseenter":"onmouseover"),t=tagcontents(d,[b],endtags,endtags,d.source.indexOf(">>",d.matchStart)+2);\nif(t){var rname=c[0].replace(" ","_"),h=insertElement(a,"span",null,"hoverrevise hoverrevise_"+rname),f=function(){var done=!reviseAll("revise",rname);\nif(b!="hoverrevise"&&done){this[evt]=null}};new Wikifier(h,t[0]);\nif(b=="hoverrevise"){h.onmouseover=f;h.onmouseout=function(){reviseAll("revert",rname)\n}}else{h[evt]=f}h=null}}};macros.instantrevise={handler:function(a,b,c,d){reviseAll("revise",c[0].replace(" ","_"))\n}};macros.endmouserevise=nullobj;macros.endhoverrevise=nullobj\n}()); a grammatical model of [X] yields a process for generating [X] \n\ne.g. Vladimir Propp:\ngrammatical model of stories\n-> yields a model of the process of storytelling\n\n<img src="protopropp.png">\n\n<<continue "}}}">>\n\n“is [X] a story?”\n→\n“create a story, [X]”\n\njust different modes of the same <b>logic program</b>,\n\n?- story(X)\n\n<<continue "}}}">>\n\nstateless (e.g. markov models)\n--->\nmore complex generation structures \n\nBosser et. al.: Linear Logic for Nonlinear Storytelling\n“proofs as stories”\n\n<img src="linear-logic-storytelling-papertop.png">\n\n<<set$part1 = true>>Back to [[Outline]]
<<replace "proofs">>linear logic proofs<<endreplace>> as stories<<continue "}}}>>\n\nsimulated environments can be modeled as linear logic contexts.\n\neat-poison : ∀C.alive(C) * apple -o {dead(C)}.\n\nΔ = { apple, alive(princess), alive(witch) }\n\nΔ |- (alive(princess)*dead(witch)) (+) (alive(witch)*dead(princess))\n\n<<continue "}}}">>\n\nwe think about changes to the environment in terms of resource <b>consumption</b> & <b>production</b>.\n\n<<continue "}}}">>\n<pre>do/eat\n: alive(C) * has(C, apple)\n -o {dead(C)}.\n\ndo/give\n: at(C, L) * at(C', L) *\n has(C, apple)\n -o {at(C, L) * at(C', L) * has(C', apple)}.</pre>\n<<continue "}}}">>\n\nLINEAR LOGIC PROGRAMMING as implemented in Celf:\nnondeterminism yields generativity/simulation\nconstructivity yields proofs as <<replace "stories">>artifacts for <<replace "analysis">>analysis of resource dependency structure<<endreplace>><<endreplace>>\n\n<<continue "}}}>>\n<img width=800 src="celf2graph.png">\n\n<<set $part2 = true>>Back to [[Outline]] <<replace>>proofs as stories<<gains>>\nproof search as interaction<<gains>>\nlogic programs as interactive stories<<gains>>\nlogical frameworks as sketching tools\n\n<<continue "}}}">><<endreplace>>\n\nthe terms in which we advertize our language designs (and therefore invent them):\n\n<<replace>>rigidity<<becomes>>expressivity<<becomes>>immediacy<<endreplace>>, <<replace>>correctness<<becomes>>abstraction<<becomes>>playfulness<<endreplace>>, <<replace>>security<<becomes>>elegance<<becomes>>whimsy<<endreplace>>, <<replace>>safety<<becomes>>structure<<becomes>>tangibility<<endreplace>>, <<replace>>limitation<<becomes>>clarity<<becomes>>surprise<<endreplace>>\n\nBack to [[Outline]]\n<<set$part4 = true>><<endreplace>>
"The Interactive Simulation"\n\nrelated to Generative Media: a long tradition of algorithmically generated music, poetry, 2d art...\n<<continue "}}}">>\n<img src="great-art-bot.png">\n<<continue "}}}">>\nwhen we add interactivity, we get games:\n\n<img src="great-artist.png">\n<<continue "}}}">>\n<img height=256 src="sim-ant.png"> <img height=256 src="simcity.png"> <img height=256 src="the-sims.jpg">\n<<continue "}}}">>\n<img height=256 src="versu.png">\n<img height=256 src="minecraft.jpg"> <img height=256 src="868-hack.jpg">\n<<continue "}}}">>\nin general:\n- there is a system of rules governing the environment\n- human can <<cyclinglink "control part of" "poke at" "explore">> the environment & create interesting, surprising behavior\n\nWarren Spector, as summarized on Gamasutra:\n<blockquote>\nCreate global rules versus specific, instanced behavior of objects and characters; build interlocking systems that are predictable and consistent (some objects are flammable, some guards are light-sensitive, the player has torches) but not pre-determined. Have a variety of object properties with plausible or simulated effects ("let water be water") that players can learn and engage with.\n</blockquote>\n\nGenerative Narrative<<continue "}}}">>\n<<display "generative narrative">>
<<silently>>\n<<set $part1 = false>>\n<<set$part2 = false>>\n<<set $part3 = false>>\n<<set$part4 = false>>\n<<endsilently>><h3><<replace "Languages for Actions in Simulated Worlds">>Or: [[what I know about doing game design with logic programs|Outline]]<<endreplace>></h3>\nChris Martens - CMU CS department\nOBT 2014\nhttp://www.cs.cmu.edu/~cmartens/obt2014/obt.html
version.extensions["cyclinglinkMacro"]={major:3,minor:1,revision:1};macros.cyclinglink={handler:function(a,b,c){var l=Wikifier.createInternalLink(a,null);\nl.className="internalLink cyclingLink";l.setAttribute("data-cycle",0);var v="";var end=false;\nif(c.length&&c[0][0]=="$"){v=c[0].slice(1);c.shift();}if(c[c.length-1]=="end"){end=true;\nc.pop();}var h=state.history[0].variables;for(var i=0;i<c.length;i++){var on=(i==Math.max(c.indexOf(h[v]),0));\nvar d=insertElement(null,"span",null,"cyclingLink"+((on)?"En":"Dis")+"abled");if(on){h[v]=c;\nl.setAttribute("data-cycle",i);}insertText(d,c[i]);l.appendChild(d);}l.onclick=function(){var t=this.childNodes;\nvar d="cyclingLink";var u=this.getAttribute("data-cycle")-0;var m=t.length;if(end&&u==m-2){var n=this.removeChild(t[u+1]);\nn.className=d+"End";this.parentNode.replaceChild(n,this);return;}t[u].classList.toggle(d+"Enabled");\nt[u].classList.toggle(d+"Disabled");u=(u+1)%m;if(v){h[v]=c[u];}t[u].classList.toggle(d+"Enabled");\nt[u].classList.toggle(d+"Disabled");this.setAttribute("data-cycle",u);};},init:function(){addStyle(".cyclingLinkDisabled { display:none; } ");\n}};macros.cyclinglink.init(); Languages for Actions in Simulated Worlds <a href="http://www.cs.cmu.edu/~cmartens">Chris Martens</a>\n(<a href="http://www.twitter.com/chrisamaphone">@chrisamaphone</a>) <<replace "interactive SIMULATIONS">>INTERACTIVE simulations<<endreplace>>\n\nmy hypothesis is: we need domain-specific "Action Languages"<<continue "}}}">>\n\n<<revision genspec>>generating random stories<<becomes>>specifying an *interactive* story<<endrevision>> <<revise genspec "vs.">>\n\n<<continue "}}}">>\n“interactive” =~ a human can interrupt and influence execution\n\nwe start with this program\n<pre>\ndo/eat : alive(C) * has(C, A) * poisonous(A) \n -o {dead(C)}.\n\ndo/give : at(C, L) * at(C', L) * has(C, A)\n -o {at(C, L) * at(C', L) * has(C', A)}.\n</pre>\nto introduce interactivity we need to know:\nwhat is the <<replace>>locus of action?<<becomes>>locus of action?\n\n"which one am i?" "what is the control interface?"<<endreplace>>\n\n<<continue "}}}">>\n\nidea: parameterize the program by locus of control. index every rule with a "do" predicate specifying the acting agent:\n\n<pre>\ndo/eat : do(C, eat (O)) * \n alive(C) * has(C, O) * poisonous(O)\n -o {dead(C)}.\n\ndo/give : do(C, give(C',O)) * \n at(C, L) * at(C', L) * has(C, O)\n -o {at(C, L) * at(C', L) * has(C', O)}.</pre>\n<<continue "}}}">>\n<pre>do(C, Action)</pre> is introduced in a <<replace>>phase<<becomes>>phase (idea from my thesis proposal for transfering control between subprograms)<<endreplace>> corresponding to C's "turn", which can be designated as an opportunity for user input\n<<continue "}}}">>\n<pre>Action</pre>ranges over the set of available actions, i.e. the control interface!\n\nQ: can we automatically derive/extract the constructors for A in terms of the rules available in the bird's-eye-view simulation?\n<<continue "}}}">>\nACTION LANGUAGE example from IF:\n\n<<cyclinglink "VERB" "eat" "take" "examine" "push" "stand on">> <<cyclinglink "NOUN" "apple" "flask" "flower" "crate" "no tea" "weasel">>\n\nthe way we interpret actions in a simulation environment is A LOT LIKE interpreting PL terms in a program environment.\n\nQ: how do we specify these languages in a way that we can reason about them (the way we're used to reasoning about formal languages)?\n\n<<set$part3 = true>>Back to [[Outline]]
a {font-size:100%!important;}\n\n#passages{font-size:24px; font-family:'Open Sans';\nborder-left: 0px !important; margin:200px 0px 0px 200px !important;}\n\n#footer{display:none!important;}\n#toolbar{display:none!important;}\n#sidebar{display:none!important;}\n\n\n.revision-span-in {\n opacity: 0;\n}\n.revision-span {\n transition: 1s;\n -webkit-transition: 1s;\n}\n.revision-span-out {\n position:absolute;\n opacity: 0;\n}\n\n.transition-out {\n display:none;\n}\n