Commit edd23735 authored by Alexander Yakovlev's avatar Alexander Yakovlev

Switched to Salet because I want procgen

parent 07a644d8
node_modules
build
dist
dist.zip
\ No newline at end of file
watchify = require('watchify')
browserify = require('browserify')
browserSync = require('browser-sync')
gulp = require('gulp')
source = require('vinyl-source-stream')
gutil = require('gulp-util')
coffeify = require('coffeeify')
coffee = require("gulp-coffee")
sass = require('gulp-sass')
uglify = require('gulp-uglify')
buffer = require('vinyl-buffer')
zip = require('gulp-zip')
concat = require('gulp-concat')
fs = require 'fs'
CSON = require 'cson'
glob = require 'glob'
reload = browserSync.reload
html = (target) ->
return () ->
return gulp.src(['html/index.html']).pipe(gulp.dest(target))
# Images
img = (target) ->
return () ->
return gulp.src(['img/*.png', 'img/*.jpeg', 'img/*.jpg']).pipe(gulp.dest(target))
# Audio assets
audio = (target) ->
return () ->
return gulp.src(['audio/*.mp3']).pipe(gulp.dest(target))
gulp.task('html', html('./build'))
gulp.task('img', img('./build/img'))
gulp.task('audio', audio('./build/audio'))
gulp.task('sass', () ->
gulp.src('sass/main.scss')
.pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError))
.pipe(gulp.dest('./build/css'))
)
bundler = watchify(browserify({
entries: ["./build/game/main.coffee"]
debug: true
transform: [coffeify]
}))
bundle = () ->
return bundler.bundle()
.on('error', gutil.log.bind(gutil, 'Browserify Error'))
.pipe(source('bundle.js'))
.pipe(gulp.dest('./build/game'))
gulp.task('concatCoffee', () ->
files = glob.sync('game/procgen/ru/*.cson')
spec = {}
for file in files
data = CSON.parseCSONFile(file)
if not data.groups?
data.groups = []
if data.phrases?
data.groups.push({
tags: [],
phrases: data.phrases
})
data.phrases = undefined
key = file.substr(0, file.lastIndexOf('.')) || file
key = key.replace('game/procgen/ru/', '')
spec[key] = data
json = JSON.stringify(spec) + '\n'
fs.writeFileSync("./build/game/procgen/ru.json", json)
return gulp.src([
'./game/begin.coffee',
'./game/story.coffee',
]).pipe(concat('./main.coffee')).pipe(gulp.dest('./build/game'))
)
gulp.task('coffee', ['concatCoffee'], bundle)
bundler.on('update', bundle)
bundler.on('log', gutil.log)
gulp.task('build', ['html', 'img', 'sass', 'coffee', 'audio'])
gulp.task('serve', ['build'], () ->
browserSync({
server: {
baseDir: 'build'
}
})
sassListener = () ->
reload('./build/css/main.css')
gulp.watch(['./html/*.html'], ['html'])
gulp.watch(['./sass/*.scss'], ['sass'])
gulp.watch(['./img/*.png', './img/*.jpeg', './img/*.jpg'], ['img'])
gulp.watch(['./game/*.coffee'], ['coffee']);
gulp.watch(['./build/css/main.css'], sassListener)
gulp.watch(
['./build/game/bundle.js', './build/img/*', './build/index.html'],
browserSync.reload)
)
gulp.task('html-dist', html('./dist'))
gulp.task('img-dist', img('./dist/img'))
gulp.task('audio-dist', audio('./dist/audio'))
gulp.task('legal-dist', () ->
return gulp.src(['LICENSE.txt'])
.pipe(gulp.dest("./dist"))
)
gulp.task('sass-dist', () ->
return gulp.src('./sass/main.scss')
.pipe(sass({outputStyle: 'compressed'}))
.pipe(gulp.dest('./dist/css'))
)
distBundler = browserify({
debug: false,
entries: ['./build/game/main.coffee'],
transform: ['coffeeify']
})
gulp.task('coffee-dist', ['concatCoffee'], () ->
return distBundler.bundle()
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(uglify())
.on('error', gutil.log)
.pipe(gulp.dest('./dist/game'))
)
gulp.task('dist', [
'html-dist',
'img-dist',
'sass-dist',
'coffee-dist',
'audio-dist',
'legal-dist'
])
gulp.task('zip', ['dist'], () ->
return gulp.src('dist/**')
.pipe(zip('dist.zip'))
.pipe(gulp.dest('.'))
)
Copyright (c) 2016 Alexander Yakovlev, https://oreolek.ru/
Raconteur is copyright (c) 2015 Bruno Dias, released under the similar license terms.
Undum is copyright (c) 2009-2015 Ian Millington, released under the similar license terms.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
......@@ -2,4 +2,4 @@
The theme is **One room**.
I'm building it for [INSTEAD](http://instead.syscall.ru/download/) interpreter.
I'm building it on [Salet](https://salet.su/) engine.
require 'format'
format.filter = function(text)
for _, s in ipairs {"%*%*", "%_%_"} do
text = text:gsub(s .. "([^%s][^<>]-[^%s][%*%_]?)" .. s, txtb("%1"));
end;
for _, s in ipairs {"%*"} do
text = text:gsub(s .. "([^%s_][^<>_]-[^%s_])" .. s, txtem("%1"));
end;
for _, s in ipairs {"%_"} do
text = text:gsub(s .. "([^%s_][^<>_]-[^%s_])" .. s, txtu("%1"));
end;
for _, s in ipairs {"%-"} do
text = text:gsub(s .. " ([^%s_][^<>_]-[^%s_]) " .. s, txtst("%1"));
end;
return text;
end
dialogue = require('../../lib/dialogue.coffee')
phrase = require('../../lib/phrase.coffee')
#oneOf = require('../../lib/oneOf.coffee')
require('salet')
ImprovEngine = require('improv')
Improv = {}
salet.game_id = "0ee0825d-0c71-4a08-bfe5-730e575df26d"
salet.game_version = "1.0"
$.getJSON('game/procgen/ru.json', (data) ->
Improv = new ImprovEngine(data, {
filters: [
ImprovEngine.filters.mismatchFilter()
]
reincorporate: false
})
$.holdReady( false )
)
$(document).ready(() ->
window.addEventListener('popstate', (event) ->
salet.goBack()
)
$("#night").on("click", () ->
if (window.night)
styles = {
"-webkit-filter": ""
"filter": ""
"background-color": ""
}
$("body").css(styles)
$("#night").removeClass("active")
window.night = false
else
styles = {
"-webkit-filter": "invert(1)hue-rotate(180deg)"
"filter": "invert(1)hue-rotate(180deg)"
"background-color": "#000"
}
$("body").css(styles)
$("#night").addClass("active")
window.night = true
)
salet.beginGame()
)
###
Element helpers. There is no real need to build monsters like a().id("hello")
because you won't use them as is. It does not make sense in context, the
author has Markdown and all utilities to *forget* about the markup.
###
way_to = (content, ref) ->
return "<a href='#{ref}' class='way'>#{content}</a>"
textlink = (content, ref) ->
return "<a href='./_writer_#{ref}' class='once'>#{content}</a>"
actlink = (content, ref) ->
return "<a href='./#{ref}' class='once'>#{content}</a>"
class ImprovModel
constructor: () ->
@tags = []
phrases: [
"обнимает гитару."
"насвистывает свою партию в песне про солнце."
"задумчиво смотрит в одну точку."
]
phrases: [
"выжимает из машины всё, что дозволено правилами."
]
phrases: [
"напевает про себя весёлый мотивчик."
]
room "start",
choices: ["vstart"]
before: (from) ->
if (!from)
"""
-- Только что звонили из клуба.
Приехали какие-то чмыри из администрации, нас отменяют.
"""
dsc: () -> """
### В машине
Рядом с вами сидит [Лёша](alexey) и #{Improv.gen("alexey")}
На переднем сидении [Марго](margo) #{Improv.gen("margo")}
Вы сидите на заднем сидении, за спиной водителя. [Катя](katie) #{Improv.gen("katie")}
Вы положили в карман дверцы [мобильный телефон.](phone)
За [окном машины](./_writer_window) проносится трасса.
*Вы сжимаете родную флейту. Только бы не опоздать.*
"""
writers:
window:
"Россия."
room "phone",
choices: "#call",
dsc: "Вы открываете список контактов. Кому бы позвонить…"
room "director",
tags: ["call"],
choices: "#director"
optionText: "Директор музыкального клуба"
dsc: """
— Алло? Анна Борисовна?
"""
dialogue "Попрощаться", "director", "call", """
— Спасибо. Созвонимся.
"""
# Virtual room to go around limitations
room "vstart",
tags: ["call"]
optionText: (from) ->
switch from
when "start" then "Осмотреться ещё раз"
when "phone" then "Отложить телефон"
else "Передумать"
enter: () ->
salet.goTo("start")
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Salet showcase</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href='https://fonts.googleapis.com/css?family=PT+Sans:400,400italic|PT+Sans+Caption' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="page">
<div class="fixed container">
<div id="tools_wrapper" class="row">
<div class='ways'>
<small class="text-muted" id="ways_hint">Click these links to explore other rooms</small>
<ul class="nav nav-pills" id="ways">
</ul>
</div>
<div class="buttons">
<button id="night" class="btn btn-outline-primary">Night mode</button>
<button id="erase" class="btn btn-outline-danger">Restart</button>
</div>
</div> <!-- End of div.tools_wrapper -->
</div>
<div class="container">
<div class="row">
<div id="title" class="title">
<div class="label">
<h1>One room</h1>
<h2>A Ludum Dare effort</h2>
<noscript>
<p class="noscript_message">This game requires Javascript.</p>
</noscript>
</div>
</div>
</div>
<div id="content_wrapper" class="row">
<div id="content" class="content">
<noscript>You need to turn on Javascript to play this game.</noscript>
</div>
<a name="end_of_content"></a>
</div>
<div id="legal" class="row">
<div id="footleft">
<p>
<a href="https://git.oreolek.ru/oreolek/ludumdare37" target="_blank">See the source code</a>
</p>
</div>
<div id="footright">
</div>
</div>
</div>
</div> <!-- End of div.page -->
<!-- CDN JS Libraries -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.min.js" integrity="sha384-QXBtGc4014gU26HdCwzgy8TVO+FHSSE4+EvPPiSTpdE9w0KyJy1ocfiIbBl1HLq7" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="game/bundle.js"></script>
</body>
</html>
require 'para'
require 'dash'
require 'quotes'
require 'dbg'
require 'emphasis';
game.forcedsc = false;
game._action = nil;
game.actions = {}
rndstr = function(strings)
return strings[rnd(stead.table.maxn(strings))];
end
File deleted
These functions are not used by Salet core.
But you can `require` them in your game and use thusly.
###
A dialogue shortcut.
Usage:
dialogue "Point out a thing in her purse (mildly)", "start", "mild", """
Point out a thing in her purse (mildly)
""", "character.mild = true"
###
dialogue = (title, startTag, endTag, text, effect) ->
retval = room("dialogue_"+Object.keys(salet.rooms).length, {
optionText: title
dsc: text
clear: false # backlog is useful in dialogues
choices: "#"+endTag
})
if typeof(startTag) == "string"
retval.tags = [startTag]
else if typeof(startTag) == "object"
retval.tags = startTag
if effect?
retval.before = (character, system) ->
eval(effect)
return retval
module.exports = dialogue
###
oneOf.js
Copyright (c) 2015 Bruno Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
###
###
Undularity Tools
Those functions are not a core part of Undularity, but provide some
general functionality that relates to adaptive text generation.
This is provided partly as a helper to less technical users, and as
a convenience for authors.
###
# Monkey patching
###
Shuffles an array. It can use Undum's random number generator implementation,
so it expects a System.rnd object to be passed into it. If one isn't
supplied, it will use Math.Random instead.
This is an implementation of the Fischer-Yates (Knuth) shuffle.
Returns the shuffled array.
###
Array.prototype.shuffle = () ->
# slice() clones the array. Object members are copied by reference, beware.
newArr = this.slice()
m = newArr.length
while (m)
i = Math.floor(salet.rnd.randf() * m--)
t = newArr[m]
newArr[m] = newArr[i]
newArr[i] = t
return newArr
###
oneOf()
Takes an array and returns an object with several methods. Each method
returns an iterator which iterates over the array in a specific way:
inOrder()
Returns the array items in order.
cycling()
Returns the array items in order, cycling back to the first item when
it runs out.
stopping()
Returns the array items in order, then repeats the last item when it
runs out.
randomly()
Returns the array items at random. Takes a system object, for consistent
randomness. Will never return the same item twice in a row.
trulyAtRandom()
Returns the array items purely at random. Takes a system object, for
consistent randomness.
inRandomOrder()
Returns the array items in a random order. Takes a system object, for
consistent randomness.
###
###
Takes a function and gives it a toString() property that calls itself and
returns its value, allowing for ambiguous use of the closure object
as a text snippet.
Returns the modified function.
###
stringish = (callback) ->
callback.toString = () ->
return '' + this.call()
return callback
oneOf = (ary...) ->
if ary.length == 0
throw new Error(
"tried to create a oneOf iterator with a 0-length array");
return {
inOrder: () ->
i = 0
return stringish(() ->
if i >= ary.length
return null
return ary[i++]
)
cycling: () ->
i = 0
return stringish(() ->
if (i >= ary.length)
i = 0
return ary[i++]
)
stopping: () ->
i = 0
return stringish(() ->
if (i >= ary.length)
i = ary.length - 1
return ary[i++]
)
randomly: (system) ->
last = null
if (ary.length<2)
throw new Error("attempted to make randomly() iterator with a 1-length array")
return stringish( () ->
i = null
offset = null
if not last?
i = Math.floor(salet.rnd.randf() * ary.length)
else
###
Let offset be a random number between 1 and the length of the
array, minus one. We jump offset items ahead on the array,
wrapping around to the beginning. This gives us a random item
other than the one we just chose.
###
offset = Math.floor(salet.rnd.randf() * (ary.length -1) + 1)
i = (last + offset) % ary.length
last = i
return ary[i]
)
trulyAtRandom: (system) ->
return stringish(() ->
return ary[Math.floor(salet.rnd.randf() * ary.length)];
)
inRandomOrder: (system) ->
shuffled = ary.shuffle(system)
i = 0
return stringish(() ->
if (i >= ary.length)
i = 0
return shuffled[i++]
)
}
Array.prototype.oneOf = () ->
oneOf.apply(null, this)
String.prototype.oneOf = () ->
return this
module.exports = oneOf