Lua, Plots, offer of code

G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

For a while I've been working on a plot/quest system. I've been trying
to keep it general enough to make it simple to write new plots into the
system. Though, as many of you know, this cannot be done in a vaccume.
It needs a game to go along with it. So, I've been developing a small
test framework in the style of a MUD - basically command-line driven.
Well, I've reached the point where I think the plot system is well
enough developed where it could be ported to a real game engine.

I've been debating on whether or not to release this, or to develop it
into something, or to just write it off as a successful test, and wait
for inspiration to do more with it. So I decided to release it.

It's located at:
http://arakon.m6.net/uploads/luaplotdemo.zip

It's 100% lua 4.0 based. To run it on windows, type "lua mud_main.lua"

There's a small readme explaining which files includes plots, and other
parts of interest. It does not explain the architecture much. I can
help with that though.

So, basically, if anyone wants to use it in there project, they are
welcome to. It's under LGPL. I'll probably make more releases in the
future as I expierment more with options and sample plots.

I'd be willing to help integrate it into an engine, or atleast the
parts that people are interested in. I'll need someone to help get me
up to speed on the engine layout of course, to see if anything
additional is needed.

Oh yes, a lot of the framework was inspired by Joseph Hewitt's
Gearhead. I was trying to capture a lot of the intents of the plot
files, but expand on the options and make it simple to understand by
looking at it.. :)
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

Yeah, the test framework ain't too solid..

just type "show", or "help show", and it tells you need two parameters:

show note knight


Also, as a note, I start the character out with a bad reputation just
so that some of the different dialog can be seen. You can change it
manually in the world.lua file. range between -100 to +100 (I think).
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

Gr.
I rushed that release too quickly. There's other plots that are
disabled. It's in the mud_plots.lua file. The three "dofile" all
work, I just had two disabled for testing purposes.

Also, with the relic plot, "show" or "sell" it to people.

Maybe I'll make another cleaner/tested (release) tomorrow.
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

In article <1120144005.902689.97480@g44g2000cwa.googlegroups.com>, "Arakon" <fabian.lemke@gmail.com> wrote:
>For a while I've been working on a plot/quest system. I've been trying
>to keep it general enough to make it simple to write new plots into the
>system. Though, as many of you know, this cannot be done in a vaccume.
> It needs a game to go along with it. So, I've been developing a small
>test framework in the style of a MUD - basically command-line driven.
>Well, I've reached the point where I think the plot system is well
>enough developed where it could be ported to a real game engine.

Bug report #1 :^)

