Re: [LONG] Spell parser toy language Mobprogs/DGScripts/?

From: Thomas Arp (t_arp@stofanet.dk)
Date: 09/05/02


From: "Artovil" <artovil@ARCANEREALMS.ORG>
> I am running a CircleMUD 3.0 bpl20 with DG Scripts and DG Events.
> We are currently in the process of redoing spells from the ground
> and up, except for a few stock spell routines.  Early along I had
> the idea that we should use some kind of toy language for spells
> since I have implemented the rudimentary foundation of a spell editor.
> Has anybody done anything similar to this?  If so, do you have any
> code I can take a look at, or perhaps even reuse?
>
A quick search of the circleftp site shows no code. However, a (just as)
quick look in the archives, show 5 posts concerning 'spell editor' in the
last year. One of these (written by Del Caminturn) at

http://post.queensu.ca/cgi-bin/listserv/wa?A2=ind0108&L=circle&P=R12731

describe some of the things you have to consider.

> What I had in mind was this:
> In the spell editor I have a menu with effects, for instance.
> Select a type (affect/damage/...)
> Write a simple script in an editor that is parsed on cast; for an affect:
> ...
> duration = (%actor.skill% / 6)
> modifier = 1
> bitvector = AFF_CURSE
> accum_duration = true
> accum_affect = true
> ...

This would be slow. Having to run through a script on each cast,
before determining output, affections etc. would slow your mud
down considerably.

> Each set of af[x] would have its own script, or possibly the engine
> could handle arrays as well, in which case I could have all the
> affect code for the spell in one script?  The more simple things
> as location and such are set through regular OLC menus, it's just
> the calculations and such that I want to parse through a script
> engine, such as DG Scripts.
>
Another suggestion:
Have some things set _outside_ the script; Manacost, target, whether
or not it is accumulative / - in duration, the bitvector+modifier if
any.

There's nothing wrong with having %actor.level% or any other variable
in a line to determine duration/output. I imagine something like this:

Spell Editor [123]
A) Spell name: curse
B) Mana      : 40 / 20 / 2
C) To Caster : You curse $N.
D) To Victim : $n casts a curse on you.
E) To room   : $N curses $n.
F) Targets   : TAR_NOT_SELF TAR_CHAR_ROOM
G) Bits      : AGGRESSIVE IS_SPELL
H) Savetype  : SAVING_SPELL
I) Affects   :
  1) -1 to APPLY_STR, sets AFF_CURSE
  2) -1 to APPLY_TOHIT, sets AFF_CURSE
J) Script    :
if %victim.level%>29
  %send% %caster% %victim.name% resists your curse.
  return -1
else
  eval duration (%caster.level% / 6) + 1
  return %duration%
end
Q) Quit

> Perhaps I am totally wrong here and this won't work at all, or it
> will be really slow and consume lots of processing power and memory,
> that's why I am asking you guys what to do.  If you don't want to
> take this on the list feel free to email me directly instead.
>
It _will_ be slower. It _will_ eat your memory. If you make it right,
it will also be easier to work with, and to expand without recompiling.

> I thought that if I for instance reused the DG Scripts I could
> easily make summon spells and such inside the editor, and it
> would be similar with the affects, and just apply the affect
> through the scripting engine instead of having everything
> hard-coded in magic.c.
>

<snip>
> If the system is a little bit slower than the normal magic system I
> will live with that, since magic will be quite rare, and rather [...]
>
It might show as quite slow in comparison, since compiled C source
is faster than interpreted scripting language.

This can be minimized by having as few things as possible set in the
script; in my example above, only the duration is set by the script.
Since the return value already is passed from script_driver() this
is a way to see if the spell should run: [mailer-semi-code]

#define SPELL_TRIGGER 4
int spell_driver(char_data *caster, *victim, some_struct *spell) {

struct trig_data *t = SPELL_TRIGGER(spell);

[checks for mana/saves/target validity]

sprintf(buf, "%s", SPELL_NAME(spell));
add_var(&GET_TRIG_VARS(t), "spellname", buf, 0);
ADD_UID_VAR(buf, t, caster, "caster", 0);
ADD_UID_VAR(buf, t, victim, "victim", 0);

if ((duration = script_driver(spell, t, SPELL_TRIGGER, TRIG_NEW))>=0)
  [send strings/apply applies/affect affects]
}

And build in some support for spell triggers in script_driver;
As it is, it handles mobs/rooms/objs. If more entities are
allowed, it must be expanded.

Welcor

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   | Newbie List:  http://groups.yahoo.com/group/circle-newbies/   |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 06/25/03 PDT