-- ***********************************************************************
--
-- Module to genmerate a B-movie plot.
-- Copyright 2019 by Sean Conner.
--
-- This program is free software: you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the
-- Free Software Foundation, either version 3 of the License, or (at your
-- option) any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details.
--
-- You should have received a copy of the GNU General Public License along
-- with this program. If not, see <
http://www.gnu.org/licenses/>.
--
-- Comments, questions and criticisms can be sent to:
[email protected]
-- ***********************************************************************
-- luacheck: globals handler
-- luacheck: ignore 611
local randomseed = require "org.conman.math".randomseed
local str = require "org.conman.string"
local abnf = require "org.conman.parsers.abnf"
local lpeg = require "lpeg"
local io = require "io"
local math = require "math"
local string = require "string"
local table = require "table"
local ipairs = ipairs
local require = require
local tonumber = tonumber
local _VERSION = _VERSION
if _VERSION == "Lua 5.1" then
module("movie")
else
_ENV = {}
end
-- ***********************************************************************
local FILES do
local function readlist(filename)
local list = {}
for line in io.lines(filename) do
table.insert(list,line)
end
return list
end
-- ===========================================================
local filename = require "CONFIG".movie
local f = io.open(filename,"r")
local data = f:read("*a")
f:close()
local Carg = lpeg.Carg
local Cc = lpeg.Cc
local Cg = lpeg.Cg
local Cs = lpeg.Cs
local Ct = lpeg.Ct
local P = lpeg.P
local R = lpeg.R
local token = R"!~"^1
local cmd = P"BaseDir:" * abnf.WSP^0 * Cg(token,'basedir') * abnf.CRLF
+ P"Male-Names:" * abnf.WSP^0 * Cg(token,'males') * abnf.CRLF
+ P"Female-Names:" * abnf.WSP^0 * Cg(token,'females') * abnf.CRLF
+ P"Family-Names:" * abnf.WSP^0 * Cg(token,'family') * abnf.CRLF
+ P"Adjectives:" * abnf.WSP^0 * Cg(token,'adjective') * abnf.CRLF
+ P"Mission:" * abnf.WSP^0 * Cg(token,'mission') * abnf.CRLF
+ P"Occupation:" * abnf.WSP^0 * Cg(token,'occupation') * abnf.CRLF
+ P"Double-Mission:" * abnf.WSP^0 * Cg(token,'dmission') * abnf.CRLF
+ P"Template:" * abnf.WSP^0 * Cg(token,'template') * abnf.CRLF
+ R" ~"^0 * abnf.CRLF
local parser = Ct(cmd^0)
local rebase = Cs((-P"/" * Carg(1) * Cc'/')^-1 * P(1)^1)
FILES = parser:match(data)
FILES.males = readlist(rebase:match(FILES.males, 1,FILES.basedir))
FILES.females = readlist(rebase:match(FILES.females, 1,FILES.basedir))
FILES.family = readlist(rebase:match(FILES.family, 1,FILES.basedir))
FILES.adjective = readlist(rebase:match(FILES.adjective, 1,FILES.basedir))
FILES.mission = readlist(rebase:match(FILES.mission, 1,FILES.basedir))
FILES.occupation = readlist(rebase:match(FILES.occupation,1,FILES.basedir))
FILES.dmission = readlist(rebase:match(FILES.dmission, 1,FILES.basedir))
end
-- ***********************************************************************
local function pick_unique(list)
local p1,p2
p1 = list[math.random(#list)]
repeat
p2 = list[math.random(#list)]
until p1 ~= p2
return { p1 , p2 }
end
-- ***********************************************************************
local article = lpeg.S"BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz" / "a"
+ lpeg.P"one" / "a"
+ lpeg.Cc'an'
function handler(req)
local config = require "CONFIG"
local handler = require "handler"
local seed = randomseed(tonumber(req))
local bytes = 0
local function write(fmt,...)
local s = string.format(fmt,...)
io.stdout:write(s)
bytes = bytes + #s
end
local hero = pick_unique(FILES.males)
local heroine = pick_unique(FILES.females)
local lastname = pick_unique(FILES.family)
local madj = pick_unique(FILES.adjective)
local fadj = pick_unique(FILES.adjective)
local occupation = pick_unique(FILES.occupation)
local mission = pick_unique(FILES.mission)
local title = FILES.dmission[math.random(#FILES.dmission)]
local man = str.template(
string.format(
"%s %s %s is %s %s %s %s %s",
hero[1],hero[2],lastname[1],
article:match(madj[1]),madj[1],madj[2],
occupation[1],
mission[1]
),
{ his = "his" , her = "his" , he = "he" , she = "he" }
)
local woman = str.template(
string.format(
"%s %s %s is %s %s %s %s %s",
heroine[1],heroine[2],lastname[2],
article:match(fadj[1]),fadj[1],fadj[2],
occupation[2],
mission[2]
),
{ his = "her" , her = "her" , he = "she" , she = "she" }
)
local story = string.format("%s %s And together, they must %s",man,woman,title)
local output = str.wrapt(story,68)
write(handler.INFO { handler.INFO , "" })
write(handler.INFO { handler.INFO , " -- The Quick and Dirty B-Movie Plot Generator --" })
write(handler.INFO { handler.INFO , "" })
write(handler.INFO { handler.INFO , "Only the finest script writers were hired to come up with thie plot:" })
write(handler.INFO { handler.INFO , "" })
for _,line in ipairs(output) do
write(handler.INFO { handler.INFO , line })
end
write(handler.INFO { handler.INFO , "" })
local port do
if config.interface.port == 70 then
port = ""
else
port = string.format(":%d",config.interface.port)
end
end
local selector = string.format("Movie:%u",seed)
local url = string.format("gopher://%s%s/1%s",config.interface.hostname,port,selector)
write(handler.INFO { handler.INFO , "Link for this B-Movie Plot:" })
write(handler.DIR { handler.DIR , url , selector })
return bytes
end
-- ***********************************************************************
if _VERSION >= "Lua 5.2" then
return _ENV
end