-----------------
Command>
show note
---------------
error: bad argument #1 to `strlower' (string expected, got nil)
stack traceback:
1: function `strlower' [C]
2: method `run' at line 229 [file `command_list.lua']
3: method `runCmd' at line 62 [file `cmdline.lua']
4: main of file `mud_main.lua' at line 72


Alan
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

I was poking around this today at school. An overview of the process it
goes through would be great, if you have the time! (Referencing your
files). Also the basic idea behind it with a simple example :D

Is the rumour stuff important with, regards to the random plot / quest
generation, or is it just an extra?

Thanks for sharing the code - it's interesting to look through.
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

Balaam wrote:
> I was poking around this today at school. An overview of the process it
> goes through would be great, if you have the time! (Referencing your
> files). Also the basic idea behind it with a simple example :D

As far as plots go, there's a primary plot class that picks "parts" to
put together. The parts themselves have to have certain requirements
in order to be added. If they don't meet those requirements, they
cannot be added.

The current samples has several "stand alone" plots (Herb plot, relic,
etc). The others are part of plot-chains, where multiple parts are
designed to work together.

After completing a plot, it bumps up a level variable, which allows
some of the more complex plots to take place, and stops after 2 or 3.
This is just a standin behavior for the test-framework.


How the plot parts themselves work:
-----
First, selecting plots that can be made. I'm heavilly using lua's
flexability here. The parse_support.lua file contains a lot of the
logic for this. Basically it allows easy filtering of lists based on
the criteria strings. This allows for things such as
FindCharacterAsset (plot_helpers.lua). This basically wraps
getRandomFromCriteria, which is from the parse_support.lua file. It
takes a table of characters, and a criteria string, and returns a
random one that is valid.

The criteria string is the interesting part. It uses the string lib to
break it up into sections, and recurse those tables to see if it
matches:
char1 = { name="test", badguy=1, job=3 }

a list of these types of structures can be filtered like this:
getRandomFromCriteria("job=3 goodguy=1", charlist)

This format is heavilly used across the system to make finding things
easy. This includes the rumors system - basically allowing different
characters with specific attributes to respond different, just by
specifying a string of requirements.

The filtering also allows for "helpers", which is bascially a table
that contains functions it can use. I've been playing around with
making the functions parameterized as well, such as:
getRandomFromCriteria("job=3 FuncLikesChar(self,other)>1", charlist)

That isn't fully implemented yet.

It also has the ability to change variables with the same
specifications, though this isn't used as much.

Anyways, the more complex plots (the ones that are not
"kind=standalone") use this to set arbitrary variables of the plot, and
and exclude or require (through the filtering) additional parts. It
kind of cascades into a complete plot.


AI, Assets, Memes
-----
The actual characters all interact through Events. The events are sent
down a line of classes that process them. The initial class is in
cmd_character.lua, which basically represents the game object.
Attached to that is a CCmdNPC (cmdnpc.lua). The NPC class handles all
of the event responses by delegating them to Generators (aka event
responders), which create Memes (aka actions). The Meme (action) with
the highest priority executes that turn - this allows overriding
behavior without knowing what behavior is being done, and without
permanently replacing behavior.

The Plots interact with characters by attaching an AssetGenerator,
which basically forwards any events to the plot that is in control.

So basically, after a character (Knight) becomes an asset for a plot,
that plot has the option to override behavior and make the character
say things, and respond differently then typical.

Plots recieve the events just like the generators do, but the format is
a bit expanded:
onSomeoneEntered = function(self, plotgen, char, event)
self = the actual plot part/class. This would be the same as "this"
for C++.
plotgen = the master plot that this "part" is part of - remember some
plots consist of lots of parts.
char = the character having the event take place
event = all of the event information. Event.targChar often includes
the character showing an item, or attacking, or whatever.
command_list.lua is where the events are started.

Example:
-------------
Easiest example is the lostpouch.lua file. I could make some easier
plots, and maybe should.. but kind of jumped into the larger stuff.

CPlotComponent from plot_helpers is the primary object to first look
at. the function MakeNewPlot makes one of these, and calls the init
for it. At this point, it basically looks through all of the parts and
starts adding random ones who's requirements are met. This allows for
plots made up of several "components" (introduction, final-encounter,
plus filler and modifications). I may change this in the future though
to make it more explicit/intuitive.

First, it needs to be selected. All of the criteria need to be met
from the main Plot:
criteria = "where.style=NIL kind=NIL level=0" ,
basically, where must not be defined, the kind of plot must not be
defined, and the player's level must be 0. This basically just assures
it is the first plot part to be added, since multple ones can be. I'm
still considering simplifying this..

after that, the
changeValues = "kind=selfcontained" ,
is executed, basically setting hte plot's kind to "selfcontained" -
this stops anything from adding anything more to it (everything will
require a kind of NIL, or "obvious", or something)

The onChanged function is then executed, which selects a place to
center action around - a location that's marked as a town, finds a
character asset who lost it (who's a goodguy), and then creates the
actual missing pouch. It then sets an internal phase variable, just
used for tracking the plot, and then sets it to being done (so no more
pieces need to be added).

The rest of the functions are for responding to events, and usually
start off with an "if" statement to see what character is having the
event take place - remember, a plot can have multiple assets, but all
of the messages go to a one function per event type.

When everything is done, plotgen:EndPlot is called, which finally ends
the plot. The primary plot component (plotgen, which is a
CPlotComponent from plot_helpers) takes care of clean up - it removes
any Asset generators from character assets, and will even remove
character assets from the world if they are owned by the plot. It does
NOT currently remove things from inventory. That's something a game
would need, this is not that developed.


> Is the rumour stuff important with, regards to the random plot / quest
> generation, or is it just an extra?

The rumor stuff is just additional. I was experimenting with creating
an "atmosphere" that felt more alive. It surely isn't required though
- a lot of the plot core could be used without it.

Same goes for the Meme/Generator/Asset stuff. It could be removed, but
some kind of alternative layer would need to be added (or would
probably already exist). Most of the power is in the methods for
finding characters, locations, and parts via the "criteria".

> Thanks for sharing the code - it's interesting to look through.

Good to hear. I'd really like to see the system in a functional game,
but really don't have the time to make one from scratch. A roguelike
seems like the best place for it, since I've enjoyed them so much, and
they concentrate on gameplay more then anything.
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.development (More info?)

Wow thanks for taking the trouble to go into detail :D
I'm sure it will be a great not only to me but to lots of other people
too!