// Set the first zero to something else. See the console for how many choices you have. choices = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; // Gahan Wilson's SCIENCE FICTION HORROR MOVIE POCKET COMPUTER // National Lampoon, November 1971 // https://dochermes.livejournal.com/886108.html // The diagram is a Directed Acyclic Graph, a DAG. DAGs can be represented // without forward references, if you start at the "end" and work back to the // "beginning". // Each of these variables represents one node in the diagram. // They are named based on the line and their position in the line, starting // with line A at the top. Nodes named "plus" are rejoin points not shown // in the diagram as separate boxes. Note that because the diagram occasionally // has arrows that point up, the lines below are not in strict bottom-to-top // order. // Each node is a list with the text for a box, and the node names of the nodes // that it connects to. The text can be "undef" for a node that is only a // rejoin point without any text. Endpoints are marked by having no next-node // entries. // Mostly I have tried to stay true to the original diagram, without optimizing // the graph. For instance, it would make a lot of sense to have a single end // node with "(The End)", but the diagram doesn't. Similarly, the tiny/giant // pairs below invent/discover could be combined. In a few places I have taken // box with an "or" list and split it into several nodes; these are the nodes // that have a row, box number, and an additional letter. // "Army, Navy, Marine Corps, and/or Coast Guard" is an "and/or"; splitting it // would eliminate the possibility that they worked together. If you // interpret "or" as exclusive-or and "and" as all four working together, // those two nodes could reasonably be split into five nodes each. // I assume that the connector below "are friendly (The End)" is an error. // Note that half of the generated stories come from the two horizontal // connections at the top, and are very short (max four nodes). It would // be better to use some sort of weighting system to balance them out; // that's left as an exercise for the reader. module stop() {} // Stop customizer section p1 = [ "and they die (The End)" ]; p2 = [ "and they leave (The End)" ]; p3 = [ "and they turn into disgusting lumps (The End)" ]; p4 = [ "and they get married and live happily ever after (The End)" ]; oplus = [ undef, p1, p2, p3 ]; o1 = [ "which kills them (The End)" ]; n1 = [ "they die from catching chicken pox (The End)" ]; n2 = [ "so they kill us (The End)" ]; n3 = [ "so they put us under a benign dictatorship (The End)" ]; n4 = [ "so they eat us (The End)" ]; n6 = [ "which turns them into disgusting lumps (The End)" ]; n7 = [ "a cute little kid convinces them people are O.K.", oplus ]; n8 = [ "a priest talks to them of God", oplus ]; n9 = [ "they fall in love with this beautiful girl", oplus, p4 ]; m1 = [ "but", n1 ]; m3 = [ "but", n7, n8, n9 ]; lplusplus = [ undef, m1, n2, n3, n4 ]; n5 = [ "which fails", lplusplus ]; m2 = [ "so scientists invent a weapon", n5, o1, n6 ]; lplus = [ undef, lplusplus, m2, m3 ]; l1 = [ "a crowd of peasants with torches (The End)" ]; l2 = [ "the Army, Navy, Marine Corps, and/or Coast Guard (The End)" ]; l3 = [ "the atomic bomb (The End)" ]; l4 = [ "the atomic bomb", lplus ]; l5 = [ "the Army, Navy, Marine Corps, and/or Coast Guard", lplus ]; l6 = [ "a crowd of peasants with torches", lplus ]; k1 = [ "can be killed by", l1, l2, l3 ]; k2 = [ "cannot be killed by", l4, l5, l6 ]; j1 = [ "and", k1, k2 ]; i1 = [ "radioactive", j1 ]; i2 = [ "not radioactive", j1 ]; h1 = [ "and are", i1, i2 ]; e1 = [ "take a few and leave (The End)" ]; g1 = [ "want our women", e1, h1 ]; g2 = [ "are friendly (The End)" ]; g3 = [ "are friendly but misunderstood", h1 ]; g4 = [ "misunderstand us", h1 ]; g5 = [ "understand us all too well", h1 ]; e7 = [ "and eat us (The End)" ]; g6 = [ "look upon us only as a source of nourishment", e7, h1 ]; f1 = [ "which (who)", g1, g2, g3, g4, g5, g6 ]; e2 = [ "bug(s)", f1 ]; e3 = [ "reptile(s)", f1 ]; e4 = [ "mechanical device(s)", f1 ]; e5 = [ "super persons", f1 ]; e6 = [ "icky things", f1 ]; dplus = [ undef, e2, e3, e4, e5, e6 ]; d1 = [ "tiny", dplus ]; d2 = [ "giant", dplus ]; d3 = [ "tiny", dplus ]; d4 = [ "giant", dplus ]; d5a = [ "Martian", dplus ]; d5b = [ "Moon", dplus ]; d5c = [ "Betelgeusian", dplus ]; d5d = [ "extragalactic", dplus ]; cplus = [ undef, d5a, d5b, d5c, d5d ]; c1 = [ "invent", d1, d2 ]; c2 = [ "discover", d3, d4 ]; c3 = [ "tiny", cplus ]; c4 = [ "giant", cplus ]; c5 = [ "everyone dies (The End)" ]; c6 = [ "almost everyone dies (The End)" ]; b1 = [ "and everybody dies (The End)" ]; b2 = [ "and almost everybody dies (The End)" ]; b3 = [ "scientists", c1, c2 ]; b4 = [ "is attacked by", c3, c4 ]; b5 = [ "destroyed (The End)" ]; b6 = [ "saved (The End)" ]; b7 = [ "not destroyed but", c5, c6 ]; a1plus = [ undef, b1, b2 ]; a1a = [ "burns up", a1plus ]; a1b = [ "freezes", a1plus ]; a1c = [ "falls into the sun", a1plus ]; a1 = [ undef, a1a, a1b, a1c ]; a3 = [ "is struck by a giant comet and", b5, b6, b7 ]; a2 = [ "Earth", a1, a3, b3, b4 ]; start = a2; // The logic is easier to follow if it's positive logic. function is_defined(x) = !is_undef(x); // Recursively walk the graph starting at the specified node. module walk(node, storySoFar=undef, step=0) { // Glue together story so far and this node, but only include a space if // they are both present. newStory = (is_defined(storySoFar) && is_defined(node[0])) ? str(storySoFar, " ", node[0]) : is_defined(storySoFar) ? storySoFar : is_defined(node[0]) ? node[0] : ""; if (len(node) < 2) { echo(newStory); } else { if (len(node) < 3) { walk(node[1], newStory, step); } else if (choices[step] == 0) { echo(str(newStory, " ... (", len(node)-1, " choices)")); } else { i = (choices[step]-1) % (len(node)-1) + 1; walk(node[i], newStory, step+1); } } } walk(start);