Game engine from previous project of mine.
This commit is contained in:
parent
41693b0f5f
commit
278b48b68d
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,413 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>Vlak ve 4:20</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* {
|
||||
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
||||
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
||||
box-sizing: border-box; /* Opera/IE 8+ */
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: darkgrey;
|
||||
font-family: "Lucida console", monospaced;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#all {
|
||||
width: 642px;
|
||||
height: 480px;
|
||||
margin: auto;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#all:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#texty {
|
||||
float: left;
|
||||
width: 400px;
|
||||
padding: 5px;
|
||||
border: 1px solid black;
|
||||
overflow: auto;
|
||||
height: 480px;
|
||||
}
|
||||
|
||||
#texty .error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#menu {
|
||||
float: left;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
#menu a {
|
||||
display: block;
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
<script src="fengari-web.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="all">
|
||||
<div id="texty">
|
||||
<p>Demo hry vlak ve 4:20</p>
|
||||
<p>Pokud se hra nespustí, dejte vědět Severákovi a napište mu, jaký prohlížeč používáte.</p>
|
||||
</div>
|
||||
<div id="menu">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var el_texty = document.getElementById("texty");
|
||||
var el_menu = document.getElementById("menu");
|
||||
|
||||
function ui_p(txt)
|
||||
{
|
||||
|
||||
el_texty.innerHTML += ("<p>" + txt + "</p>");
|
||||
el_texty.scrollTop = el_texty.scrollHeight;
|
||||
}
|
||||
|
||||
function ui_cls(txt)
|
||||
{
|
||||
|
||||
el_texty.innerHTML = "";
|
||||
}
|
||||
|
||||
function ui_add_menu(code, txt)
|
||||
{
|
||||
|
||||
el_menu.innerHTML += ("<a href=\"#\" data-code=\""+code+"\">" + txt + "</p>");
|
||||
}
|
||||
|
||||
function ui_cls_menu()
|
||||
{
|
||||
|
||||
el_menu.innerHTML = "";
|
||||
}
|
||||
|
||||
function ui_errormsg(txt)
|
||||
{
|
||||
|
||||
el_texty.innerHTML += ("<p class=\"error\">" + txt.replace("\n", "<br/>") + "</p>");
|
||||
el_texty.scrollTop = el_texty.scrollHeight;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script type="application/lua">
|
||||
local js = require "js"
|
||||
local window = js.global
|
||||
|
||||
gamefile = "syrecky.lua"
|
||||
|
||||
-- Hagen game engine
|
||||
-- (c) Severák 2019-2021
|
||||
|
||||
-- kód nedoporučuju nikomu číst, protože zárodek vzniknul během jednoho odpoledne
|
||||
|
||||
-- inspirace
|
||||
-- - hra Gateway od Legend entrertaiment
|
||||
-- - textovky od Petra Kaina
|
||||
-- - textovkový engine INSTEAD
|
||||
|
||||
-- globals
|
||||
|
||||
paramsNo = 0
|
||||
params = {}
|
||||
currVerb = nil
|
||||
|
||||
verb_ord = {}
|
||||
room_ord = {}
|
||||
item_ord = {}
|
||||
|
||||
menu2codes = {}
|
||||
|
||||
issued_command = {}
|
||||
|
||||
-- API
|
||||
|
||||
function verb(def)
|
||||
def.is_verb = true
|
||||
def.params = def.params or {}
|
||||
verb_ord[#verb_ord+1] = def
|
||||
return def
|
||||
end
|
||||
|
||||
function room(def)
|
||||
def.is_room = true
|
||||
room_ord[#room_ord+1] = def
|
||||
return def
|
||||
end
|
||||
|
||||
function item(def)
|
||||
def.is_item = true
|
||||
item_ord[#item_ord+1] = def
|
||||
return def
|
||||
end
|
||||
|
||||
function cls()
|
||||
window:ui_cls()
|
||||
end
|
||||
|
||||
local function split_lines(str)
|
||||
local result = {}
|
||||
for line in str:gmatch '[^\n]+' do
|
||||
table.insert(result, line)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function p(par)
|
||||
par = par or ""
|
||||
for line in par:gmatch '[^\n]+' do
|
||||
window:ui_p(line)
|
||||
end
|
||||
end
|
||||
|
||||
function here()
|
||||
return game[game.me.w]
|
||||
end
|
||||
|
||||
function move(what, where)
|
||||
game[what].w = where
|
||||
end
|
||||
|
||||
function walk(where, nocls)
|
||||
assert(game[where], "room " .. where .. " does not exist")
|
||||
move("me", where)
|
||||
if not nocls then
|
||||
cls()
|
||||
end
|
||||
p(game[where].n)
|
||||
p(game[where].d)
|
||||
for i,item in ipairs(item_ord) do
|
||||
if item.d and item.w==here().ref then
|
||||
p(item.d)
|
||||
end
|
||||
end
|
||||
show_verbs()
|
||||
end
|
||||
|
||||
function has(what)
|
||||
return game[what].w=="me"
|
||||
end
|
||||
|
||||
function location_of(what)
|
||||
return game[what].w
|
||||
end
|
||||
|
||||
function is_here(what)
|
||||
return game[what].w==game.me.w
|
||||
end
|
||||
|
||||
|
||||
-- end of API
|
||||
|
||||
-- TODO - checkovat všechny parametry
|
||||
function _has_subj_of(verb)
|
||||
local parCode = verb.params[#params+1]
|
||||
for i,item in ipairs(item_ord) do
|
||||
if item[parCode] and (verb.global_reach or item.w==here().ref or item.w=="me") then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function show_verbs()
|
||||
paramsNo = 0
|
||||
currVerb = ""
|
||||
params = {}
|
||||
local here = game[game.me.w]
|
||||
window:ui_cls_menu();
|
||||
menu2codes={}
|
||||
for i,verb in ipairs(verb_ord) do
|
||||
if verb.always or here[verb.ref] or _has_subj_of(verb) then
|
||||
local idx=#menu2codes+1
|
||||
window:ui_add_menu(idx, verb.n);
|
||||
menu2codes[idx] = verb.ref
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function show_items()
|
||||
local verb = game[currVerb]
|
||||
local parCode = verb.params[#params+1]
|
||||
-- print("parCode="..parCode)
|
||||
window:ui_cls_menu();
|
||||
menu2codes={}
|
||||
for i,item in ipairs(item_ord) do
|
||||
if item[parCode] and (verb.global_reach or item.w==here().ref or item.w=="me") then
|
||||
local idx=#menu2codes+1
|
||||
window:ui_add_menu(idx, item.n);
|
||||
menu2codes[idx] = item.ref
|
||||
end
|
||||
end
|
||||
if #menu2codes=="0" then
|
||||
show_verbs() -- situace kdy není možné zobrazit další krok v menu
|
||||
-- TODO - vyřešit nějak líp
|
||||
end
|
||||
end
|
||||
|
||||
function process_param(param)
|
||||
if paramsNo == 0 then
|
||||
currVerb = param
|
||||
paramsNo = #game[currVerb].params
|
||||
else
|
||||
params[#params+1]=param
|
||||
end
|
||||
|
||||
-- debug:
|
||||
|
||||
--[[
|
||||
print("param="..param)
|
||||
print("params="..table.concat(params," "))
|
||||
print("currVerb="..currVerb)
|
||||
print("paramsNo="..paramsNo)
|
||||
print("#params="..#params)
|
||||
print "---"
|
||||
]]
|
||||
|
||||
if #params==paramsNo then
|
||||
p ""
|
||||
p("> " .. table.concat(issued_command, " "))
|
||||
issued_command = {}
|
||||
game[currVerb].act(table.unpack(params))
|
||||
if game.round then
|
||||
game.round()
|
||||
end
|
||||
show_verbs()
|
||||
else
|
||||
show_items()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- game defaults
|
||||
|
||||
game = {
|
||||
title = "Emty game",
|
||||
me = item{
|
||||
w="intro"
|
||||
},
|
||||
intro = room{
|
||||
n="void",
|
||||
d="YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.",
|
||||
ref = "intro"
|
||||
},
|
||||
void = room{
|
||||
n="void",
|
||||
d="YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.",
|
||||
ref = "void"
|
||||
},
|
||||
vars = {}
|
||||
}
|
||||
|
||||
-- utils
|
||||
|
||||
function read_config(filename)
|
||||
filename = filename or ''
|
||||
assert(type(filename) == 'string')
|
||||
local ans,u,k,v,temp = {}, '_'
|
||||
local f = io.open(filename)
|
||||
if f then
|
||||
f:close()
|
||||
for line in io.lines(filename) do
|
||||
temp = line:match('^%[(.+)%]$')
|
||||
if temp ~= nil and u ~= temp then u = temp end
|
||||
k,v = line:match('^([^=]+)=(.+)$')
|
||||
if u ~= nil then
|
||||
ans[u] = ans[u] or {}
|
||||
if k ~= nil then
|
||||
ans[u][k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
return ans
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
-- GUI
|
||||
|
||||
-- loads game
|
||||
load_game, err = loadfile(gamefile, "t", setmetatable(game, {__index=_G}))
|
||||
|
||||
if err then
|
||||
window:ui_errormsg(err)
|
||||
-- os.exit(1)
|
||||
end
|
||||
|
||||
load_game()
|
||||
|
||||
local refcnt = 0
|
||||
-- add refs
|
||||
for ref,obj in pairs(game) do
|
||||
if type(obj)=='table' and (obj.is_verb or obj.is_room or obj.is_item) then
|
||||
obj.ref = ref
|
||||
refcnt = refcnt + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- stupid cyber arm glitching again!
|
||||
for i,obj in ipairs(verb_ord) do
|
||||
print("verb " .. obj.ref)
|
||||
end
|
||||
for i,obj in ipairs(room_ord) do
|
||||
print("room " .. obj.ref)
|
||||
end
|
||||
for i,obj in ipairs(item_ord) do
|
||||
print("item " .. obj.ref)
|
||||
end
|
||||
|
||||
print("refcnt = " .. refcnt)
|
||||
print("#verb_ord = " .. #verb_ord)
|
||||
print("#room_ord = " .. #room_ord)
|
||||
print("#item_ord = " .. #item_ord)
|
||||
print("#sum_ord = " .. #verb_ord + #room_ord + #item_ord)
|
||||
|
||||
local ok, err = pcall(walk, "intro")
|
||||
if not ok then
|
||||
window:ui_errormsg(err)
|
||||
end
|
||||
|
||||
window.document:getElementById("menu"):addEventListener("click", function(eL, ev)
|
||||
local target = ev.target;
|
||||
local code = target:getAttribute("data-code")
|
||||
|
||||
local text = target.innerText
|
||||
local i = tonumber(code)
|
||||
|
||||
issued_command[#issued_command+1] = text
|
||||
|
||||
local ok, err = pcall(process_param, menu2codes[i])
|
||||
if not ok then
|
||||
window:ui_errormsg(err)
|
||||
show_verbs()
|
||||
end
|
||||
|
||||
ev:stopPropagation();
|
||||
ev:preventDefault();
|
||||
end)
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,284 @@
|
|||
-- Syrečky pro Hagen engine
|
||||
-- (c) Severák 2015 - 2019
|
||||
|
||||
-- / port z ALAN verze
|
||||
|
||||
title = "Syrečky 2019"
|
||||
|
||||
-- utils
|
||||
|
||||
local function randomp(texty)
|
||||
return function()
|
||||
p(texty[math.random(1, #texty)])
|
||||
end
|
||||
end
|
||||
|
||||
-- slovesa
|
||||
|
||||
cont=verb{
|
||||
n="pokračovat",
|
||||
act = function()
|
||||
walk(here().cont)
|
||||
end
|
||||
}
|
||||
|
||||
sever = verb{
|
||||
n = "sever",
|
||||
act = function()
|
||||
walk(here().sever)
|
||||
end
|
||||
}
|
||||
|
||||
jih = verb{
|
||||
n = "jih",
|
||||
act = function()
|
||||
walk(here().jih)
|
||||
end
|
||||
}
|
||||
|
||||
desc = verb{
|
||||
n ="prozkoumej",
|
||||
params = {"desc"},
|
||||
act = function(what)
|
||||
p("Zkoumáš " .. game[what].n .. ":")
|
||||
local description = game[what].desc
|
||||
if type(description)=='string' then
|
||||
p(description)
|
||||
elseif type(description)=='function' then
|
||||
description()
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
open = verb{
|
||||
n ="otevři",
|
||||
params = {"open"},
|
||||
act = function(what)
|
||||
local description = game[what].open
|
||||
if type(description)=='string' then
|
||||
p(description)
|
||||
elseif type(description)=='function' then
|
||||
description()
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
give = verb{
|
||||
n = "dej",
|
||||
params = {"darovatelne", "komu"},
|
||||
act = function(co, komu)
|
||||
-- tohle je trošku hack
|
||||
if komu=="naokno" then
|
||||
p "Na okno raději nic dávat nebudu. Mohli by to unést holubi."
|
||||
return
|
||||
end
|
||||
|
||||
if co=="syrecky" then
|
||||
p "Dáváš otci syrečky."
|
||||
p "Otec: dík, synku."
|
||||
p "Dokázal jsi to! Dal jsi otci syrečky."
|
||||
p "Game over!"
|
||||
move("syrecky", "otec")
|
||||
else
|
||||
p("Dáváš otci " .. game[co].n .. ".")
|
||||
p "Otec: No co já s tím? Tohle nechci."
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
eat = verb{
|
||||
n = "sněz",
|
||||
params = {"jedle"},
|
||||
act = function(co)
|
||||
if co=="bageta" then
|
||||
p "OK. Dám si bagetu."
|
||||
p "* žvejk, žvejk, žvejk, žvejk"
|
||||
p "Jo... Byla docela dobrá."
|
||||
move("bageta", "void")
|
||||
elseif co=="syrecky" then
|
||||
p "Syrečky nesním:"
|
||||
p "a) neuvěřitelně páchnou"
|
||||
p "b) s plynovou maskou se dost blbě jí"
|
||||
p "c) kdybych je snědl, nešlo by tuhle hru vyhrát"
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- předměty a lokace
|
||||
|
||||
-- OBÝVÁK
|
||||
|
||||
obyvak = room{
|
||||
n="Obývák",
|
||||
d="Normalní panelakový obývak. Na sever od něj je kuchyně.",
|
||||
sever="kuchyn"
|
||||
}
|
||||
|
||||
maska = item{
|
||||
n="plynovou masku",
|
||||
d="Plynova maska z dob ruske okupace.",
|
||||
desc="Stará protiplynová maska, patrně ruské výroby. Nechápu co dělala v pohovce.",
|
||||
w="pohovka",
|
||||
darovatelne = true
|
||||
}
|
||||
|
||||
pohovka = item{
|
||||
n="pohovku",
|
||||
d="Stará prašivá pohovka sotva drží. Pamatuje snad i druhou světovou.",
|
||||
desc = function()
|
||||
if maska.w=='pohovka' then
|
||||
p "Z pohovky čouhá něco divného, zkusím to vytáhnout."
|
||||
p "Wow! Je to plynová maska!"
|
||||
move("maska", "me")
|
||||
else
|
||||
p "V pohovce je už jenom prach."
|
||||
end
|
||||
end,
|
||||
w="obyvak"
|
||||
}
|
||||
|
||||
otec = item{
|
||||
n="otce",
|
||||
d="Na pohovce se valí otec a kouka se na telku.",
|
||||
desc="Tvůj fotr. Fešák.",
|
||||
w="obyvak"
|
||||
}
|
||||
|
||||
-- tohle je trošku hack - neumíme moc dobře skloňovat, tak máme pro otce speciální objekt na obdarovávání
|
||||
otci = item{
|
||||
n = "otci",
|
||||
komu = true,
|
||||
w = "obyvak"
|
||||
}
|
||||
|
||||
televize = item{
|
||||
n = "televizi",
|
||||
desc = randomp{
|
||||
"V telce běží zápas pražských S.",
|
||||
"Fanoušci v televizi hážou dělobuchy.",
|
||||
"Právě běží reklama.",
|
||||
"V televizi je Horst Fuchs: A pokud zavoláte do deseti minut, dostanete ke každému noži koťátko zdarma."
|
||||
},
|
||||
w = "obyvak"
|
||||
}
|
||||
|
||||
|
||||
-- KUCHYNĚ
|
||||
|
||||
kuchyn = room{
|
||||
n="Kuchyň",
|
||||
d="Umakartová kuchyň z doby vrcholného komunismu. Na jih od ní je obyvák.",
|
||||
jih="obyvak"
|
||||
}
|
||||
|
||||
syrecky = item{
|
||||
n = "syrečky",
|
||||
desc = "Strašně smradlavé syrečky. Smrdí tak mocně, že je to cítit i přes igelit.",
|
||||
w = "lednice",
|
||||
darovatelne = true,
|
||||
jedle = true
|
||||
}
|
||||
|
||||
bageta = item{
|
||||
n = "bagetu",
|
||||
d = "Na kuchyňské lince leží bageta.",
|
||||
desc = function()
|
||||
p "Typická bageta z benzínky. Kupodivu ani není prošlá."
|
||||
if game.bageta.w~="me" then
|
||||
p "Beru ji sebou."
|
||||
move("bageta", "me")
|
||||
end
|
||||
end,
|
||||
darovatelne = true,
|
||||
jedle = true,
|
||||
w = "kuchyn"
|
||||
}
|
||||
|
||||
|
||||
|
||||
lednice = item{
|
||||
n="lednici",
|
||||
d="Spořádaně tu vrní obstarožní lednice",
|
||||
desc = "Obstarožní lednička značky CALEX. Hotová hrozba pro životní prostředí.",
|
||||
open = function()
|
||||
p "Otevíráš ledničku. Dveře vržou."
|
||||
if syrecky.w=="lednice" then
|
||||
if maska.w=="me" then
|
||||
p "Syrečky strašne smrdí, bereš si na pomoc plynovou masku."
|
||||
move("syrecky", "me")
|
||||
p "Vypadáš přitom jak stalker ze stejnojmené počitačové hry, ale podařilo se ti vzít syrečky."
|
||||
else
|
||||
p "Strašlivý smrad syrečků tě donutil ledničku zase zavřít!"
|
||||
end
|
||||
else
|
||||
p "V lednici však už je jen \"Příšera, která žila v lednici vedle majonézy a za zelným salátem\". A ta tě nezajímá."
|
||||
end
|
||||
end,
|
||||
w="kuchyn"
|
||||
}
|
||||
|
||||
vyhled = item{
|
||||
n = "výhled",
|
||||
d = "A je tu krásný výhled na Jihozápadní město",
|
||||
w="kuchyn",
|
||||
desc = randomp{
|
||||
"Paneláky dnes vypadají patřičně depresivně.",
|
||||
"Před barákem zrovna někomu kradou auto.",
|
||||
"Před barákem zrovna policajti rozdávají pokuty.",
|
||||
"Děti si hrajou na hřišti.",
|
||||
"Důchodkyně pomlouvají tu dnešní mládež.",
|
||||
"Vietnamc si šel zakouřit před večerku.",
|
||||
"Gopnici ve vchodu tančí na hardbass.",
|
||||
"Nikde nikdo s rouškou - není to tím, že je rok 1995?"
|
||||
},
|
||||
open="Okno raději otvírat nebudu, mohl by se sem dostat smog."
|
||||
}
|
||||
|
||||
naokno = item{
|
||||
n = "na okno",
|
||||
komu = true,
|
||||
w = "kuchyn"
|
||||
}
|
||||
|
||||
-- META
|
||||
|
||||
local sledovani = randomp{
|
||||
"Otec se napil piva.",
|
||||
"GOOOOOOOOOOOOOOOL!!!!\nSparťani v televizi právě skórovali. Řve celé sídliště.",
|
||||
"Otec se raduje, Sparta vede 1:0 .",
|
||||
"Otec začína být nervózní.\nOtec: Tak kde jsou sakra ty syrečky?!"
|
||||
}
|
||||
|
||||
local zrani = randomp{
|
||||
"Otec spokojeně mlaská při žraní syrečků.",
|
||||
"Otec: To je dobrota, to je dobrota.",
|
||||
"Otec: Mňam, mňam...",
|
||||
"Otec slastně mlaská při žraní syrečků.",
|
||||
"Otec se olizuje až za ušima."
|
||||
}
|
||||
|
||||
function round()
|
||||
if here().ref=="obyvak" then
|
||||
if syrecky.w=="otec" then
|
||||
zrani()
|
||||
else
|
||||
sledovani()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
intro = room{
|
||||
d=[[SYREČKY 2019 - technologické demo
|
||||
|
||||
(verze z 17.8.2019)
|
||||
(technicky aktualizováno v lednu 2021)
|
||||
|
||||
Tvým cílem je donést otci syrečky z kuchyně.
|
||||
|
||||
Hru navrhnul Petr Kain v roce 2010, potom sloužila jako česká obdoba Cloak of Darkness.]],
|
||||
cont="obyvak",
|
||||
auto_command = "pokračovat"
|
||||
}
|
Loading…
Reference in New Issue