summaryrefslogtreecommitdiff
path: root/src/map/magic-interpreter.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/magic-interpreter.hpp')
-rw-r--r--src/map/magic-interpreter.hpp321
1 files changed, 183 insertions, 138 deletions
diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp
index 432245d..f233f37 100644
--- a/src/map/magic-interpreter.hpp
+++ b/src/map/magic-interpreter.hpp
@@ -3,27 +3,29 @@
#include "magic-interpreter.t.hpp"
+#include <cassert>
+
#include "magic.hpp"
#include "map.hpp"
#include "script.hpp"
#include "skill.t.hpp"
-struct expr;
-struct val;
-struct location;
-struct area;
-struct spell;
+struct expr_t;
+struct val_t;
+struct location_t;
+struct area_t;
+struct spell_t;
struct invocation;
-typedef struct location
+struct location_t
{
- int m;
+ map_local *m;
int x, y;
-} location_t;
+};
-typedef struct area
+struct area_t
{
- union a
+ union au
{
location_t a_loc;
struct
@@ -37,29 +39,39 @@ typedef struct area
location_t loc;
int width, height;
} a_rect;
- struct area *a_union[2];
+ dumb_ptr<area_t> a_union[2];
+
+ au() { memset(this, '\0', sizeof(*this)); }
+ ~au() = default;
+ au(const au&) = default;
+ au& operator = (const au&) = default;
} a;
int size;
AREA ty;
-} area_t;
+};
-typedef struct val
+struct val_t
{
union v
{
int v_int;
DIR v_dir;
- char *v_string;
- // can't be dumb_ptr<block_list>
- block_list *v_entity; /* Used ONLY during operation/function invocation; otherwise we use v_int */
- area_t *v_area;
+ dumb_string v_string;
+ /* Used ONLY during operation/function invocation; otherwise we use v_int */
+ dumb_ptr<block_list> v_entity;
+ dumb_ptr<area_t> v_area;
location_t v_location;
- // can't be dumb_ptr<invocation>
- invocation *v_invocation; /* Used ONLY during operation/function invocation; otherwise we use v_int */
- struct spell *v_spell;
+ /* Used ONLY during operation/function invocation; otherwise we use v_int */
+ dumb_ptr<invocation> v_invocation;
+ dumb_ptr<spell_t> v_spell;
+
+ v() { memset(this, '\0', sizeof(*this)); }
+ ~v() = default;
+ v(const v&) = default;
+ v& operator = (const v&) = default;
} v;
TYPE ty;
-} val_t;
+};
/* ----------- */
/* Expressions */
@@ -67,12 +79,12 @@ typedef struct val
#define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */
-typedef struct e_location
+struct e_location_t
{
- struct expr *m, *x, *y;
-} e_location_t;
+ dumb_ptr<expr_t> m, x, y;
+};
-typedef struct e_area
+struct e_area_t
{
union a0
{
@@ -80,21 +92,26 @@ typedef struct e_area
struct
{
e_location_t loc;
- struct expr *width, *depth, *dir;
+ dumb_ptr<expr_t> width, depth, dir;
} a_bar;
struct
{
e_location_t loc;
- struct expr *width, *height;
+ dumb_ptr<expr_t> width, height;
} a_rect;
- struct e_area *a_union[2];
+ dumb_ptr<e_area_t> a_union[2];
+
+ a0() { memset(this, '\0', sizeof(*this)); }
+ ~a0() = default;
+ a0(const a0&) = default;
+ a0& operator = (const a0&) = default;
} a;
AREA ty;
-} e_area_t;
+};
-typedef struct expr
+struct expr_t
{
- union e
+ union eu
{
val_t e_val;
e_location_t e_location;
@@ -103,153 +120,165 @@ typedef struct expr
{
int id, line_nr, column;
int args_nr;
- struct expr *args[MAX_ARGS];
+ dumb_ptr<expr_t> args[MAX_ARGS];
} e_funapp;
int e_id;
struct
{
- struct expr *expr;
+ dumb_ptr<expr_t> expr;
int id;
} e_field;
+
+ eu() { memset(this, '\0', sizeof(*this)); }
+ ~eu() = default;
+ eu(const eu&) = default;
+ eu& operator = (const eu&) = default;
} e;
EXPR ty;
-} expr_t;
+};
-typedef struct effect
+struct effect_t
{
- struct effect *next;
+ dumb_ptr<effect_t> next;
union e0
{
struct
{
int id;
- expr_t *expr;
+ dumb_ptr<expr_t> expr;
} e_assign;
struct
{
int id;
- expr_t *area;
- struct effect *body;
+ dumb_ptr<expr_t> area;
+ dumb_ptr<effect_t> body;
FOREACH_FILTER filter;
} e_foreach;
struct
{
int id;
- expr_t *start, *stop;
- struct effect *body;
+ dumb_ptr<expr_t> start, stop;
+ dumb_ptr<effect_t> body;
} e_for;
struct
{
- expr_t *cond;
- struct effect *true_branch, *false_branch;
+ dumb_ptr<expr_t> cond;
+ dumb_ptr<effect_t> true_branch, false_branch;
} e_if;
- expr_t *e_sleep; /* sleep time */
- const ScriptCode *e_script;
+ dumb_ptr<expr_t> e_sleep; /* sleep time */
+ dumb_ptr<const ScriptBuffer> e_script;
struct
{
int id;
int args_nr;
int line_nr, column;
- expr_t *args[MAX_ARGS];
+ dumb_ptr<expr_t> args[MAX_ARGS];
} e_op;
struct
{
- int args_nr, *formals;
- expr_t **actuals;
- struct effect *body;
+ std::vector<int> *formalv;
+ dumb_ptr<std::vector<dumb_ptr<expr_t>>> actualvp;
+ dumb_ptr<effect_t> body;
} e_call;
+
+ e0() { memset(this, '\0', sizeof(*this)); }
+ ~e0() = default;
+ e0(const e0&) = default;
+ e0& operator = (const e0&) = default;
} e;
EFFECT ty;
-} effect_t;
+};
/* ---------- */
/* Components */
/* ---------- */
-typedef struct component
+struct component_t
{
- struct component *next;
+ dumb_ptr<component_t> next;
int item_id;
int count;
-} component_t;
+};
-typedef struct effect_set
+struct effect_set_t
{
- effect_t *effect, *at_trigger, *at_end;
-} effect_set_t;
+ dumb_ptr<effect_t> effect, at_trigger, at_end;
+};
-typedef struct spellguard
+struct spellguard_t
{
- struct spellguard *next;
- union s
+ dumb_ptr<spellguard_t> next;
+ union su
{
- expr_t *s_condition;
- expr_t *s_mana;
- expr_t *s_casttime;
- component_t *s_components;
- component_t *s_catalysts;
- struct spellguard *s_alt; /* either `next' or `s.s_alt' */
+ dumb_ptr<expr_t> s_condition;
+ dumb_ptr<expr_t> s_mana;
+ dumb_ptr<expr_t> s_casttime;
+ dumb_ptr<component_t> s_components;
+ dumb_ptr<component_t> s_catalysts;
+ dumb_ptr<spellguard_t> s_alt; /* either `next' or `s.s_alt' */
effect_set_t s_effect;
+ su() { memset(this, '\0', sizeof(*this)); }
+ ~su() = default;
+ su(const su&) = default;
+ su& operator = (const su&) = default;
} s;
SPELLGUARD ty;
-} spellguard_t;
+};
/* ------ */
/* Spells */
/* ------ */
-typedef struct letdef
+struct letdef_t
{
int id;
- expr_t *expr;
-} letdef_t;
+ dumb_ptr<expr_t> expr;
+};
-typedef struct spell
+struct spell_t
{
- char *name;
- char *invocation;
- int index; // Relative location in the definitions file
+ std::string name;
+ std::string invocation;
+ int index_; // Relative location in the definitions file
SPELL_FLAG flags;
int arg;
SPELLARG spellarg_ty;
- int letdefs_nr;
- letdef_t *letdefs;
+ std::vector<letdef_t> letdefv;
- spellguard_t *spellguard;
-} spell_t;
+ dumb_ptr<spellguard_t> spellguard;
+};
/* ------- */
/* Anchors */
/* ------- */
-typedef struct teleport_anchor
+struct teleport_anchor_t
{
- char *name;
- char *invocation;
- expr_t *location;
-} teleport_anchor_t;
+ std::string name;
+ std::string invocation;
+ dumb_ptr<expr_t> location;
+};
/* ------------------- */
/* The big config blob */
/* ------------------- */
-typedef struct
+struct magic_conf_t
{
- int vars_nr;
- const char **var_name;
- val_t *vars; /* Initial assignments, if any, or NULL */
-
- int obscure_chance;
- int min_casttime;
+ struct mcvar
+ {
+ std::string name;
+ val_t val;
+ };
+ // This should probably be done by a dedicated "intern pool" class
+ std::vector<mcvar> varv;
- int spells_nr;
- spell_t **spells;
+ std::map<std::string, dumb_ptr<spell_t>> spells_by_name, spells_by_invocation;
- int anchors_nr; /* NEGATIVE iff we have sorted the anchors */
- teleport_anchor_t **anchors;
-} magic_conf_t;
+ std::map<std::string, dumb_ptr<teleport_anchor_t>> anchors_by_name, anchors_by_invocation;
+};
/* Execution environment */
@@ -266,57 +295,72 @@ typedef struct
struct magic_config;
-typedef struct env
+struct env_t
{
magic_conf_t *base_env;
- val_t *vars;
-} env_t;
+ std::unique_ptr<val_t[]> varu;
+
+ val_t& VAR(size_t i)
+ {
+ assert (varu);
+ if (varu[i].ty == TYPE::UNDEF)
+ return base_env->varv[i].val;
+ else
+ return varu[i];
+ }
+
+};
#define MAX_STACK_SIZE 32
-typedef struct cont_activation_record
+struct cont_activation_record_t
{
- effect_t *return_location;
- union c
+ dumb_ptr<effect_t> return_location;
+ union cu
{
struct
{
int id;
TYPE ty;
- effect_t *body;
- int entities_nr;
- int *entities;
+ dumb_ptr<effect_t> body;
+ dumb_ptr<std::vector<int>> entities_vp;
int index;
} c_foreach;
struct
{
int id;
- effect_t *body;
+ dumb_ptr<effect_t> body;
int current;
int stop;
} c_for;
struct
{
- int args_nr, *formals;
- val_t *old_actuals;
+ int args_nr;
+ int *formalap;
+ dumb_ptr<val_t[]> old_actualpa;
} c_proc;
+
+ cu() { memset(this, '\0', sizeof(*this)); }
+ ~cu() {}
+ cu(const cu&) = delete;
+ cu& operator = (const cu&) = delete;
} c;
CONT_STACK ty;
-} cont_activation_record_t;
+};
-typedef struct status_change_ref
+struct status_change_ref_t
{
StatusChange sc_type;
int bl_id;
-} status_change_ref_t;
+};
struct invocation : block_list
{
dumb_ptr<invocation> next_invocation; /* used for spells directly associated with a caster: they form a singly-linked list */
INVOCATION_FLAG flags;
- env_t *env;
- spell_t *spell;
+ dumb_ptr<env_t> env;
+ dumb_ptr<spell_t> spell;
int caster; /* this is the person who originally invoked the spell */
int subject; /* when this person dies, the spell dies with it */
@@ -326,13 +370,12 @@ struct invocation : block_list
cont_activation_record_t stack[MAX_STACK_SIZE];
int script_pos; /* Script position; if nonzero, resume the script we were running. */
- effect_t *current_effect;
- effect_t *trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */
- effect_t *end_effect; /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */
+ dumb_ptr<effect_t> current_effect;
+ dumb_ptr<effect_t> trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */
+ dumb_ptr<effect_t> end_effect; /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */
/* Status change references: for status change updates, keep track of whom we updated where */
- int status_change_refs_nr;
- status_change_ref_t *status_change_refs;
+ std::vector<status_change_ref_t> status_change_refv;
};
@@ -345,25 +388,23 @@ extern env_t magic_default_env; /* Fake default environment */
/**
* Adds a component selection to a component holder (which may initially be NULL)
*/
-void magic_add_component(component_t ** component_holder, int id, int count);
+void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count);
-teleport_anchor_t *magic_find_anchor(char *name);
+dumb_ptr<teleport_anchor_t> magic_find_anchor(const std::string& name);
-/**
- * The parameter `param' must have been dynamically allocated; ownership is transferred to the resultant env_t.
- */
-env_t *spell_create_env(magic_conf_t *conf, spell_t *spell,
- dumb_ptr<map_session_data> caster, int spellpower, char *param);
+dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell,
+ dumb_ptr<map_session_data> caster, int spellpower, const_string param);
-void magic_free_env(env_t *env);
+void magic_free_env(dumb_ptr<env_t> env);
/**
* near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components)
*/
-effect_set_t *spell_trigger(spell_t *spell, dumb_ptr<map_session_data> caster,
- env_t *env, int *near_miss);
+effect_set_t *spell_trigger(dumb_ptr<spell_t> spell,
+ dumb_ptr<map_session_data> caster,
+ dumb_ptr<env_t> env, int *near_miss);
-dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, env_t *env);
+dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, dumb_ptr<env_t> env);
/**
* Bind a spell to a subject (this is a no-op for `local' spells).
@@ -378,22 +419,26 @@ int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invoca
*/
dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> source);
-spell_t *magic_find_spell(char *invocation);
+dumb_ptr<spell_t> magic_find_spell(const std::string& invocation);
/* The following is used only by the parser: */
-typedef struct args_rec
+struct args_rec_t
{
- int args_nr;
- expr_t **args;
-} args_rec_t;
+ dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp;
+};
-typedef struct
+struct proc_t
{
- char *name;
- int args_nr;
- int *args;
- effect_t *body;
-} proc_t;
+ std::string name;
+ std::vector<int> argv;
+ dumb_ptr<effect_t> body;
+
+ proc_t()
+ : name()
+ , argv()
+ , body()
+ {}
+};
// must be called after itemdb initialisation
int magic_init(const char *);