Heres a REVISED "patch-by-hand" for DG scripts. Tested and all, works wonders! Your filenames will most likely differ. Plus I use some patches you might not, like George's buffer patch. Another note is that GET_TRIG_DEPTH is NO LONGER updated here, it is useless IMHO, and using BREAK would (excuse the unintended pun) break it anyways, because if used from nested loops, since it searches for "done" rather than "end", it doesn't search for "end"s inbetween. NOTE: this changes the overall design of my original WHILE patch to end with DONE and not END, so unpatch your previous version (if you have one) before patching this one. This allows for CORRECTLY breaking from WHILE/SWITCH from within nested IFs, the way C works. I.e, you can do: while (%x% < 5) eval x (%x% + 1) if (%x% == 2) if (yet something else again) break end end done The way these changes work in scripts: wait <statement> ... done switch <statement> case <instance> ... break case <instance> case <instance> ... break default ... done "break" can be used to drop out the current "while" or "switch", or end the script if it isn't in a while/switch. With while loops, if more than 30 loops occur, it will automatically cause a WAIT for 1 second. If more than 100 loops occur since the script has started executing /from the beginning/ (if it WAITs it will still remember how many loops), it will mudlog-warn the MUD. - Chris Jacobson PS. No credit needed, just dont go telling your builders you wrote this yerself :-P ------------------------- *-> in scripts.h: * add the macro: #define GET_TRIG_LOOPS(t) ((t)->loops) * in trig_data, add: int loops; * in cmdlist_element, add: struct cmdlist_element *original; *-> scriptengine.c * add /* * scans for a case/default instance * returns the line containg the correct case instance, or the last * line of the trigger if not found. */ struct cmdlist_element *find_case(TrigData *trig, struct cmdlist_element *cl, void *go, ScriptData *sc, int type, char *cond) { struct cmdlist_element *c; char *p, *buf; if (!(cl->next)) return cl; for (c = cl->next; c->next; c = c->next) { for (p = c->cmd; *p && isspace(*p); p++); if (!strn_cmp("while ", p, 6) || !strn_cmp("switch", p, 6)) c = find_done(c); else if (!strn_cmp("case ", p, 5)) { buf = get_buffer(MAX_STRING_LENGTH); sprintf(buf, "(%s) == (%s)", cond, p + 5); if (process_if(buf, go, sc, trig, type)) { release_buffer(buf); return c; } release_buffer(buf); } else if (!strn_cmp("default", p, 7)) return c; else if (!strn_cmp("done", p, 3)) return c; } return c; } /* * scans for end of while/switch-blocks. * returns the line containg 'end', or the last * line of the trigger if not found. */ struct cmdlist_element *find_done(struct cmdlist_element *cl) { struct cmdlist_element *c; char *p; if (!(cl->next)) return cl; for (c = cl->next; c->next; c = c->next) { for (p = c->cmd; *p && isspace(*p); p++); if (!strn_cmp("while ", p, 6) || !strn_cmp("switch ", p, 7)) c = find_done(c); else if (!strn_cmp("done", p, 3)) return c; } return c; } *> script_driver: * in the beginning, add these variables: struct cmdlist_element *temp; UInt32 loops = 0; * replace: if (mode == TRIG_NEW) GET_TRIG_DEPTH(trig) = 1; * with: if (mode == TRIG_NEW) { GET_TRIG_LOOPS(trig) = 0; GET_TRIG_DEPTH(trig) = 1; } * replace "} else if (!strn_cmp("end", p, 3)) { ... }" with: } else if (!strn_cmp("while ", p, 6)) { temp = find_done(cl); if (process_if(p + 6, go, sc, trig, type)) { temp->original = cl; } else { cl = temp; loops = 0; } } else if (!strn_cmp("switch ", p, 7)) { cl = find_case(trig, cl, go, sc, type, p + 7); } else if (!strn_cmp("end", p, 3)) { GET_TRIG_DEPTH(trig)--; } else if (!strn_cmp("done", p, 4)) { if (cl->original && process_if(cl->original->cmd + 6, go, sc, trig, type)) { cl = cl->original; loops++; GET_TRIG_LOOPS(trig)++; if (loops == 30) { process_wait(go, trig, type, "wait 1", cl); depth--; release_buffer(cmd); return ret_val; } if (GET_TRIG_LOOPS(trig) == 100) { mudlogf(NRM, LVL_BUILDER, TRUE, "SCRIPTERR: Trigger VNum %d has looped 100 times!!!", GET_TRIG_VNUM(trig)); } } } else if (!strn_cmp("break", p, 5)) { cl = find_done(cl); } else if (!strn_cmp("case", p, 4)) { ; // Do nothing, this allows multiple cases to a single instance } +------------------------------------------------------------+ | Ensure that you have read the CircleMUD Mailing List FAQ: | | http://democracy.queensu.ca/~fletcher/Circle/list-faq.html | +------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/15/00 PST