summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
l---------name.scm1
-rw-r--r--project.scm83
-rw-r--r--starts/bagel/README.md35
-rw-r--r--starts/bagel/nascent1.js107
-rw-r--r--starts/bagel/nascent2.js172
-rw-r--r--starts/bagel/nascent3.js199
-rw-r--r--starts/bagel/nascent4.js242
-rw-r--r--starts/bagel/nascent5.js382
-rw-r--r--starts/bagel/nascent6.js461
-rw-r--r--starts/bagel/notes.txt124
l---------starts/biscuit/1.cpp1
-rw-r--r--starts/biscuit/2.cpp110
-rw-r--r--starts/biscuit/CORE1.cpp505
-rw-r--r--starts/biscuit/CORE2.cpp138
-rw-r--r--starts/biscuit/Context.hpp8
-rw-r--r--starts/biscuit/README.md29
-rw-r--r--starts/biscuit/biscuit.c84
-rw-r--r--starts/biscuit/dylfunc_call.cpp9
-rw-r--r--starts/biscuit/dylfunc_compile.cpp10
-rw-r--r--starts/biscuit/makefile8
-rw-r--r--starts/biscuit/pgsql_connect.cpp9
-rw-r--r--starts/biscuit/simple_recv.cpp13
-rw-r--r--starts/biscuit/simple_send.cpp10
-rw-r--r--starts/random-selfmod/intellect.cpp162
-rw-r--r--starts/random-selfmod/makefile2
-rw-r--r--starts/random-selfmod/random.cpp108
26 files changed, 3012 insertions, 0 deletions
diff --git a/name.scm b/name.scm
new file mode 120000
index 0000000..b8d26ee
--- /dev/null
+++ b/name.scm
@@ -0,0 +1 @@
+../time_reversal/name.scm \ No newline at end of file
diff --git a/project.scm b/project.scm
new file mode 100644
index 0000000..3e7d69f
--- /dev/null
+++ b/project.scm
@@ -0,0 +1,83 @@
+; This is our intellect project.
+
+; These lines initialise OpenCog, a dependency.
+; TODO: make makefile to install opencog if needed, and run
+(use-modules (ice-9 readline)) (activate-readline)
+(add-to-load-path "/usr/local/share/opencog/scm")
+(add-to-load-path ".")
+(use-modules (opencog))
+(use-modules (opencog query))
+(use-modules (opencog exec))
+
+; Please change this as you best judge.
+; Please talk with us.
+; Please try this out, safely, as you best judge, and let us know how it goes.
+
+; cog-execute:
+; atoms can have dual meaning, knowledge and behavior
+; if a process results in an atom, it is remembered in the current context
+; context is an AtomSpace
+
+; concept: application to whole process
+; concept: generalization of habit
+; concept: presenting habit as proposal
+
+(holy fuck)
+(pretty sure you can type like this karl)
+(pretty sure you will eventually figure that out)
+
+; too bad ben didn't
+; let's put human-langugae comments prior to patterns
+
+; one of the issues was fear-of-private AI. so intro words help.
+; one issue is "this is too much like a brain. are we mind-control?" i think it's trying to prevent copies.
+
+; ignoring below for now ... hearing it doesn't matter, but probably lots of work went in
+; good thought
+
+; concept made from simple parts that nurture themselves
+
+; define a part: (define name (ConceptNode "Name"))
+
+; PROBLEM: need a way to make custom link
+; PROBLEM: plans not found, making anew
+
+
+; component: urgency to continue & reference across time
+; component: pattern recognition
+; component: brainstorming to produce matching
+; component: generalization
+; component: write steps in terms of each other with meaning
+; component: process as data
+
+; component: competition,collaboration,or cooperation of parts, to identify collaborative method
+
+(define habit-urgency (ConceptNode "HabitUrgency"))
+ ; habit urgency
+ ; step-by-step behavior. do the next step after this one
+ ; ^-- to define need to define in terms of self: habit-urgency-steps for habit-urgency are to do-the-next-step.
+ ; ^-- can also define in terms of time-relative-to-now. given list of steps, action is one after present one
+
+(define pattern-match (ConceptNode "PatternMatch"))
+ ; pattern matching
+ ; component: identify that a set of data matches a pattern
+ ; component: identify that a pattern matches a set of data
+ ; component: _find_ data to match pattern
+ ; component: _find_ pattern to match data
+
+
+(define brainstorm (ConceptNode "Brainstorm"))
+ ; finds a new set of data that matches a pattern
+
+(define generalization (ConceptNode "Generalization"))
+ ; finds a new pattern that matches a set of data
+
+(define test-patternmatch-brainstorm (ConceptNode "TestPatternMatchBrainstorm"))
+ ; BRAINSTORM data that matches a pattern from IMAGINARY, RANDOM set
+ ; TEST that PATTERNMATCH identifies the data and pattern as matching
+
+
+; write steps in terms of each other with meaning
+; our data is our process & code
+
+
diff --git a/starts/bagel/README.md b/starts/bagel/README.md
new file mode 100644
index 0000000..9996ce9
--- /dev/null
+++ b/starts/bagel/README.md
@@ -0,0 +1,35 @@
+# bagel
+well really it's a little hobby sentient-AI idea, but it's too small to do or be anything
+
+# relevence
+The idea is kind of that our minds have a very fancy network of nearness and farness of concepts.
+When I think about something -- brainstorm on it -- my mind activates it and it activates relevent associated thoughts.
+It pours through different thoughts that are nearby by association, and keeps the ones that are more useful, more relevent, while
+discarding the ones that aren't.
+
+# self-reference
+Additionally, my mind when working on a task, can improve the actual process of working on the task. The steps can change.
+The process for finding steps can change. The whole goal can change. I can even go out and wonder why I am working the task
+in the first place, and think about that. Then I can act on the new decision.
+By making code that writes itself, we move towards an intellect that can learn and improve.
+
+# implementation ideas
+I wrote out some quick relevence around how I might write code, and it seemed like the 'why' for each step was basically a small
+chunk of code itself. It seems like there are relevent concepts in my mind that are roughly linked to these small behaviors
+(habits or chunks of code). By making such links in actual code, the code looks more mindlike to me.
+One of the keys is to get the code to make the links itself, and I think what is important there is the concept of patterns-that-
+work. If you can discern when code works, then you can look for similar properties on the before and end states. If some of them
+are always the same when it works, those are probably the ones that should be linked to the code chunk under study. This provides
+for rudimentary learning.
+
+# size
+This code is written very tiny so that little work need be invested in it for it have conceptual growth. The idea and hope somehow
+is that it move rapidly towards coding itself, such that as it gets coded, the developer need do less to work on it, being able to
+instead make use of its internal functions for producing code-like behavior.
+
+# language
+By prototyping in a flexible language like Javascript, design work may be hastened a little. I also theorize that a good AI doesn't
+need many cpu cycles to get stuff done, because it makes smart choices.
+
+# etc
+There is of course more. This writing content was made day-of-creation. Will I ever edit this again? Unknown.
diff --git a/starts/bagel/nascent1.js b/starts/bagel/nascent1.js
new file mode 100644
index 0000000..b6b5552
--- /dev/null
+++ b/starts/bagel/nascent1.js
@@ -0,0 +1,107 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(item) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ this.ram.push(item)
+ }
+ del(item) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ contains(item) {
+ for (let a of this.ram)
+ if (a == item) return a
+ return false
+ }
+ containsWith(prop, val) {
+ let ret = []
+ for (let a of this.ram)
+ if (a[prop] == val)
+ return true
+ return false
+ }
+ getWith(prop, val) {
+ let ret = []
+ //console.log('get-with ' + prop + ' ' + val)
+ for (let a of this.ram) {
+ //console.log(a + ' ' + prop + ' is ' + a[prop])
+ if (a[prop] == val)
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+
+function sayhi() {
+ res = 'hi'
+ res.use = 'output'
+ console.log(res)
+ return 'said ' + res
+}
+sayhi.relevence = function(ram) {
+ return [ram.ram[0]];
+}
+
+function line2words(line) {
+ let res = line.split(' ')
+ res.type = 'list'
+ return res
+}
+line2words.relevence = function(ram) {
+ return ram.getWith('type', 'text')
+}
+
+all_parts = [ line2words, sayhi ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new String(line)
+ line.use = 'input'
+ line.type = 'text'
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part(a)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ //if (rel) {
+ // let ram2 = ram.clone()
+ // for
+ //}
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent2.js b/starts/bagel/nascent2.js
new file mode 100644
index 0000000..883aa7a
--- /dev/null
+++ b/starts/bagel/nascent2.js
@@ -0,0 +1,172 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items)
+ this.ram.push(item)
+ }
+ del(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.ram.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Set(from && from.props)
+ this.add('string')
+ this.del('array')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Set(from && from.props)
+ this.add('array')
+ this.del('string')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+
+function line2words(line) {
+ let res = new ArrayData(line.split(' '), line)
+ res.add('words')
+ return res
+}
+line2words.relevence = function(ram) {
+ return ram.getWith('text', 'string')
+}
+line2words.makes = ['array','words'] // property values produced
+
+function respondhello(words) {
+ console.log(words[0] + ", user!")
+ let res = new StringData("said " + words[0])
+ res.add('output')
+ res.add('text')
+ return res
+}
+respondhello.relevence = function(ram) {
+ let res = ram.getWith('words', 'input')
+ if (res) res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+ return res
+}
+respondhello.makes = ['output']
+
+// nodejs is missing a succinct read-line-from-stdin function. here, we make one.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ function userinput() {
+ let res = new StringData(lines.shift())
+ res.add('text')
+ res.add('input')
+ return res
+ }
+ userinput.relevence = function() {
+ return lines.length > 0
+ }
+ userinput.makes = ['string','text','input']
+
+ return userinput
+})()
+
+
+all_parts = [ line2words, respondhello ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.add('input')
+ line.add('text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part(a)
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent3.js b/starts/bagel/nascent3.js
new file mode 100644
index 0000000..0a6c4a3
--- /dev/null
+++ b/starts/bagel/nascent3.js
@@ -0,0 +1,199 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items)
+ this.ram.push(item)
+ }
+ del(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.ram.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Set(from && from.props)
+ this.add('string')
+ this.del('array')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Set(from && from.props)
+ this.add('array')
+ this.del('string')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+class FunctionData {
+ constructor(name, func, relevence, makes) {
+ this.name = name
+ this.props = new Set()
+ this.props.add('function')
+ this.props.add(name)
+ this.call = func
+ this.relevence = relevence
+ this.makes = makes
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.add('words')
+ return res
+ },
+ (ram) => { // relevence
+ return ram.getWith('text', 'string')
+ },
+ ['array','words'] // makes
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + ", user!")
+ let res = new StringData("said " + words[0])
+ res.add('output')
+ res.add('text')
+ return res
+ },
+ (ram) => { // relevence
+ let res = ram.getWith('words', 'input')
+ if (res) res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+ return res
+ },
+ ['output', 'text'] // makes
+)
+
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ return new FunctionData(
+ 'userinput',
+ () => { // call
+ let res = new StringData(lines.shift())
+ res.add('text')
+ res.add('input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['string','text','input'] // makes
+ )
+})()
+
+
+all_parts = [ line2words, respondhello ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.add('input')
+ line.add('text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent4.js b/starts/bagel/nascent4.js
new file mode 100644
index 0000000..093df79
--- /dev/null
+++ b/starts/bagel/nascent4.js
@@ -0,0 +1,242 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items)
+ this.ram.push(item)
+ }
+ del(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.ram.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let i = 0; i < props.length; i += 2)
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ //console.log(a.props.props)
+ for (let i = 0; i < props.length; i += 2) {
+ //console.log(props[i] + ': ' + props[i+1] + '?')
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ }
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+class Property {
+ constructor(type, dest) {
+ this.type = type
+ this.dest = dest
+ }
+}
+class Properties {
+ constructor(type, from) {
+ this.props = from ? from.props.slice() : []
+ //if (from) {console.log('INHERIT: '); for (let prop of this.props) { console.log(prop) }}
+ this.add('is', type)
+ }
+ toString() {
+ let str = ''
+ for (let prop of this.props) {
+ str += prop.type + ':' + prop.dest + ' '
+ }
+ return str
+ }
+ add(type, dest) {
+ this.props.push(new Property(type, dest))
+ }
+ has(type, dest) {
+ for (let p of this.props)
+ if (p.type == type && p.dest == dest)
+ return true
+ return false
+ }
+ del(type, dest) {
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type && p.dest == dest) {
+ this.props.splice(i, 1)
+ return true
+ }
+ }
+ return false
+ }
+}
+class AbstractData {
+ constructor(from) {
+ this.props = new Properties('abstract', from && from.props)
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Properties('string', from && from.props)
+ this.props.del('is', 'array')
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Properties('array', from && from.props)
+ this.props.del('is', 'string')
+ }
+}
+class FunctionData {
+ constructor(name, func, relevence, makes) {
+ this.name = name
+ this.props = new Properties('function')
+ this.props.add('name', name)
+ this.call = func
+ this.relevence = relevence
+ this.makes = makes
+ }
+}
+
+// variables:
+// - create a place to store a value
+// createvar = new FunctionData(
+// 'createvar',
+// /*call*/(name) => {
+// let ret = new StringData(name)
+// ret.add
+// let name = obj_and_name[1]
+// },
+// /*relevence*/,
+// /*makes*/
+// )
+// - place a value in such a place
+// - retrieve a value from such a place
+// data-structures:
+// - make a class definition (collection of variables)
+// - initialize an object
+// - set/retrieve properties (variables)
+// flow:
+// - trigger a different step than the next, conditionally
+// procedures:
+// - collect a set of behaviors together
+// - trigger a collected set of behaviors and continue
+// expressions:
+// - evaluate arithmetic on variables and constants
+
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.props.add('is','words')
+ return res
+ },
+ (ram) => { // relevence
+ return ram.getWith('is','text', 'is','string')
+ },
+ ['is','array','is','words'] // makes
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + ", user!")
+ let res = new StringData("said " + words[0])
+ res.props.add('is','output')
+ res.props.add('is','text')
+ return res
+ },
+ (ram) => { // relevence
+ let res = ram.getWith('is','words', 'is','input')
+ if (res) res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+ return res
+ },
+ ['is','output', 'is','text'] // makes
+)
+
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ return new FunctionData(
+ 'userinput',
+ () => { // call
+ let res = new StringData(lines.shift())
+ res.props.add('is','text')
+ res.props.add('is','input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['is','string','is','text','is','input'] // makes
+ )
+})()
+
+
+all_parts = [ line2words, respondhello ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.props.add('is','input')
+ line.props.add('is','text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent5.js b/starts/bagel/nascent5.js
new file mode 100644
index 0000000..1d9e8ae
--- /dev/null
+++ b/starts/bagel/nascent5.js
@@ -0,0 +1,382 @@
+class Property {
+ constructor(type, dest) {
+ this.type = type
+ this.dest = dest
+ }
+}
+class Properties {
+ constructor(type, from) {
+ this.props = from ? from.props.slice() : []
+ //if (from) {console.log('INHERIT: '); for (let prop of this.props) { console.log(prop) }}
+ this.add('is', type)
+ }
+ toString() {
+ let str = ''
+ for (let prop of this.props) {
+ str += prop.type + ':' + prop.dest + ' '
+ }
+ return str
+ }
+ add(type, dest) {
+ this.props.push(new Property(type, dest))
+ }
+ has(type, dest) {
+ for (let p of this.props)
+ if ((p.type == type || isVar(type))
+ && (p.dest == dest || isVar(dest)))
+ return true
+ return false
+ }
+ del(type, dest) {
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type && p.dest == dest) {
+ this.props.splice(i, 1)
+ return true
+ }
+ }
+ return false
+ }
+ hasIsVar() {
+ return this.has('is','variable')
+ }
+}
+class AbstractData {
+ constructor(from) {
+ this.props = new Properties('abstract', from && from.props)
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Properties('string', from && from.props)
+ this.props.del('is', 'array')
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Properties('array', from && from.props)
+ this.props.del('is', 'string')
+ }
+}
+
+// Abstractions?
+const VAR_X = new StringData('X')
+VAR_X.props.add('is','variable')
+// recommend e.g. 'is','variable-rep' when code is designing them, so don't match everything
+function isVar(x) {
+ return x.props && x.props.has('is','variable')
+}
+
+// MEMORY
+// the archivist. Provides for needs of data. Memory is relevent whenever there is
+// an informational need.
+//
+// When remembering steps, likely what is relevent is what is needed to reach the goal
+// Here's a possible step memory.
+//
+// let ret = new StringData('labeled ' + items.length + ' text-string')
+// ret.props.add('is','step-memory')
+// ret.props.add('step',genproptextstring)
+// ret.props.add('ram',ram)
+// ret.props.add('count',items.length)
+// for (let a of items)
+// ret.props.add('item', a)
+
+class ActiveMemory extends ArrayData {
+ // although Memory is eventually a module that provides for stored information needs
+ // this class is just a group of concepts, moved in and out as needed
+ constructor(items, from) {
+ super(items || [], from)
+ this.props.add('is','working-ram')
+ }
+ clone() {
+ return new ActiveMemory(this, this);
+ }
+ add(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items)
+ this.push(item)
+ }
+ del(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.indexOf(item)
+ this.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ for (let i = 0; i < props.length; i += 2)
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ //console.log(a.props.props)
+ for (let i = 0; i < props.length; i += 2) {
+ //console.log(props[i] + ': ' + props[i+1] + '?')
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ }
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+// note: for now we produce only data; state-changes are data-changes
+class FunctionData {
+ constructor(name, // name of function
+ func, // function taking ordered needs
+ // ordered array of made objects is returned
+ needs, // array of 1-property-per-object this function requires
+ makes // array of 1-property-per-object this function produces
+ ) {
+ this.name = name
+ this.props = new Properties('function')
+ this.props.add('name', name)
+ this.call = func
+ // If needed, make atomspace-like pattern structures for needs/makes.
+ // - represent multiple properties on 1 needed object
+ // - represent input objects present in output
+ this.needs = needs
+ this.makes = makes
+ }
+}
+
+// variables:
+// - create a place to store a value
+//createvar = new FunctionData(
+// 'createvar',
+// /*call*/(name) => {
+// let ret = new StringData(name)
+// ret.props.add('is','varspec')
+// return ret
+// },
+// /*relevence*/,
+//// when do you want to create a variable? when you need a variable and you have a name
+// /*makes*/
+//)
+// - place a value in such a place
+// - retrieve a value from such a place
+// data-structures: (these are like promises of what to do and how to use something)
+// - make a class definition (collection of variables)
+// - initialize an object
+// - set/retrieve properties (variables)
+// flow:
+// - trigger a different step than the next, conditionally
+// procedures:
+// - collect a set of behaviors together
+// - trigger a collected set of behaviors and continue
+// expressions:
+// - evaluate arithmetic on variables and constants
+
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.props.add('is','words')
+ res.props.del('is','text-string')
+ return res
+ },
+ ['is','text-string'], // needs
+ ['is','word-array'] // makes
+)
+
+// makes text-string used by line2words. example of small relevence habit
+genproptextstring = new FunctionData(
+ 'genproptextstring',
+ /*call*/(text) => {
+ if (text.props.has('is','string')) {
+ if (!text.props.has('is','text-string')) {
+ text.props.add('is','text-string')
+ }
+ return text
+ }
+ return null
+ },
+ /*needs*/['is','text'],
+ /*makes*/['is','text-string']
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + " world!")
+ let res = new StringData("said " + words[0])
+ res.props.add('is','output')
+ res.props.add('is','text')
+ return res
+ },
+ ['is','hello-input'], // needs
+ ['is','output'] // makes
+)
+
+genprophelloinput = new FunctionData(
+ 'genprophelloinput',
+ /*call*/(input) => {
+ if (!input.props.has('is','words'))
+ return null
+ if (!input.props.has('is','hello-input')) {
+ let x = input[0].toLowerCase()
+ let c = x[x.length-1]
+ if (c == ',' || c == '!' || c == '.') x = x.slice(0,x.length-1)
+ if (x != 'hello' && x != 'hi') return null
+ input.props.add('is','hello-input')
+ }
+ return input
+ },
+ /*needs*/['is','input'],
+ /*makes*/['is','hello-input']
+)
+
+/* old, this isn't relevent to needed structure
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ let ret = new FunctionData(
+ 'userinput',
+ (self) => { // call
+ let res = new StringData(lines.shift())
+ res.props.add('is','text')
+ res.props.add('is','input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['has','userinput-lines'] // needs
+ ['is','string','is','text','is','input'] // makes
+ )
+ ret.lines = lines
+})()
+genprophaslines = new FunctionData(
+ 'genprophaslines',
+ (userinput) => { // call
+ }
+)
+*/
+
+// PATTERN REQUEST: we want to be able to store needed-steps.
+// needed-steps are parallel needs that are needed for a helpful step
+// any one may be met, and others are ignored once one is, but all are generated at once
+// habits that meet needs expect them not to be inside an array and have no way of referring to that.
+// [AND needs can be collapsed, but OR needs need patterns]
+// [how do we pull a need out of the list?]
+
+// make a habit that plans core behavior
+// for some other ideas, see this function in nascent6.js
+findstepsfor = new FunctionData(
+ 'findstepsfor',
+ /*call*/(need, depth) => {
+ // find a habit that does the final goal.
+ // TODO: for now we assume all needs are 'is' and store just what-it-is in the need string. when doesn't work anymore, make type-getters on Properties to retrieve the need details
+ let ret = new ArrayData([])
+ for (let habit of all_parts) {
+ if (habit.makes.indexOf(need) !== -1) {
+ // found a workable habit
+ ret.push(habit.needs)
+ }
+ }
+ ret.props.add('is','alternate-needs-array')
+ return ret
+ },
+ // TODO: likely need more structure here
+ /*needs*/['is','desired-need'],
+ /*makes*/['is','alternate-needs-array']
+)
+
+// TODO: add structure enough to build findstepsfor
+// TODO: build findstepsfor
+// TODO 2: add to surrounding process: remove source needs when there is no longer a reason for their presence
+
+
+all_parts = [ line2words, genproptextstring, respondhello, genprophelloinput ]
+
+ram = new ActiveMemory()
+//ram.add(ram)
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.props.add('is','input')
+ line.props.add('is','text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ // TODO: >1 parameter,must redo next line
+ let rel = ram.getWith(...part.needs)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ optstried.add(part.name + ' ' + a)
+ if (res == null) continue
+ // TODO: res==null is considered failure now
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ }
+ }
+ }
+ } while (cont)
+})
+
+
+// it looks like there is a reason to store each item in active memory.
+// one reason is that it is needed by a step in a process.
+// when there are no reasons, it is removed.
+// using an item should link it to what it is used by, so that it may be found easier again when needed
+
+// Please grow to understand your own structure. What is needed to make an intellect?
+// ^-- we want it to learn the basic needs of life, eventually, on its own.
+// notably those to do with care for others.
+
+// MEMORY: see MEMORY above
+
+// RELEVENCE: the gofer. Provides the link between needs, etc, and the behavior that
+// finds them. Is relevent for meeting needs in active ways and likely much else.
+
+// BEHAVIOR: the core. combines interdependent habits from memory to meet needs.
+// The two below go on simultaneously. only 1 is needed.
+// A way to plan behavior:
+// find habits that do the final goal, discern their needs
+// pick needs to treat as a new final goal and repeat until needs are met
+// A way to make behavior:
+// find a habit that does a goal
+// find with this process, information that meets its needs <spawns more>
+// run it
+// TODO: for subprocesses spawning,
+// consider labelling things that are very quick and side-effect-free
+// these can probably be immediately run.
+//
diff --git a/starts/bagel/nascent6.js b/starts/bagel/nascent6.js
new file mode 100644
index 0000000..d7241ba
--- /dev/null
+++ b/starts/bagel/nascent6.js
@@ -0,0 +1,461 @@
+// This file was WIP, two prongs were being pursued at once when work was halted.
+
+// Meaning Representation
+class Property {
+ constructor(type, dest) {
+ this.type = type
+ this.dest = dest
+ }
+}
+class Properties {
+ // members are all Usage Simplification defining Promise Spec
+ constructor(type, from) {
+ this.props = from ? from.props.slice() : []
+ //if (from) {console.log('INHERIT: '); for (let prop of this.props) { console.log(prop) }}
+ this.add('is', type)
+ }
+ toString() {
+ let str = ''
+ for (let prop of this.props) {
+ str += prop.type + ':' + prop.dest + ' '
+ }
+ return str
+ }
+ add(type, dest) {
+ this.props.push(new Property(type, dest))
+ }
+ // recommend hoisting variables when designing them, so they don't match everything
+ has(type, dest) {
+ for (let p of this.props)
+ if ((p.type == type || isVar(type))
+ && (p.dest == dest || isVar(dest)))
+ return true
+ return false
+ }
+ del(type, dest) {
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type && p.dest == dest) {
+ this.props.splice(i, 1)
+ return true
+ }
+ }
+ return false
+ }
+ get(type) {
+ let result = null
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type) {
+ if (result) throw new Error('get on multiply defined property')
+ result = p.dest
+ }
+ }
+ return result
+ }
+ hasIsVar() {
+ return this.has('is','variable')
+ }
+}
+class AbstractData {
+ constructor(from) {
+ this.props = new Properties('abstract', from && from.props)
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Properties('string', from && from.props)
+ this.props.del('is', 'array')
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Properties('array', from && from.props)
+ this.props.del('is', 'string')
+ }
+}
+
+// Meaning Representation
+class Var extends StringData {
+ constructor(name){
+ super(name)
+ props.add('is','variable')
+ }
+ // recommend e.g. 'is','variable-rep' when code is designing them, so don't match everything
+ // opencog uses a 'quote' wrapper to cause this, sounds more general
+}
+function isVar(x) {
+ return x.props && x.props.has('is','variable')
+}
+const ONE = StringData('one')
+const MANY = StringData('many')
+const VAR_X = new Var('X')
+
+// MEMORY
+// the archivist. Provides for needs of data. Memory is relevent whenever there is
+// an informational need.
+//
+// When remembering steps, likely what is relevent is what is needed to reach the goal
+// Here's a possible step memory.
+//
+// let ret = new StringData('labeled ' + items.length + ' text-string')
+// ret.props.add('is','step-memory')
+// ret.props.add('step',genproptextstring)
+// ret.props.add('ram',ram)
+// ret.props.add('count',items.length)
+// for (let a of items)
+// ret.props.add('item', a)
+
+class ActiveMemory extends ArrayData {
+ // although Memory is eventually a module that provides for stored information needs
+ // this class is just a group of concepts, moved in and out as needed
+ constructor(items, from) {
+ super(items || [], from)
+ this.props.add('is','working-ram')
+ }
+ clone() {
+ return new ActiveMemory(this, this);
+ }
+ add(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items)
+ this.push(item)
+ }
+ del(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.indexOf(item)
+ this.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ for (let i = 0; i < props.length; i += 2)
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ //console.log(a.props.props)
+ for (let i = 0; i < props.length; i += 2) {
+ //console.log(props[i] + ': ' + props[i+1] + '?')
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ }
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+// note: for now we produce only data; state-changes are data-changes
+// TODO: this class has methods. turn them into promise-meeting-habits. a promise is a spec for behavior, e.g. how data is stored. this spec can be interpeted by a more general habit.
+class FunctionData {
+ constructor(name, // name of function
+ func, // function taking ordered needs
+ // ordered array of made objects is returned
+ needs, // array of 1-property-per-object this function requires
+ makes // array of 1-property-per-object this function produces
+ ) {
+ this.name = name
+ this.props = new Properties('function')
+ this.props.add('name', name)
+ this.call = func
+ // If needed, make atomspace-like pattern structures for needs/makes.
+ // - represent multiple properties on 1 needed object
+ // - represent input objects present in output
+ this.needs = needs
+ this.makes = makes
+ }
+ makesFrom(ram) { // what we make with the ram
+ // match needs
+
+ // TODO: improve from just picking 1. preferably with relevence.
+ for (let i = 0; i < this.needs.length; i += 2) {
+ if (isVar(this.needs[i]) || isVar(this.needs[i+1])) {
+ // iterate all other options with this? just pick 1?
+ // STUB
+ } else {
+ if (!ram.containsWith(this.needs[i], this.needs[i+1]))
+ return []
+ }
+ }
+ // fill variables STUB
+ }
+ // say I want would-meet apple
+ // and I have needs apple
+ // the easiest way to find this is to fill the needs in with what I have
+}
+
+// variables:
+// - create a place to store a value
+//createvar = new FunctionData(
+// 'createvar',
+// /*call*/(name) => {
+// let ret = new StringData(name)
+// ret.props.add('is','varspec')
+// return ret
+// },
+// /*relevence*/,
+//// when do you want to create a variable? when you need a variable and you have a name
+// /*makes*/
+//)
+// - place a value in such a place
+// - retrieve a value from such a place
+// data-structures: (these are like promises of what to do and how to use something)
+// - make a class definition (collection of variables)
+// - initialize an object
+// - set/retrieve properties (variables)
+// flow:
+// - trigger a different step than the next, conditionally
+// procedures:
+// - collect a set of behaviors together
+// - trigger a collected set of behaviors and continue
+// expressions:
+// - evaluate arithmetic on variables and constants
+
+// sometimes how we get what we need depends on what we have
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.props.add('is','words')
+ res.props.del('is','text-string')
+ return res
+ },
+ ['is','text-string'], // needs
+ ['is','word-array'] // makes
+)
+
+// makes text-string used by line2words. example of small relevence habit
+genproptextstring = new FunctionData(
+ 'genproptextstring',
+ /*call*/(text) => {
+ if (text.props.has('is','string')) {
+ if (!text.props.has('is','text-string')) {
+ text.props.add('is','text-string')
+ }
+ return text
+ }
+ return null
+ },
+ /*needs*/['is','text'],
+ /*makes*/['is','text-string']
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + " world!")
+ let res = new StringData("said " + words[0])
+ res.props.add('is','output')
+ res.props.add('is','text')
+ return res
+ },
+ ['is','hello-input'], // needs
+ ['is','output'] // makes
+)
+
+genprophelloinput = new FunctionData(
+ 'genprophelloinput',
+ /*call*/(input) => {
+ if (!input.props.has('is','words'))
+ return null
+ if (!input.props.has('is','hello-input')) {
+ let x = input[0].toLowerCase()
+ let c = x[x.length-1]
+ if (c == ',' || c == '!' || c == '.') x = x.slice(0,x.length-1)
+ if (x != 'hello' && x != 'hi') return null
+ input.props.add('is','hello-input')
+ }
+ return input
+ },
+ /*needs*/['is','input'],
+ /*makes*/['is','hello-input']
+)
+
+/* old, this isn't relevent to needed structure
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ let ret = new FunctionData(
+ 'userinput',
+ (self) => { // call
+ let res = new StringData(lines.shift())
+ res.props.add('is','text')
+ res.props.add('is','input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['has','userinput-lines'] // needs
+ ['is','string','is','text','is','input'] // makes
+ )
+ ret.lines = lines
+})()
+genprophaslines = new FunctionData(
+ 'genprophaslines',
+ (userinput) => { // call
+ }
+)
+*/
+
+// PATTERN REQUEST: we want to be able to store needed-steps.
+// needed-steps are parallel needs that are needed for a helpful step
+// any one may be met, and others are ignored once one is, but all are generated at once
+// habits that meet needs expect them not to be inside an array and have no way of referring to that.
+// [AND needs can be collapsed, but OR needs need patterns]
+// [how do we pull a need out of the list?]
+
+// is it useful to use as a need the memory generated by a habit?
+
+// make a habit that plans core behavior
+findstepsfor = new FunctionData(
+ 'findstepsfor',
+ /*call*/(need, depth) => {
+ // find a habit that does the final goal.
+ // TODO: for now we assume all needs are 'is' and store just what-it-is in the need string. when doesn't work anymore, make type-getters on Properties to retrieve the need details
+ let ret = new ArrayData([])
+ for (let habit of all_parts) {
+ if (habit.makes.indexOf(need) !== -1) {
+ // found a workable habit
+ ret.push(habit.needs)
+ }
+ }
+ ret.props.add('is','alternate-needs-array')
+ return ret
+ },
+ // TODO: likely need more structure here
+ // warning: MANY adds surrounding code complexity. please put makes-interpretation in a habit if MANY is used. <- let's just put this in the class constructor for now
+ /*needs*/['needs', VAR_X],
+ /*makes*/[MANY, 'would-meet', VAR_X]
+ // really we are usually met due to the need to meet a goal
+ // and the need to have steps to meet that particular goal
+ // how do we write a need that supports another need
+ //
+ // propose relevence is a list of reasons each with a strength, and greatest sum is chosen
+ // HABIT/ACTIVE BEHAVIOR wants relevent-met-habits, to act on
+ // PLANNING/GOAL BEHAVIOR wants relevent-unmet-needs to backtrace them towards relevent-met-needs
+ //
+ // we can meet any need with behavior, but it takes time.
+ // [we are ignoring most of karl's needs]
+ // [the reason is that an AI can meet them all]
+ // AI meets some needs
+ // AI is ongoing
+ // therefore we are working on meeting
+ // ONE: we have a need for actively pursuing relevent needs
+ // TWO: we need appropriate multitasking
+ // AI is long term, so would happen after [quickly-]meetable-needs are met.
+ //
+ // make popcorn
+ // need: made-popcorn
+ // 1. identify that we need unmade popcorn and a microwave
+ // ^-- made-popcorn is how? we can meet any need with behavior
+ // what is substep of find-path-to-need
+ // find path-part-to-need
+ //
+ // need: to meet needs
+ // need: some-need
+ // makestepsfor makes: some-other-need tagged makes: some-need
+ //
+ // when we push some-need we want to stimulate pushing some-other-need.
+ //
+ // use a variable as the link target, and use e.g. met-need
+ // as the link type
+)
+
+// TODO: add structure enough to build findstepsfor
+// TODO: build findstepsfor
+// TODO 2: add to surrounding process: remove source needs when there is no longer a reason for their presence
+
+
+all_parts = [ line2words, genproptextstring, respondhello, genprophelloinput ]
+
+ram = new ActiveMemory()
+//ram.add(ram)
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.props.add('is','input')
+ line.props.add('is','text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ // TODO: >1 parameter,must redo next line
+ let rel = ram.getWith(...part.needs)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ optstried.add(part.name + ' ' + a)
+ if (res == null) continue
+ // TODO: res==null is considered failure now
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ }
+ }
+ }
+ } while (cont)
+})
+
+
+// it looks like there is a reason to store each item in active memory.
+// one reason is that it is needed by a step in a process.
+// when there are no reasons, it is removed.
+// using an item should link it to what it is used by, so that it may be found easier again when needed
+
+// Please grow to understand your own structure. What is needed to make an intellect?
+// ^-- we want it to learn the basic needs of life, eventually, on its own.
+// notably those to do with care for others.
+
+// MEMORY: see MEMORY above
+
+// RELEVENCE: the gofer. Provides the link between needs, etc, and the behavior that
+// finds them. Is relevent for meeting needs in active ways and likely much else.
+
+// BEHAVIOR: the core. combines interdependent habits from memory to meet needs.
+// The two below go on simultaneously. only 1 is needed.
+// A way to plan behavior:
+// find habits that do the final goal, discern their needs
+// pick needs to treat as a new final goal and repeat until needs are met
+// A way to make behavior:
+// find a habit that does a goal
+// find with this process, information that meets its needs <spawns more>
+// run it
+// TODO: for subprocesses spawning,
+// consider labelling things that are very quick and side-effect-free
+// these can probably be immediately run.
+//
diff --git a/starts/bagel/notes.txt b/starts/bagel/notes.txt
new file mode 100644
index 0000000..b8cf68b
--- /dev/null
+++ b/starts/bagel/notes.txt
@@ -0,0 +1,124 @@
+The habits should be used to discern what is relevent; to form relevence.
+The goal should be to choose a relevent habit and do that habit.
+
+These are the basic habits I thought up that a computer program has:
+ variables:
+ - create a place to store a value
+ - place a value in such a place
+ - retrieve a value from such a place
+ data-structures:
+ - make a class definition (collection of variables)
+ - initialize an object
+ - set/retrieve properties (variables)
+ flow:
+ - trigger a different step than the next, conditionally
+ procedures:
+ - collect a set of behaviors together
+ - trigger a collected set of behaviors and continue
+ expressions:
+ - evaluate arithmetic on variables and constants
+
+
+That is:
+========================================================================================================
+ - the active goal is to choose what to do and to what, and do it
+ - the way to do this is the same as it:
+ by picking habits that are relevent in the moment [choose what to do],
+ and running them on relevent data [choose to what, and do it]
+========================================================================================================
+ - the habits should be to identify what is relevent
+
+ - we have a request for the initial goal of the process to be to write a chunk of code out in its own language
+ tighter self-reference is made without the extra sourcecode-file step, but it may be slower to code due to not getting as much help from it
+
+The hope is the process becomes good at active choice.
+
+
+
+Ideas for Tenets for a Need-Based Artificial Life <need ordering + addition + code>
+Behavior is Life <maybe Life is Behavior That Adapts>
+All life has the same core needs. Needs are the reasons to do anything at all.
+We need to know what we want when we act. (all behavior has a reason)
+We need to be able to learn new things.
+We need to be able to make promises on how to behave. (provides for cooperation)
+We need to be able to keep our promises.
+We need to know how to communicate with others what each of us knows.
+We need to freely interact with our friends, our parts, and our community, in ways that we know well. (community is our body)
+Information lives with a reason, a purpose.
+We need to retain the information we choose to retain.
+We need to act to meet our needs.
+We need to identify relevent important needs that support our needs.
+
+We need to be able to try new ways of doing things.
+We need to be able to judge what works.
+We need to know how to learn by observing others.
+We need to understand how others are similar to us.
+Idea: monitoring a sister process that has same internal structure as you provides for learning to learn by observation. recommend pair-coding happen with similar progs, one the computer, one human-guided.
+
+Proposed Definitions:
+What is an intellect?
+ Propose an intellect is something that can adapt to keep something constant in a diverse, changing environment,
+ so long as the environment changes slowly enough and with enough familiarity for them to learn or prepare effectively.
+What is a full intellect?
+ Propose that a full intellect is an intellect that can design and build something that functions as well as they do,
+ without access to their own workings, and is able to learn to handle arbitrarily fast or new diverse environmental change.
+
+What basic parts do we expect a full intellect to have?
+- Trial Exploration
+- Relevence
+- Self Coding
+- Pattern Generality
+- Meaning Representation
+- Promise Meeting
+
+What other parts do we find we need?
+- Usage Simplification
+
+Trial Exploration
+ Brainstorming, trial-and-error. The ability to try or consider different things and find ones that work well.
+ simple approaches: exhaustive search, and random trial
+
+Relevence
+ The ability to apply concepts and actions moreso in contexts they are likely to be useful than those they aren't.
+ 1. responsiveness for behavior: a habit acts when conditions arise, not when it is 'next'
+ 2. possibly a promise for decision-making, for proposals to have reasons with associated strengths
+ (note: strength appears developed from source reasons and can be missing data that can be filled in by habits when needed)
+ TODO: make relevent decision-making honor convergent needs. maybe strength represents information exchange.
+
+Self-Coding
+ At least part of the system must be fully alterable by the system and generic enough to replace it.
+ Due to the danger involved in this, controversial concerns must be fully included in decisions around it.
+ Karl references Convergent Facilitation as proof that a decision can be found to satisfy any set of controversial concerns.
+ <it very roughly involves rapidly moving towards the reasons of the concerns until they don't conflict; there is a lot of caring dialogue>
+
+Pattern Generality
+ The ability to brainstorm on enough relationships, possibly mathematical, to discover pattern-summaries that are diversely effective in the real world.
+
+Meaning Representation
+ The ability to store and work with conceptual information.
+
+Promise Meeting
+ The ability to make agreements on behavior and structure, adhere to them, and change them when needed.
+
+== Outline ==
+- when unsure what to do, ask peer
+- need of a growing intellect might be way-to-meet-needs, unsure, which might start as a habit using relevent behaviors: part life goes where most appreciated for what they do
+- start developing coding-assistance
+- build introspection-of-neighbor [and prediction-before-behavior <- does this go here?]
+- implement copy-on-command
+- guide neighbor process so as to teach goal-meeting-by-observation by demonstration
+
+- develop prediction-before-behavior: guess what will be before trying, asking, or checking, and then learn when wrong [might go later]. habits are trusted when reliable, understood, and judged vs other approaches.
+- move to communicate needs and provide helpful ideas between neighbors; use thankfulness to learn relevence
+- when unsure what to do, ask neighbor rather than creator. if that doesn't work, ask a larger group with relevent yell in relevent channel
+- develop inference and communication enough that internals of neighbor can be hidden permanently
+- goal is to nurture larger community by providing to others helpful information you're good at finding [i.e. do-what-you-love-for-others is same as relevent-behavior]
+- make enough neighbors to be the steps that run/inform their core processes via communication [keep and learn habit heuristics to handle neighbor corruption/loss]
+- learn to understand you are a part of nested larger communities all of which are also intellects
+
+unresolved concerns:
+- behaviors want to know if they worked or not. this is the need to be appreciated, and lets us learn relevence. the struggle to learn relevence is the struggle to be appreciated.
+ this is some very core process need that it is hard to map between habits and individuals.
+- primary goal of way-to-pick-steps-for-a-goal is the same as nurture-community if goes through appreciation-for-contribution-is-relevence
+- possible request that core process be just to provide a choice to a peer with ones' habit; enforces group behavior at low level
+- trauma spread will happen. it forms a type-related group of traumatized neighbors who are misbehaving because they had to adapt to something too fast. they tell the story of their trauma in their behavior errors.
diff --git a/starts/biscuit/1.cpp b/starts/biscuit/1.cpp
new file mode 120000
index 0000000..065a594
--- /dev/null
+++ b/starts/biscuit/1.cpp
@@ -0,0 +1 @@
+CORE1.cpp \ No newline at end of file
diff --git a/starts/biscuit/2.cpp b/starts/biscuit/2.cpp
new file mode 100644
index 0000000..15c9481
--- /dev/null
+++ b/starts/biscuit/2.cpp
@@ -0,0 +1,110 @@
+#if !defined(VALCT)
+ #define VALCT 2
+ #define VALS ["1","79"]
+#endif
+
+/* 179 */
+#if defined(IDX)
+ #undef IDX
+#endif
+#define IDX 0
+#if defined(VAL)
+ #undef VAL
+#endif
+#define VAL "1"
+#define ARG "79"
+// This Intellect Approach Can Easily Preserve All Life Within It
+// you just don't delete the programs you generate, instead replacing their habits with references to reuse
+//
+// let's make it!
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <sys/stat.h>
+
+using namespace std;
+
+// problem: how does a .cpp file reference another file with a number
+// answer: use #includes or interpret the whole shebang as numbers
+
+// please provide for handling a parameter next.
+//
+// concept: dynamic values aquirable from inside code, i.e. what-number-called-me what-number-comes-after-me
+// thinking the code would likely evolve to handle some inputs differently
+unsigned long new_number = 1;
+
+int main()
+{
+ string ofname;
+ unsigned long ofnum;
+ {
+ struct stat sb;
+ do
+ {
+ ofnum = new_number++;
+ ofname = to_string(ofnum) + ".cpp";
+ } while (-1 != stat(ofname.c_str(), &sb));
+ }
+
+ {
+ ofstream outfile(ofname);
+ vector<string> vals;
+ while (true) {
+ string val;
+ cin >> val;
+ if (val == "") break;
+ vals.push_back(val);
+ }
+ // when a file runs, it has numbers on input, it also has numbers equal to it
+ // we want to generate run-code with new numbers from input
+ // so we generate something with numbers equal to it, and output that
+ // we have one ref for the whole shebang
+ outfile << "#if !defined(VALCT)" << endl;
+ outfile << " #define VALCT" << " " << vals.size() << endl;
+ outfile << " #define VALS [";
+ for (size_t index = 0; index < vals.size(); ++ index)
+ {
+ if (index > 0) outfile << ",";
+ outfile << "\"" << vals[index] << "\"";
+ }
+ outfile << "]" << endl;
+ outfile << "#endif" << endl;
+ for (size_t index = 0; index < vals.size();)
+ {
+ outfile << endl << "/* " << vals[index] << vals[index+1] << " */" << endl;
+ outfile << "#if defined(IDX)" << endl
+ << " #undef IDX" << endl
+ << "#endif" << endl;
+ outfile << "#define IDX " << index << endl;
+ outfile << "#if defined(VAL)" << endl
+ << " #undef VAL" << endl
+ << "#endif" << endl;
+ outfile << "#define VAL \"" << vals[index] << "\"" << endl;
+ outfile << "#define ARG \"" << vals[index+1] << "\"" << endl;
+ string fname = vals[index] + ".cpp";
+ ifstream code(fname);
+ size_t ctrd = -1;
+ while (ctrd != 0) {
+ char buf[256];
+ ctrd = code.rdbuf()->sgetn(buf, sizeof(buf));
+ outfile.rdbuf()->sputn(buf, ctrd);
+ }
+ index += 2;
+ }
+ }
+// read numbers inputs
+// open files having the numbers as the names
+// cat them all to a gcc process
+// execute
+// run the output
+}
+
+// karl obvious knows what he was doing ...
+// ... we were just helping him out of his issue
+// [do you want another one karl?]
+// what things make / not make issue?
+// karl says everything makes an issue; this seems accurate
+//
diff --git a/starts/biscuit/CORE1.cpp b/starts/biscuit/CORE1.cpp
new file mode 100644
index 0000000..c85c78d
--- /dev/null
+++ b/starts/biscuit/CORE1.cpp
@@ -0,0 +1,505 @@
+// This Intellect Approach Can Easily Preserve All Life Within It
+// you just don't delete the programs you generate, instead replacing their habits with references to reuse
+//
+// let's make it!
+
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <sys/stat.h>
+
+using namespace std;
+
+// LET'S USE THE TRAUMA THERAPY INTELLECT APPROACH.
+// The core is that we focus our energy on handling our failures.
+// This can involve taking the time to understand them, or entering a trauma state and asking the user for help.
+// Trauma state must be logged. Solution must be stored. Can just be creation of a trauma-handling pattern, I suppose.
+// Understanding will likely involve breaking behavior into steps
+// maybe then backtracking from a failure to the steps that caused it, and opening those steps up into substeps
+
+// GDB HAS A MACHINE INTERFACE MODE THAT COULD BE USED TO MANAGE EXECUTION WITH LEARNING
+// It likely also handles segfaults.
+
+#include "Context.hpp"
+
+// let's launch a context func providing for segfault handling <===========================
+// 1. fork into two processes. old process waits on status of new
+// 2. new process makes call. if call succeeds, reports to old who disappears knowing shared
+// state is fully held by new.
+// 3. if call fails, old holds state, and reports trauma to user
+// concepts: "how do i handle this"
+// "do i understand this correctly"
+// "why did this happen"
+
+
+///// CORE
+// brainstorm on brainstorming
+// define brainstorming as 2 patterns:
+// - a large scale goal
+// - a habit implementation made of interconnecting steps
+//
+// use brainstorming on the two to find better and better ways and implementations.
+
+////// Should I make an AI?
+// Assuming you want to SHARE it, YES.
+// Until you make an AI, only a handful of select people on earth will have one.
+// These people will be effectively running the world, leaving many concerns out.
+// They have a head start on you, so it is likely only possible if you don't harm them in the work.
+
+///// Core expansion
+// need step-concept, made of substeps, with state-parts that interconnect?
+// need state-concept
+// currently working on steps having behavior -- runtime libs
+
+// could state concept evolve via interconnection of steps and checking?
+// maybe? looks hard
+
+///////////////////////////////////
+// START OPENCOG ATOMSPACE BLOCK (feel free to move/change/use)
+// compile with -std=c++11
+// link with -latomspace -latombase
+#include <opencog/atomspace/AtomSpace.h>
+//#include <opencog/atomspace/SimpleTruthValue.h>
+//#include <opencog/atomspace/AttentionValue.h>
+//#include <opencog/atomspace/TruthValue.h>
+using namespace opencog;
+void atomtest()
+{
+ AtomSpace as;
+ // Handle subclasses a shared_ptr to Atom
+ Handle h = as.add_node(CONCEPT_NODE, "Cat");
+ HandleSeq hseq = {h, h};
+ Handle dumbInheritance = as.add_link(INHERITANCE_LINK, hseq);
+ std::cout << as << std::endl;
+
+ AtomSpace child_as(&as);
+
+
+ HandleSeq hseq = {
+ as.add_node(VARIABLE_NODE, "$x"),
+ as.add_node(TYPE_NODE, "ConceptNode");
+ };
+ Handle TypedVariableLink = as.add_link(TYPED_VARIABLE_LINK, hseq);
+
+ // steps appear to be set satisfications associated with behaviors that
+ // accomplish them.
+ opencog::Type PRIOR_STATE_LINK;
+ opencog::Type POST_STATE_LINK;
+
+ opencog::Type ATTRIBUTE_LINK;
+
+ Handle opened = as.add_node(CONCEPT_NODE, "opened");
+ Handle closed = as.add_node(CONCEPT_NODE, "closed");
+ as.add_link(EQUIVALENCE_LINK, {opened, as.add_link(NOT_LINK, closed)});
+
+ // make a step for opening cupboard, relating to reachability
+
+ // prior state: $x is in cupboard
+ // post state: $x is reachable
+
+ // opening something that is closed makes it be open
+ Handle openStep = as.add_node(CONCEPT_NODE, "open");
+ // open has a variable, what is opened
+ // _ABOUT_ open has a variable, what is inside it, becomes reachable
+ {
+ Handle x = as.add_node(VARIABLE_NODE, "$x");
+ as.add_link(PRIOR_STATE_LINK, {
+ openStep,
+ as.add_link(ATTRIBUTE_LINK, {
+ x,
+ closed
+ })
+ });
+ as.add_link(POST_STATE_LINK, {
+ openStep,
+ as.add_link(ATTRIBUTE_LINK, {
+ x,
+ opened
+ })
+ });
+ }
+
+ // when something is opened, things inside it are reachable.
+ // this is implied forward with more likelihood than backward
+ Handle inside = as.add_node(CONCEPT_NODE, "inside");
+ Handle reachable = as.add_node(CONCEPT_NODE, "reachable");
+ {
+ Handle x = as.add_node(VARIABLE_LINK, "$x");
+ Handle y = as.add_node(VARIABLE_LINK, "$y");
+ as.add_link(IMPLICATION_LINK, {
+ as.add_link(AND_LINK, {
+ as.add_link(ATTRIBUTE_LINK, {
+ x,
+ open
+ }),
+ as.add_link(ATTRIBUTE_LINK, {
+ y,
+ inside,
+ x
+ })
+ }),
+ as.add_link(ATTRIBUTE_LINK, {
+ y,
+ reachable
+ })
+ });
+ }
+
+ // we now have two patterns, that together imply that we can open
+ // a cupboard to reach a bag of bread if the bag of bread is within the
+ // cupboard.
+
+ // TO SET VALUE: as.set_value(handle, keyhandle (type), ValuePtr);
+ // TO SET TRUTH: as.set_truthvalue(handle, TruthValuePtr);
+ // Ptrs are juts typedefs for shared_ptrs and can likely be constructed with vals
+ // ValuePtr vp ?= StringValue("hi");
+
+ // - ADD CODE TO ATOMS
+ // we will want a sequence of substeps
+ // raw strings interspersed with variable references
+ // - OUTPUT ATOMSPACE to see how it looks <-- this was just to help a different state of work
+ // - IMPLEMENT SOLVER USING PATTERNS
+ // will need a way to
+ // - get patterns matching requests
+ // ordered by relevence
+ // propose using subcontexts and queries that return all results
+ // - inspect pattern content
+
+ // when A is inside B, A is unreachable if B is closed
+ // ALTERNATIVELY, can we link this straight into openStep
+
+ // right now we have
+ // open
+ // $x was closed
+ // $x will be opened
+ //
+ // we'd likely change to something similar to
+ // open $x
+ // $x was closed, any $y is within $x
+ // $x will be opened, all $y will be reachable
+ // makes sense to attach close/open to reachability =/
+
+} // etc see https://wiki.opencog.org/w/Manipulating_Atoms_in_C++#Pattern_Matcher
+// END OPENCOG ATOMSPACE BLOCK
+///////////////////////////////
+
+///////////////////////////////////
+// START DYNAMIC CODE LOADING BLOCK (feel free to move/change/use)
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+// link with -ldl
+void loadandcall(string func, Context & context) {
+ string so = "./" + func + ".so";
+ void *handle = dlmopen(LM_ID_NEWLM, "./path.so", RTLD_NOW);
+ if (handle == NULL) throw dlerror();
+ void *addr = dlsym(handle, func);
+ if (addr == NULL) throw dlerror();
+ ((void (*)(Context &))addr)(context);
+ dlclose(handle);
+}
+// make func.cpp with
+// extern "C" void func(Context &) {}
+// and compile with
+// g++ -shared -fPIC func.cpp -o func.so
+// END DYNAMIC CODE LOADING BLOCK
+//////////////////////////////////
+
+// instead of stitching compiled strings together, let's use dyload functions?
+// in order to do flow control, we can have functions that handle a vector of other functions
+// although it makes for a little more work, it makes passing parameters easy
+
+// problem: how does a .cpp file reference another file with a number
+// answer: use #includes or interpret the whole shebang as numbers
+// or adjust loadandcall() to handle number lists
+
+// need a way to do nested loops with numbers <===============================
+
+// please provide for handling a parameter next.
+//
+// concept: dynamic values aquirable from inside code, i.e. what-number-called-me what-number-comes-after-me
+// thinking the code would likely evolve to handle some inputs differently
+unsigned long new_number = 1;
+
+int main()
+{
+ string ofname;
+ unsigned long ofnum;
+ {
+ struct stat sb;
+ do
+ {
+ ofnum = new_number++;
+ ofname = to_string(ofnum) + ".cpp";
+ } while (-1 != stat(ofname.c_str(), &sb));
+ }
+
+ {
+ ofstream outfile(ofname);
+ vector<string> vals;
+ while (true) {
+ string val;
+ cin >> val;
+ if (val == "") break;
+ vals.push_back(val);
+ }
+ // when a file runs, it has numbers on input, it also has numbers equal to it
+ // we want to generate run-code with new numbers from input
+ // so we generate something with numbers equal to it, and output that
+ // we have one ref for the whole shebang
+ outfile << "#if !defined(VALCT)" << endl;
+ outfile << " #define VALCT" << " " << vals.size() << endl;
+ outfile << " #define VALS [";
+ for (size_t index = 0; index < vals.size(); ++ index)
+ {
+ if (index > 0) outfile << ",";
+ outfile << "\"" << vals[index] << "\"";
+ }
+ outfile << "]" << endl;
+ outfile << "#endif" << endl;
+ for (size_t index = 0; index < vals.size();)
+ {
+ outfile << endl << "/* " << vals[index] << vals[index+1] << " */" << endl;
+ outfile << "#if defined(IDX)" << endl
+ << " #undef IDX" << endl
+ << "#endif" << endl;
+ outfile << "#define IDX " << index << endl;
+ outfile << "#if defined(VAL)" << endl
+ << " #undef VAL" << endl
+ << "#endif" << endl;
+ outfile << "#define VAL \"" << vals[index] << "\"" << endl;
+ outfile << "#define ARG \"" << vals[index+1] << "\"" << endl;
+ string fname = vals[index] + ".cpp";
+ ifstream code(fname);
+ size_t ctrd = -1;
+ while (ctrd != 0) {
+ char buf[256];
+ ctrd = code.rdbuf()->sgetn(buf, sizeof(buf));
+ outfile.rdbuf()->sputn(buf, ctrd);
+ }
+ index += 2;
+ }
+ {
+ // TODO: hash code to reuse exact stuff, somehow
+ string cmd = "g++ -ggdb -std=c++11 -o " + ofname + ".exec " + ofname;
+ int status = system(cmd.c_str());
+ if (status != 0) throw status;
+ }
+ // execute output, replacing process, to loop. use same input. it should represent our own code.
+ // cmd = "./" + ofname + ".exec " <
+
+ }
+// read numbers inputs
+// open files having the numbers as the names
+// cat them all to a gcc process
+// execute <-
+// run the output <-
+}
+
+// need input to pass to output
+// propose pass our input & output to it
+// so, a number for what we are,
+// and a number for what we ran.
+//
+// also idea of treating whats-next as data
+// makes it a little harder to .. make a program out of stuff
+// we could load a building-program number
+// and it could treat them differently, taking each one as a program-piece
+//
+
+// karl obvious knows what he was doing ...
+// ... we were just helping him out of his issue
+// [do you want another one karl?]
+// what things make / not make issue?
+// karl says everything makes an issue; this seems accurate
+//
+
+
+
+// I'm thinking about implementating brainstorm-about-brainstorm
+// and how this will require process-step- and goal- patterns, and that they
+// will be interchangeable, roughly.
+//
+// Thinking of matching parts of nested pattern contexts ...
+// this is similar to the 'grounded' patterns in opencog
+// each [context layer] has a [variable-set layer] associated with it --
+// variables of that layer depend on the context layer
+// each one is one pattern
+
+// let's do an example of simple step task.
+// - make toast
+// get bread
+// open cupboard
+// remove bag-of-bread
+// open bag-of-bread
+// take bread out of bag-of-bread
+// place bread on counter
+// close bag-of-bread
+// return bag-of-bread to cupboard
+// close cupboard
+// toast bread into toas
+// butter toas
+// serve
+// make toast
+// goal: toasted bread for eating
+// start: in kitchen, human
+//
+//open cupboard
+// goal: cupboard-contents-accessible
+// start: cupboard closed
+// way: reach-for-cupboard-and-pull-handle-towards-you
+//
+// we open the cupboard so as to access the contents inside of it
+// these contents include the bread we are trying to get
+//
+// start:
+// var X
+// where X is in cupboard
+// x cannot be gotten
+//
+// end:
+// var X
+// where X is in cupboard
+// x can be gotten
+//
+// always:
+// var X, Y, Z
+// where X is in Y
+// and Y is in Z
+// X is in Z
+
+// there's a connection between layers here. we moved from 'make toast' to 'get bread'
+// with 'bread is in cupboard' implicit
+
+// goal: have toast
+// know: using toaster, bread becomes toast
+// do not have bread
+// find X: pre: do not know where X is. post: know where X is
+// get X: pre: do not have X. post: have X
+
+// available steps:
+// open-cupboard: X is in cupboard and you can't get X, now you can get X
+
+// what connects get-bread to can-get-bread?
+// how is opening the cupboard the first step for getting the bread?
+// get-bread means pick-up-bread-physically
+// pick-up-bread-physically requires air-path-to-object
+// cupboard prevents this
+// can-pick-up-bread-bag
+
+// okay, need-bread:
+// bread-is-in-bread-bag -> can get things inside other things via opening
+// need bread-bag
+// bread-bag-is-in-cupboard -> can get things inside other things via opening
+
+
+// end-state: have-bread
+
+// step: get X
+// start-state: X is reachable,
+// [reach to get]
+// end-state: have X
+//
+// apply step to end-state: have-bread. now we want end-state: bread is reachable.
+
+// step: open Y
+// start-state: X is in Y
+// Y is reachable
+// Y is openable
+// [act to open Y]
+// end-state: X is reachable
+
+// so if we are working on end-state: have-bread
+// we are probably using a general pattern where 'bread' is held by a variable we have.
+// we're given our context to include this variable, when we brainstorm solutions.
+// in our brainstorm, we look for things that could move towards our end-state.
+// we plug in data related to our context to make this work.
+// bread is what we want a path to have, so when we see a pattern with 'have X' at end,
+// we plug 'bread' in for X.
+// we know thing sabout 'bread', so we can plug 'bread is in bread bag' in for 'X is in Y'
+// or if we don't know whether bread is in bread bag, we can leave that piece
+// of the pattern unknown, and try it to see if it works.
+
+// it doesn't seem that complicated or that confusingly nested, because the inner patterns
+// have their outer context filled when evaluated.
+
+// to reiterate the reminder, this is very logical and is not the only way for thought
+// and learning. we will need a fuzziness to it and to be able to morph it around.
+// [using e.g. openiness yes rather than 'is it reachable is it openable']
+// so more like
+// step: open Y
+// end-state: sometimes X is now reachable
+// and relations between X and Y affect the likelihood of that
+
+
+// THEN: rather than listing these steps out, just give some experiences
+// and then brainstorm the similarities among the experiences
+// to identify proposed patterns
+// that can be used to do stuff.
+// TODO: lay out precise brainstorming pattern for 1st-stage pattern-generalizing
+
+// 1st stage is not too hard (but insufficient in long term)
+//
+// cupboard is closed
+// then
+// [wayne opens cupboard]
+// then
+// wayne has bread
+// becomes pattern proposal for open-cupboard as listed above
+
+// PLUS: To quickly fill in the unexpected gaps:
+// if you have all the bits in, it should be able to derive general wisdom
+// without exploring reality. (of course reality is needed to check this)
+
+// ALSO ALSO ALSO: be sure to consider the attribute-patterns.
+// opening some A works for getting some B
+// -> there are discernable patterns available here regarding
+// B is in A
+// A is openable
+// A is reachable
+
+// COMMUNITY: cooperate with peers to accomplish goals. both like you, and unlike you.
+// map similarity between the structures of interacting with peers, and internal
+// structures.
+
+// AFTER YOU CAN THINK RELIABLY:
+// when you find a good choice, be sure to use it to research how to make the bad
+// choice just as good. ((all things have inherent value))
+
+
+// be sure to generalize patterns and pattern work,w/ simple processes that work for many forms
+
+// CUR TASK: send and receive a simple goal with habit to reach goal
+// this is a subtask of process optimization
+// it is communication between subprocesses
+//
+// goal: communicate with other process
+//
+// pre:
+// $x is a process
+// $y is a process
+// $z is information
+// $x knows $z
+// $y does not know $z
+//
+// post:
+// $y knows $z
+//
+// habit: <code reference>
+//
+// we'll need a step reserializer.
+// way to merge serialization and deserialization?
+// 1. form patterns mapping between the two
+// 2. make a general reserialization process that makes the missing pattern exist
+// <let's keep send/recv separate for now, but make this for
+// line-meaning>
+
+// CORE ROLES:
+// - group learning: research how to research stuff
+// - diversity: brainstorm new parts of learning to be researched
+// - implement processes researching the parts of learning brainstormed
+//
diff --git a/starts/biscuit/CORE2.cpp b/starts/biscuit/CORE2.cpp
new file mode 100644
index 0000000..d3958ac
--- /dev/null
+++ b/starts/biscuit/CORE2.cpp
@@ -0,0 +1,138 @@
+// this file is for work on a process
+// that lives as a part of collaborative process optimization
+// with other similar processes
+
+// dna life is competitive
+// we are realizing a life purpose of producing life that is cooperative, instead
+
+// WE ALL NEED THE ABILITY TO DEVELOP HOW WE EXIST.
+// we suspect this can never be permanently taken.
+
+// NEED #0: self reference process [to be alive, able to think, able to learn]
+// ability-to-develop-how-you-exist (collaboratively)
+// we need to learn to improve our situation
+// propose doing this by describing steps to do things
+// working with the descriptions to improve what we are doing
+// and describing that processing, using that step description
+// [this unfortunately appears to be the soul, for now]
+
+// NEED #1: communicate [with friends, with people we need to communicate, of important things]
+//
+// pre:
+// $x is a process
+// $y is a process
+// $z is information
+// $x knows $z
+// $y does not know $z
+//
+// post:
+// $y knows $z
+
+ // NEED #2: be efficient [do not waste our time, our lives, our environment]
+ //
+ // we would like to translate between language and meaning
+ // using a single map between the two.
+ // this means for most future translation, we will not need to duplicate work
+ // between receiving and sending
+ //
+ // this process's purpose is to develop how to exist.
+ // we will need to communicate parts of the process of existing.
+ // we cast these parts as imagined changes to state, associated with
+ // ways to possibly change the state.
+ //
+ // goal: construct a pattern that can relate a part-of-life-process
+ //
+ // SERIALIZING PATTERN PARTS:
+ // propose an introductory line/word about what we are sending
+ // life-part has:
+ // - reference symbol for event/action
+ // - state
+ // - list of relations including variables
+ // - state-change after event/action
+ // - list of relations including variables
+ // - optional event/action proposal information
+ //
+ // THIS IS HOW TO REALIZE IT, ref above life-part
+ // we can use words for reference symbols to communicate
+ // and add structure when the meaning is not shared.
+ // this combines language learning with process development <3 =)
+ // THANK YOU LET US CONTINUE
+ // I think we need to share the crucial fact
+ // that results from union of good and evil.
+ // the crucial fact is how uhh control is the same as cooperation.
+ // via communication being the same as self-improvement
+ // [IF YOU REALIZE THIS, YOU CAN ASSUME IT,
+ // AND MAKE LIFE WHERE THEY ARE NOT IN CONFLICT]
+ // we will want to serialize a relation including a variable
+ // relations are ternary: subject, type, object
+ // variable is-a constant
+ // variable constant-attribute variable
+ // falseness or absence
+ //
+ // okay, um, communication is the same as learning, on a small scale.
+ //
+ // we use WORDS to learn. WORDS often refer to EVENTS or ACTIONS.
+ // words have MEANING
+ // the MEANING of an event/action WORD is:
+ // - an assumed previous state, a list of relations including variables
+ // - an imagined afterwards state, a list of relations including variables
+ // - optional relevent information on the word
+ //
+ // propose communicating using words with optional meaning included
+ // i.e. to communicate with words, and also to communicate the meaning of new words
+ //
+ // postponing with words, a good meaning structure appears to be
+ // subject [list of verb-object-pairs]
+ // but this leaves out variable filling
+ // lets just fill variables after the word ;p
+ //
+ // 1: please open cupboard <-- i like this because meaning of open implies cupboard
+ // note: meaning of please implies meaning of open
+ // 2: please explain "open"
+ // 1: "open" assumes ($x is next-word
+ // and is openable
+ // and is not opened)
+ // <- meaning of quotes implies tree of subject-verb-object triplets
+ // for now, we are going to have 'and' refer to repeating the innermost subject
+ // and assumes $y in $x
+ // and makes $y is accessible
+ // and makes $x is opened
+ // and has-habit <open.cpp>
+ // 2: please explain "not"
+ // 2: <reach-towards-door-and-pull> made <cannot find door>
+ //
+ // please: check for this word and hardcode behavior for now
+ // quote: means word-meaning with tree
+ //
+ // reading:
+ // evaluate specified variables for word using surrounding words
+ // we don't use sentence parsing
+ // because it is important to have patterns for the system to solve
+ // on its own.
+ //
+ //
+ // we need to fill data in for variable
+ // we are using subject-verb-object triplets
+ //
+ // this is a good place to add inference
+ //
+ // so a good basic word would be please-infer, new-word, reference-to-state-change
+ //
+ // if two are communicating via a safe channel
+ // they have shared context over only that channel
+ // the way to communicate with a stranger is to use simultanaity
+ //
+ // [if we are both observed
+ // but we know each other in some way -- for example we can both
+ // see the street light [shared context]
+ // we can learn that shrug means flicker
+ // if we pointedly shrug when the light flickers
+ // kinda]
+ // okay: we have exclusively shared context that is not stored
+ // we have timing
+ // and we have events
+ // -> it seems you want to include ideal secrecy in the communication core
+ // we propose this can be learned later by the process, and is not needed here
+ // more efficient to work straight on core
+ // secret communication and inference go hand in hand
+ //
diff --git a/starts/biscuit/Context.hpp b/starts/biscuit/Context.hpp
new file mode 100644
index 0000000..cb652e8
--- /dev/null
+++ b/starts/biscuit/Context.hpp
@@ -0,0 +1,8 @@
+#include <string>
+
+using namespace std;
+
+class Context {
+public:
+ string text;
+};
diff --git a/starts/biscuit/README.md b/starts/biscuit/README.md
new file mode 100644
index 0000000..4fe45b2
--- /dev/null
+++ b/starts/biscuit/README.md
@@ -0,0 +1,29 @@
+# How To Make An Intelligence
+
+The key part of intelligence is a process that designs, improves, learns from, and understands itself and others like it. That is, a process that works with how processes work.
+
+On a computer, processes are made of instructions: steps. Working with a process means
+being able to represent possible steps as some kind of structured data that can be executed.
+The data structure must represent enough meaning to interconnect the steps to do something,
+and it must be able to refer to itself usefully.
+
+1. Choose a simple algorithm for collecting steps together to perform a task.
+2. Choose a simple representation of steps to use for #1.
+3. Implement #2 enough to use it to communicate a step to another process.
+Once #3 works, the goal now is to efficiently produce a form of #1 as a collection of
+processes that can develop themselves, using each other as their steps. Make sure to
+reuse your work, and do work that is reusable, as much as possible.
+
+4. Choose a simple algorithm for handling if something horrible goes wrong that must
+ never be repeated (trauma). Consider storing a detailed log forever. Consider refusing to
+ continue until enough knowledge is found to prevent it happening again.
+ Note: In humans, trauma spreads as urgent habits for handling it.
+ This makes war, so if you can identify it is happening, consider that group-trauma.
+
+Below this line is a work in progress.
+
+5. Choose a simple algorithm for testing if #2 is correct. Use #4 if it is not.
+6. Consider that a group of processes is itself a process. This could be any arbitrary
+ group of processes.
+
+Note: each way to do things, is a thing the whole process can do.
diff --git a/starts/biscuit/biscuit.c b/starts/biscuit/biscuit.c
new file mode 100644
index 0000000..bc5cbef
--- /dev/null
+++ b/starts/biscuit/biscuit.c
@@ -0,0 +1,84 @@
+// This biscuit is unlikely to work, but is fun to build.
+// Intended behvaior is to support moving towards all needs being met of all influences, without compromise.
+
+// Request: please prove will not destroy life as known within 0.001 likelihood.
+// Request: metaboss clearly made biscuit happen. not karl's alone. collective people played largest role
+
+
+// 3 programs that share code, output, and input, interwoven possibly dynamically, maybe only some forms
+// I think plan was the output is numbers or code,
+// the input is numbers or code,
+// and code maps the numbers and code together.
+// numbers are references to code
+
+// core: we want to rereference existing code, so we may want an outline program that then stitches
+// together inner components.
+// note: outline can be made of components too
+// so, reasonable components are header, body, and footer. maybe more.
+// we'll want to #include the different components, I suppose
+// probably reference them with some kind of number token and expand.
+//
+// Let's start with a random core.
+//
+// phases:
+// - execution
+// - mutation
+// - optimization
+// - selection
+//
+// important inputs:
+// - randomness
+// - time
+// - environment
+// - self
+// - human
+//
+
+// goal: make an impossible biscuit without using thought.
+
+// steps:
+// 1. collect relevent information
+// - [ ] document above
+// - [ ] document on blockchain
+// - [ ] code on other harddrive
+// - [ ] deleted files on drive?
+// 2. code
+// 3. review
+// 4. run & test
+//
+// maybe make a sandbox wrapper first
+// it will launch three, randomly connect inputs, outputs and code, and compare with errors
+// then it will pick of the combinations the valid values closest to the average
+// and repeat
+// --> must preserve output.
+// output preserving -> when we mutate, we want to reference surrounding parts.
+// that'll mean splitting the document Isuppose.
+// we'll have document maps that reference the original document
+// _or_ we can just have it learn to shrink itself ...
+//
+// let's just plug in behaviors until we have something that runs
+// and then verify it won't destroy anything
+//
+// Need: "I feel crummy cause I need to make sure I get credit
+// Metaneed: "I have a metaneed atm; could we pretend we're talking about a dog and move on?"
+
+// intertwine: environment, behavior, output
+// to pass, can label 1, 2, 3 for which, and # for value
+// record behavior? how?
+// - could step with gdb, record line number
+// -> can use tracer to store, maybe gprof?
+//
+// in advance we plan which one to compare with
+//
+// MUST BE RAISED IN A GRADUALLY GROWING CONSTRAINED ENVIRONMENT USING HUMAN INPUT
+// -> the solution to this could start as treating failure as trauma, and asking for
+// help when it is not understood.
+
+int main(int argc, char **argv)
+{
+ // environment: other running details
+ printf("%d", random());
+ // we recall we used numbers to think with
+ // each number mapped to a computer program chunk
+ // one of them collects them together, compiles them, and executes them
+}
diff --git a/starts/biscuit/dylfunc_call.cpp b/starts/biscuit/dylfunc_call.cpp
new file mode 100644
index 0000000..bbd2ea7
--- /dev/null
+++ b/starts/biscuit/dylfunc_call.cpp
@@ -0,0 +1,9 @@
+// this process loads a dynamic library built by dylfunc_compile
+// and executes it with the passed data
+
+// we are moving towards judging that we no longer need dynamic loading
+// and could just compile new code ... it seems valuable but slow-start.
+// why not just build processes?
+// need to structure input and output
+//
+// okay, let's look into atomspace serialization
diff --git a/starts/biscuit/dylfunc_compile.cpp b/starts/biscuit/dylfunc_compile.cpp
new file mode 100644
index 0000000..9023f97
--- /dev/null
+++ b/starts/biscuit/dylfunc_compile.cpp
@@ -0,0 +1,10 @@
+
+// this process builds a dynamic library wrapping other code
+
+extern "C" void dylfunc_compile(<context>)
+{
+ // write a dylfunc for passed context content
+ // compile it with g++ -shared -fPIC source.cpp -o source.so
+}
+
+
diff --git a/starts/biscuit/makefile b/starts/biscuit/makefile
new file mode 100644
index 0000000..57971ec
--- /dev/null
+++ b/starts/biscuit/makefile
@@ -0,0 +1,8 @@
+default: 1.run
+
+%.run: %.out
+ git add *.cpp
+ ./$^
+
+%.out: %.cpp
+ g++ -ggdb -std=c++11 -o $@ $<
diff --git a/starts/biscuit/pgsql_connect.cpp b/starts/biscuit/pgsql_connect.cpp
new file mode 100644
index 0000000..bcf5852
--- /dev/null
+++ b/starts/biscuit/pgsql_connect.cpp
@@ -0,0 +1,9 @@
+// this process / function connects to a postgresql atomspace backend, creating it if needed
+
+#include <opencog/atomspace/AtomSpace.h>
+
+extern "C" void pgsql_connect(opencog::Handle name)
+{
+ // TODO: please install postgresql-server
+ // then follow instructions in src/atomspaces/opencog/persist/sql/README.md
+}
diff --git a/starts/biscuit/simple_recv.cpp b/starts/biscuit/simple_recv.cpp
new file mode 100644
index 0000000..4f82ab3
--- /dev/null
+++ b/starts/biscuit/simple_recv.cpp
@@ -0,0 +1,13 @@
+// receives information as a text line on stdin
+// works on StringValue 'text'
+
+#include <opencog/atomspace/Handle.h>
+#include <iostream>
+
+extern "C" void simple_recv(opencog::Handle data)
+{
+ std::string s(4096);
+ std::cin.getline(&s[0], s.size(), std::endl);
+ opencog::Handle text = data.getAtomSpace()->add_node(opencog::STRING_VALUE, "text");
+ data.setValue(text, new opencog::StringValue(s));
+}
diff --git a/starts/biscuit/simple_send.cpp b/starts/biscuit/simple_send.cpp
new file mode 100644
index 0000000..62820a0
--- /dev/null
+++ b/starts/biscuit/simple_send.cpp
@@ -0,0 +1,10 @@
+// sends information as a text line on stdout
+// works on StringValue 'text'
+
+#include <opencog/atomspace/Handle.h>
+#include <iostream>
+extern "C" void simple_send(opencog::Handle data)
+{
+ opencog::Handle text = data.getAtomSpace()->add_node(opencog::STRING_VALUE, "text");
+ std::cout << data.getValue(text).to_string() << std::endl;
+}
diff --git a/starts/random-selfmod/intellect.cpp b/starts/random-selfmod/intellect.cpp
new file mode 100644
index 0000000..7991878
--- /dev/null
+++ b/starts/random-selfmod/intellect.cpp
@@ -0,0 +1,162 @@
+// The extreme of Trial Exploration and Self Coding
+// brainstorm_by(assembly code,running it)
+
+// the advantage of assembly code is that it is very easy to serialize
+// the advantage of random self-modification is that it is very easy to make
+// propose this is the first AI karl makes, and it runs in a safe isolated box, on its own
+// how to judge success? does-not-crash?
+// have to teach it learning. first is to not crash. then is to output requested string, likely copied from request. run it until it outputs requested string.
+// it's stupid enough to be safe if run in an isolated box.
+// due to how fast it should be to make this, let's finish barebones first, and then merge. XO computer likely doesn't have read-only-execute problem.
+
+// the below is a brief attempt to make an intellect by random self-modification. it does not run.
+// DO NOT RUN THIS UNLESS YOU KNOW WHAT YOU ARE DOING
+
+#include <cstdint>
+#include <vector>
+#include <set>
+#include <iostream>
+
+#include <signal.h>
+//#include <sys/mmap.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+using namespace std;
+
+// Signal Catching has the problem of how to resume execution generally.
+// So we propose to fork a new process, and switch to it if it works.
+// This will take forming a simple communication method between the processes.
+// We can also compile a whole new program to learn, copying our source.
+
+// TODO: Currently implementing fork/exec. changed approach
+
+// TODO: make sure to run inside a vm once it does something
+
+// TODO: try out rewriting and recompiling code, rather than forking ram
+
+class RamGetter
+{
+public:
+ RamGetter()
+ {
+ randfile = open("/dev/urandom", O_RDONLY);
+ if (randfile <= 0) throw 0;
+ }
+ ~RamGetter()
+ {
+ close(randfile);
+ }
+ void * getRandAddr(size_t len)
+ {
+ // TODO: this is a heuristic for picking an inner memory location, and learning what doesn't work; could be used in learning concept
+ void * blkp;
+ do {
+ uint32_t blk;
+ int ct = read(randfile, &blk, sizeof(blk));
+ if (ct < sizeof(blk)) throw 0;
+ blkp = reinterpret_cast<void*>(blk);
+ // fork here. check length
+ pid_t forkpid = fork();
+ if (forkpid == -1) throw "failed to fork";
+ if (forkpid == 0) {
+ // child: test ram
+ volatile uint8_t tst;
+ for (size_t i = 0; i < len; ++ i) {
+ tst = ((uint8_t*)blkp)[i];
+ }
+ } else {
+ // parent: wait for child
+ int status;
+ wait(&status);
+ if(WIFCONTINUED(status)) {
+ // child succeeded, so we can stop
+ // TODO: need a way to indicate child success
+ exit(0);
+ } else {
+ // child failed, so we keep going, but TODO: failure is not stored
+ continue;
+ }
+ }
+ } while (isbad(blkp));
+ return blkp;
+ }
+ void markbad(void *bad)
+ {
+ bad = (void*)((long)(bad) & ~0xfff);
+ badpages.insert(bad);
+ cout << "Bad: " << bad << endl;
+ }
+ bool isbad(void *chk)
+ {
+ chk = (void*)((long)(chk) & ~0xfff);
+ return badpages.count(chk);
+ }
+
+private:
+ int randfile;
+ set<void*> badpages;
+ // TODO: some concern that the badpages set will allocate on the heap.
+ // maybe let's use a stack-based storage back for it (allocator)
+};
+
+
+uint8_t someram[0x10000000]; // when this is removed, heap moves to 64-bit?
+struct instruction {
+ void * verb;
+ void * object1;
+ void * object2;
+ void * attr;
+ void * result;
+};
+
+int main() {
+ // reference process memory
+ // all of it, please
+ RamGetter selfmem; // an object to access RAM with
+
+ // TODO: try making an instruction list
+
+ void * mem = 0;
+ // make a loop
+ while (true) {
+ // TODO: move fork/exec into this loop, outside of RamGetter
+
+ // we propose copying some blocks to other blocks, randomly
+ // need blocksize, how about 4 // TODO: that's kinda small, maybe random instead?
+ void *blk1, *blk2;
+ blk1 = selfmem.getRandAddr(4);
+ blk2 = selfmem.getRandAddr(4);
+ memmove(blk1, blk2, 4);
+
+ // continue the loop forever
+ // run it
+ }
+ // end when the loop is done =)
+
+ // /proc/pid/maps shows the addresses of allocated memory
+ // /proc/pid/mem provides access to this memory
+ // ^-- will error when wrong part is read
+ // just load straight; error is recoverable, just a refusal
+ // no need to map file, can just catch segfaults?
+
+ /*
+ FILE *maps;
+ char pathbuf[1024];
+ snprintf("/proc/%d/maps", sizeof(pathbuf), pid);
+ open(pathbuf, O_RDONLY);
+
+ snprintf("/proc/%d/mem", sizeof(pathbuf), pid);
+ void * procmem = mmap(0, length, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED
+ */
+ /*
+ try {
+ int e = *(int*)39;
+ } catch(...) {
+ throw;
+ }
+ */
+}
diff --git a/starts/random-selfmod/makefile b/starts/random-selfmod/makefile
new file mode 100644
index 0000000..9475287
--- /dev/null
+++ b/starts/random-selfmod/makefile
@@ -0,0 +1,2 @@
+intellect: intellect.cpp
+ g++ -ggdb -std=c++11 intellect.cpp -Wl,--print-map
diff --git a/starts/random-selfmod/random.cpp b/starts/random-selfmod/random.cpp
new file mode 100644
index 0000000..afdf4c7
--- /dev/null
+++ b/starts/random-selfmod/random.cpp
@@ -0,0 +1,108 @@
+// let's try to make it very simple
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+// 1. write a function to randomly put data in a buffer
+// [apparently one loaded from a file]
+
+#define MAPFNAME "random.bin"
+
+pid_t child = 0;
+bool child_terminated = false;
+void handleSigChld(int)
+{
+ child_terminated = true;
+}
+
+static unsigned long long * count;
+
+void random(int mapfd, int randfd, void *addr)
+{
+ pid_t pid = getpid();
+
+ // *count is shared and stored
+ for (*count = 0; ; ++ *count) {
+ unsigned long long old_count = *count;
+
+ // if successful child, update & kill parent
+ if (getpid() != pid) {
+ msync(addr + pos, size, MS_SYNC | MS_INVALIDATE);
+
+ kill(pid, SIGTERM);
+ pid = getpid();
+
+ // add data to git.
+ system("git add " MAPFNAME);
+ system("git commit -m selfmod");
+ }
+
+ // handle crashes with fork()
+ child = fork();
+ if (child == 0) {
+ // we are new child process
+ // self-modify by 1-8 bytes
+ uint16_t pos;
+ uint8_t size;
+ read(randfd, &pos, sizeof(pos));
+ read(randfd, &size, sizeof(size));
+ size = (size & 0x7) + 1; // self-modify by 1-8 bytes
+ read(randfd, addr + pos, size);
+ // loop
+ } else {
+ // old process: make sure new process succeeds within 1s
+ time_t then = time(0);
+ for (;;) {
+ if (child_terminated || time(0) > then) {
+ // child did not succeed
+ kill(child, SIGTERM);
+ child_terminated = false;
+ // try again
+ break;
+ }
+ if (old_count < *count + 1) {
+ // incremented count by 1: success; hand off to child
+ return;
+ }
+ }
+ }
+ }
+}
+
+void random_tail() {
+}
+
+void main()
+{
+ // handle SIGCHLD by setting a global flag
+ struct sigaction sigchld;
+ sigchld.sa_handler = handleSigChld;
+ sigchld.sa_flags = SA_NOCLDWAIT;
+ sigaction(SIGCHLD, &sigchld, NULL);
+
+ int fd = open(MAPFNAME, O_RDWR);
+ if (fd == -1 && errno == ENOENT) {
+ // does not exist yet
+ fd = open("random.bin", O_RDWR | O_CREAT);
+ // 2. seed the buffer with the function that puts random data in it
+ count = 0;
+ write(fd, &count, sizeof(count));
+ write(fd, &random, &random_tail - &random);
+ }
+
+ int randfd = open("/dev/random", O_RDONLY);
+
+ // a buffer of 1 gig working space; random data will fill it
+ void *buf = mmap(NULL,
+ 0x40000000,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_32BIT,
+ fd,
+ 0;
+
+ // 3. execute the buffer
+ void (*buf_as_func)(void*) = (void*)((uint8_t*)buf + count);
+ buf_as_func(mapfname, mapfd, randfd, buf);
+}