00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <time.h>
00042 #include <sys/types.h>
00043 #include <ctype.h>
00044 #include "merc.h"
00045 #include "tables.h"
00046 #include "lookup.h"
00047
00048 extern int flag_lookup (const char *word, const struct flag_type *flag_table);
00049
00050
00051
00052
00053
00054 #define CHK_RAND (0)
00055 #define CHK_MOBHERE (1)
00056 #define CHK_OBJHERE (2)
00057 #define CHK_MOBEXISTS (3)
00058 #define CHK_OBJEXISTS (4)
00059 #define CHK_PEOPLE (5)
00060 #define CHK_PLAYERS (6)
00061 #define CHK_MOBS (7)
00062 #define CHK_CLONES (8)
00063 #define CHK_ORDER (9)
00064 #define CHK_HOUR (10)
00065 #define CHK_ISPC (11)
00066 #define CHK_ISNPC (12)
00067 #define CHK_ISGOOD (13)
00068 #define CHK_ISEVIL (14)
00069 #define CHK_ISNEUTRAL (15)
00070 #define CHK_ISIMMORT (16)
00071 #define CHK_ISCHARM (17)
00072 #define CHK_ISFOLLOW (18)
00073 #define CHK_ISACTIVE (19)
00074 #define CHK_ISDELAY (20)
00075 #define CHK_ISVISIBLE (21)
00076 #define CHK_HASTARGET (22)
00077 #define CHK_ISTARGET (23)
00078 #define CHK_EXISTS (24)
00079 #define CHK_AFFECTED (25)
00080 #define CHK_ACT (26)
00081 #define CHK_OFF (27)
00082 #define CHK_IMM (28)
00083 #define CHK_CARRIES (29)
00084 #define CHK_WEARS (30)
00085 #define CHK_HAS (31)
00086 #define CHK_USES (32)
00087 #define CHK_NAME (33)
00088 #define CHK_POS (34)
00089 #define CHK_CLAN (35)
00090 #define CHK_RACE (36)
00091 #define CHK_CLASS (37)
00092 #define CHK_OBJTYPE (38)
00093 #define CHK_VNUM (39)
00094 #define CHK_HPCNT (40)
00095 #define CHK_ROOM (41)
00096 #define CHK_SEX (42)
00097 #define CHK_LEVEL (43)
00098 #define CHK_ALIGN (44)
00099 #define CHK_MONEY (45)
00100 #define CHK_OBJVAL0 (46)
00101 #define CHK_OBJVAL1 (47)
00102 #define CHK_OBJVAL2 (48)
00103 #define CHK_OBJVAL3 (49)
00104 #define CHK_OBJVAL4 (50)
00105 #define CHK_GRPSIZE (51)
00106
00107
00108
00109
00110 #define EVAL_EQ 0
00111 #define EVAL_GE 1
00112 #define EVAL_LE 2
00113 #define EVAL_GT 3
00114 #define EVAL_LT 4
00115 #define EVAL_NE 5
00116
00117
00118
00119
00120 const char *fn_keyword[] = {
00121 "rand",
00122 "mobhere",
00123 "objhere",
00124
00125
00126 "mobexists",
00127 "objexists",
00128
00129 "people",
00130 "players",
00131 "mobs",
00132 "clones",
00133 "order",
00134 "hour",
00135
00136
00137 "ispc",
00138 "isnpc",
00139 "isgood",
00140 "isevil",
00141 "isneutral",
00142 "isimmort",
00143 "ischarm",
00144 "isfollow",
00145 "isactive",
00146 "isdelay",
00147 "isvisible",
00148 "hastarget",
00149 "istarget",
00150 "exists",
00151
00152 "affected",
00153 "act",
00154 "off",
00155 "imm",
00156 "carries",
00157
00158 "wears",
00159
00160 "has",
00161 "uses",
00162 "name",
00163 "pos",
00164 "clan",
00165 "race",
00166 "class",
00167 "objtype",
00168
00169 "vnum",
00170 "hpcnt",
00171 "room",
00172 "sex",
00173 "level",
00174 "align",
00175 "money",
00176 "objval0",
00177 "objval1",
00178 "objval2",
00179 "objval3",
00180 "objval4",
00181 "grpsize",
00182
00183 "\n"
00184 };
00185
00186 const char *fn_evals[] = {
00187 "==",
00188 ">=",
00189 "<=",
00190 ">",
00191 "<",
00192 "!=",
00193 "\n"
00194 };
00195
00196
00197
00198
00199 int keyword_lookup (const char **table, char *keyword)
00200 {
00201 register int i;
00202 for (i = 0; table[i][0] != '\n'; i++)
00203 if (!str_cmp (table[i], keyword))
00204 return (i);
00205 return -1;
00206 }
00207
00208
00209
00210
00211
00212 int num_eval (int lval, int oper, int rval)
00213 {
00214 switch (oper)
00215 {
00216 case EVAL_EQ:
00217 return (lval == rval);
00218 case EVAL_GE:
00219 return (lval >= rval);
00220 case EVAL_LE:
00221 return (lval <= rval);
00222 case EVAL_NE:
00223 return (lval != rval);
00224 case EVAL_GT:
00225 return (lval > rval);
00226 case EVAL_LT:
00227 return (lval < rval);
00228 default:
00229 bug ("num_eval: invalid oper", 0);
00230 return 0;
00231 }
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 CHAR_DATA *get_random_char (CHAR_DATA * mob)
00244 {
00245 CHAR_DATA *vch, *victim = NULL;
00246 int now = 0, highest = 0;
00247 for (vch = mob->in_room->people; vch; vch = vch->next_in_room)
00248 {
00249 if (mob != vch && !IS_NPC (vch)
00250 && can_see (mob, vch) && (now = number_percent ()) > highest)
00251 {
00252 victim = vch;
00253 highest = now;
00254 }
00255 }
00256 return victim;
00257 }
00258
00259
00260
00261
00262
00263 int count_people_room (CHAR_DATA * mob, int iFlag)
00264 {
00265 CHAR_DATA *vch;
00266 int count;
00267 for (count = 0, vch = mob->in_room->people; vch; vch = vch->next_in_room)
00268 if (mob != vch && (iFlag == 0 || (iFlag == 1 && !IS_NPC (vch))
00269 || (iFlag == 2 && IS_NPC (vch))
00270 || (iFlag == 3 && IS_NPC (mob) && IS_NPC (vch)
00271 && mob->pIndexData->vnum ==
00272 vch->pIndexData->vnum) || (iFlag == 4
00273 &&
00274 is_same_group (mob,
00275 vch)))
00276 && can_see (mob, vch))
00277 count++;
00278 return (count);
00279 }
00280
00281
00282
00283
00284
00285
00286 int get_order (CHAR_DATA * ch)
00287 {
00288 CHAR_DATA *vch;
00289 int i;
00290
00291 if (!IS_NPC (ch))
00292 return 0;
00293 for (i = 0, vch = ch->in_room->people; vch; vch = vch->next_in_room)
00294 {
00295 if (vch == ch)
00296 return i;
00297 if (IS_NPC (vch) && vch->pIndexData->vnum == ch->pIndexData->vnum)
00298 i++;
00299 }
00300 return 0;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 bool has_item (CHAR_DATA * ch, int vnum, sh_int item_type, bool fWear)
00310 {
00311 OBJ_DATA *obj;
00312 for (obj = ch->carrying; obj; obj = obj->next_content)
00313 if ((vnum < 0 || obj->pIndexData->vnum == vnum)
00314 && (item_type < 0 || obj->pIndexData->item_type == item_type)
00315 && (!fWear || obj->wear_loc != WEAR_NONE))
00316 return TRUE;
00317 return FALSE;
00318 }
00319
00320
00321
00322
00323 bool get_mob_vnum_room (CHAR_DATA * ch, int vnum)
00324 {
00325 CHAR_DATA *mob;
00326 for (mob = ch->in_room->people; mob; mob = mob->next_in_room)
00327 if (IS_NPC (mob) && mob->pIndexData->vnum == vnum)
00328 return TRUE;
00329 return FALSE;
00330 }
00331
00332
00333
00334
00335 bool get_obj_vnum_room (CHAR_DATA * ch, int vnum)
00336 {
00337 OBJ_DATA *obj;
00338 for (obj = ch->in_room->contents; obj; obj = obj->next_content)
00339 if (obj->pIndexData->vnum == vnum)
00340 return TRUE;
00341 return FALSE;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 int cmd_eval (int vnum, char *line, int check,
00357 CHAR_DATA * mob, CHAR_DATA * ch,
00358 const void *arg1, const void *arg2, CHAR_DATA * rch)
00359 {
00360 CHAR_DATA *lval_char = mob;
00361 CHAR_DATA *vch = (CHAR_DATA *) arg2;
00362 OBJ_DATA *obj1 = (OBJ_DATA *) arg1;
00363 OBJ_DATA *obj2 = (OBJ_DATA *) arg2;
00364 OBJ_DATA *lval_obj = NULL;
00365
00366 char *original, buf[MAX_INPUT_LENGTH], code;
00367 int lval = 0, oper = 0, rval = -1;
00368
00369 original = line;
00370 line = one_argument (line, buf);
00371 if (buf[0] == '\0' || mob == NULL)
00372 return FALSE;
00373
00374
00375
00376
00377 if (mob->mprog_target == NULL)
00378 mob->mprog_target = ch;
00379
00380 switch (check)
00381 {
00382
00383
00384
00385 case CHK_RAND:
00386 return (atoi (buf) < number_percent ());
00387 case CHK_MOBHERE:
00388 if (is_number (buf))
00389 return (get_mob_vnum_room (mob, atoi (buf)));
00390 else
00391 return ((bool) (get_char_room (mob, buf) != NULL));
00392 case CHK_OBJHERE:
00393 if (is_number (buf))
00394 return (get_obj_vnum_room (mob, atoi (buf)));
00395 else
00396 return ((bool) (get_obj_here (mob, buf) != NULL));
00397 case CHK_MOBEXISTS:
00398 return ((bool) (get_char_world (mob, buf) != NULL));
00399 case CHK_OBJEXISTS:
00400 return ((bool) (get_obj_world (mob, buf) != NULL));
00401
00402
00403
00404
00405 case CHK_PEOPLE:
00406 rval = count_people_room (mob, 0);
00407 break;
00408 case CHK_PLAYERS:
00409 rval = count_people_room (mob, 1);
00410 break;
00411 case CHK_MOBS:
00412 rval = count_people_room (mob, 2);
00413 break;
00414 case CHK_CLONES:
00415 rval = count_people_room (mob, 3);
00416 break;
00417 case CHK_ORDER:
00418 rval = get_order (mob);
00419 break;
00420 case CHK_HOUR:
00421 rval = time_info.hour;
00422 break;
00423 default:;
00424 }
00425
00426
00427
00428
00429 if (rval >= 0)
00430 {
00431 if ((oper = keyword_lookup (fn_evals, buf)) < 0)
00432 {
00433 sprintf (buf, "Cmd_eval: prog %d syntax error(2) '%s'",
00434 vnum, original);
00435 bug (buf, 0);
00436 return FALSE;
00437 }
00438 one_argument (line, buf);
00439 lval = rval;
00440 rval = atoi (buf);
00441 return (num_eval (lval, oper, rval));
00442 }
00443
00444
00445
00446
00447 if (buf[0] != '$' || buf[1] == '\0')
00448 {
00449 sprintf (buf, "Cmd_eval: prog %d syntax error(3) '%s'",
00450 vnum, original);
00451 bug (buf, 0);
00452 return FALSE;
00453 }
00454 else
00455 code = buf[1];
00456 switch (code)
00457 {
00458 case 'i':
00459 lval_char = mob;
00460 break;
00461 case 'n':
00462 lval_char = ch;
00463 break;
00464 case 't':
00465 lval_char = vch;
00466 break;
00467 case 'r':
00468 lval_char = rch == NULL ? get_random_char (mob) : rch;
00469 break;
00470 case 'o':
00471 lval_obj = obj1;
00472 break;
00473 case 'p':
00474 lval_obj = obj2;
00475 break;
00476 case 'q':
00477 lval_char = mob->mprog_target;
00478 break;
00479 default:
00480 sprintf (buf, "Cmd_eval: prog %d syntax error(4) '%s'",
00481 vnum, original);
00482 bug (buf, 0);
00483 return FALSE;
00484 }
00485
00486
00487
00488 if (lval_char == NULL && lval_obj == NULL)
00489 return FALSE;
00490
00491
00492
00493
00494 switch (check)
00495 {
00496 case CHK_ISPC:
00497 return (lval_char != NULL && !IS_NPC (lval_char));
00498 case CHK_ISNPC:
00499 return (lval_char != NULL && IS_NPC (lval_char));
00500 case CHK_ISGOOD:
00501 return (lval_char != NULL && IS_GOOD (lval_char));
00502 case CHK_ISEVIL:
00503 return (lval_char != NULL && IS_EVIL (lval_char));
00504 case CHK_ISNEUTRAL:
00505 return (lval_char != NULL && IS_NEUTRAL (lval_char));
00506 case CHK_ISIMMORT:
00507 return (lval_char != NULL && IS_IMMORTAL (lval_char));
00508 case CHK_ISCHARM:
00509 return (lval_char != NULL && IS_AFFECTED (lval_char, AFF_CHARM));
00510 case CHK_ISFOLLOW:
00511 return (lval_char != NULL && lval_char->master != NULL
00512 && lval_char->master->in_room == lval_char->in_room);
00513 case CHK_ISACTIVE:
00514 return (lval_char != NULL && lval_char->position > POS_SLEEPING);
00515 case CHK_ISDELAY:
00516 return (lval_char != NULL && lval_char->mprog_delay > 0);
00517 case CHK_ISVISIBLE:
00518 switch (code)
00519 {
00520 default:
00521 case 'i':
00522 case 'n':
00523 case 't':
00524 case 'r':
00525 case 'q':
00526 return (lval_char != NULL && can_see (mob, lval_char));
00527 case 'o':
00528 case 'p':
00529 return (lval_obj != NULL && can_see_obj (mob, lval_obj));
00530 }
00531 case CHK_HASTARGET:
00532 return (lval_char != NULL && lval_char->mprog_target != NULL
00533 && lval_char->in_room ==
00534 lval_char->mprog_target->in_room);
00535 case CHK_ISTARGET:
00536 return (lval_char != NULL && mob->mprog_target == lval_char);
00537 default:;
00538 }
00539
00540
00541
00542
00543 line = one_argument (line, buf);
00544 switch (check)
00545 {
00546 case CHK_AFFECTED:
00547 return (lval_char != NULL
00548 && IS_SET (lval_char->affected_by,
00549 flag_lookup (buf, affect_flags)));
00550 case CHK_ACT:
00551 return (lval_char != NULL
00552 && IS_SET (lval_char->act, flag_lookup (buf, act_flags)));
00553 case CHK_IMM:
00554 return (lval_char != NULL
00555 && IS_SET (lval_char->imm_flags,
00556 flag_lookup (buf, imm_flags)));
00557 case CHK_OFF:
00558 return (lval_char != NULL
00559 && IS_SET (lval_char->off_flags,
00560 flag_lookup (buf, off_flags)));
00561 case CHK_CARRIES:
00562 if (is_number (buf))
00563 return (lval_char != NULL
00564 && has_item (lval_char, atoi (buf), -1, FALSE));
00565 else
00566 return (lval_char != NULL
00567 && (get_obj_carry (lval_char, buf, lval_char) !=
00568 NULL));
00569 case CHK_WEARS:
00570 if (is_number (buf))
00571 return (lval_char != NULL
00572 && has_item (lval_char, atoi (buf), -1, TRUE));
00573 else
00574 return (lval_char != NULL
00575 && (get_obj_wear (lval_char, buf) != NULL));
00576 case CHK_HAS:
00577 return (lval_char != NULL
00578 && has_item (lval_char, -1, item_lookup (buf), FALSE));
00579 case CHK_USES:
00580 return (lval_char != NULL
00581 && has_item (lval_char, -1, item_lookup (buf), TRUE));
00582 case CHK_NAME:
00583 switch (code)
00584 {
00585 default:
00586 case 'i':
00587 case 'n':
00588 case 't':
00589 case 'r':
00590 case 'q':
00591 return (lval_char != NULL
00592 && is_name (buf, lval_char->name));
00593 case 'o':
00594 case 'p':
00595 return (lval_obj != NULL
00596 && is_name (buf, lval_obj->name));
00597 }
00598 case CHK_POS:
00599 return (lval_char != NULL
00600 && lval_char->position == position_lookup (buf));
00601 case CHK_CLAN:
00602 return (lval_char != NULL
00603 && lval_char->clan == clan_lookup (buf));
00604 case CHK_RACE:
00605 return (lval_char != NULL
00606 && lval_char->race == race_lookup (buf));
00607 case CHK_CLASS:
00608 return (lval_char != NULL
00609 && lval_char->class == class_lookup (buf));
00610 case CHK_OBJTYPE:
00611 return (lval_obj != NULL
00612 && lval_obj->item_type == item_lookup (buf));
00613 default:;
00614 }
00615
00616
00617
00618
00619 if ((oper = keyword_lookup (fn_evals, buf)) < 0)
00620 {
00621 sprintf (buf, "Cmd_eval: prog %d syntax error(5): '%s'",
00622 vnum, original);
00623 bug (buf, 0);
00624 return FALSE;
00625 }
00626 one_argument (line, buf);
00627 rval = atoi (buf);
00628
00629 switch (check)
00630 {
00631 case CHK_VNUM:
00632 switch (code)
00633 {
00634 default:
00635 case 'i':
00636 case 'n':
00637 case 't':
00638 case 'r':
00639 case 'q':
00640 if (lval_char != NULL && IS_NPC (lval_char))
00641 lval = lval_char->pIndexData->vnum;
00642 break;
00643 case 'o':
00644 case 'p':
00645 if (lval_obj != NULL)
00646 lval = lval_obj->pIndexData->vnum;
00647 }
00648 break;
00649 case CHK_HPCNT:
00650 if (lval_char != NULL)
00651 lval =
00652 (lval_char->hit * 100) / (UMAX (1, lval_char->max_hit));
00653 break;
00654 case CHK_ROOM:
00655 if (lval_char != NULL && lval_char->in_room != NULL)
00656 lval = lval_char->in_room->vnum;
00657 break;
00658 case CHK_SEX:
00659 if (lval_char != NULL)
00660 lval = lval_char->sex;
00661 break;
00662 case CHK_LEVEL:
00663 if (lval_char != NULL)
00664 lval = lval_char->level;
00665 break;
00666 case CHK_ALIGN:
00667 if (lval_char != NULL)
00668 lval = lval_char->alignment;
00669 break;
00670 case CHK_MONEY:
00671 if (lval_char != NULL)
00672 lval = lval_char->gold + (lval_char->silver * 100);
00673 break;
00674 case CHK_OBJVAL0:
00675 if (lval_obj != NULL)
00676 lval = lval_obj->value[0];
00677 break;
00678 case CHK_OBJVAL1:
00679 if (lval_obj != NULL)
00680 lval = lval_obj->value[1];
00681 break;
00682 case CHK_OBJVAL2:
00683 if (lval_obj != NULL)
00684 lval = lval_obj->value[2];
00685 break;
00686 case CHK_OBJVAL3:
00687 if (lval_obj != NULL)
00688 lval = lval_obj->value[3];
00689 break;
00690 case CHK_OBJVAL4:
00691 if (lval_obj != NULL)
00692 lval = lval_obj->value[4];
00693 break;
00694 case CHK_GRPSIZE:
00695 if (lval_char != NULL)
00696 lval = count_people_room (lval_char, 4);
00697 break;
00698 default:
00699 return FALSE;
00700 }
00701 return (num_eval (lval, oper, rval));
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711 void expand_arg (char *buf,
00712 const char *format,
00713 CHAR_DATA * mob, CHAR_DATA * ch,
00714 const void *arg1, const void *arg2, CHAR_DATA * rch)
00715 {
00716 static char *const he_she[] = { "it", "he", "she" };
00717 static char *const him_her[] = { "it", "him", "her" };
00718 static char *const his_her[] = { "its", "his", "her" };
00719 const char *someone = "someone";
00720 const char *something = "something";
00721 const char *someones = "someone's";
00722
00723 char fname[MAX_INPUT_LENGTH];
00724 CHAR_DATA *vch = (CHAR_DATA *) arg2;
00725 OBJ_DATA *obj1 = (OBJ_DATA *) arg1;
00726 OBJ_DATA *obj2 = (OBJ_DATA *) arg2;
00727 const char *str;
00728 const char *i;
00729 char *point;
00730
00731
00732
00733
00734 if (format == NULL || format[0] == '\0')
00735 return;
00736
00737 point = buf;
00738 str = format;
00739 while (*str != '\0')
00740 {
00741 if (*str != '$')
00742 {
00743 *point++ = *str++;
00744 continue;
00745 }
00746 ++str;
00747
00748 switch (*str)
00749 {
00750 default:
00751 bug ("Expand_arg: bad code %d.", *str);
00752 i = " <@@@> ";
00753 break;
00754 case 'i':
00755 one_argument (mob->name, fname);
00756 i = fname;
00757 break;
00758 case 'I':
00759 i = mob->short_descr;
00760 break;
00761 case 'n':
00762 i = someone;
00763 if (ch != NULL && can_see (mob, ch))
00764 {
00765 one_argument (ch->name, fname);
00766 i = capitalize (fname);
00767 }
00768 break;
00769 case 'N':
00770 i = (ch != NULL && can_see (mob, ch))
00771 ? (IS_NPC (ch) ? ch->short_descr : ch->name) : someone;
00772 break;
00773 case 't':
00774 i = someone;
00775 if (vch != NULL && can_see (mob, vch))
00776 {
00777 one_argument (vch->name, fname);
00778 i = capitalize (fname);
00779 }
00780 break;
00781 case 'T':
00782 i = (vch != NULL && can_see (mob, vch))
00783 ? (IS_NPC (vch) ? vch->short_descr : vch->name) : someone;
00784 break;
00785 case 'r':
00786 if (rch == NULL)
00787 rch = get_random_char (mob);
00788 i = someone;
00789 if (rch != NULL && can_see (mob, rch))
00790 {
00791 one_argument (rch->name, fname);
00792 i = capitalize (fname);
00793 }
00794 break;
00795 case 'R':
00796 if (rch == NULL)
00797 rch = get_random_char (mob);
00798 i = (rch != NULL && can_see (mob, rch))
00799 ? (IS_NPC (ch) ? ch->short_descr : ch->name) : someone;
00800 break;
00801 case 'q':
00802 i = someone;
00803 if (mob->mprog_target != NULL
00804 && can_see (mob, mob->mprog_target))
00805 {
00806 one_argument (mob->mprog_target->name, fname);
00807 i = capitalize (fname);
00808 }
00809 break;
00810 case 'Q':
00811 i = (mob->mprog_target != NULL
00812 && can_see (mob,
00813 mob->
00814 mprog_target)) ? (IS_NPC (mob->mprog_target)
00815 ? mob->
00816 mprog_target->short_descr :
00817 mob->mprog_target->name) :
00818 someone;
00819 break;
00820 case 'j':
00821 i = he_she[URANGE (0, mob->sex, 2)];
00822 break;
00823 case 'e':
00824 i = (ch != NULL && can_see (mob, ch))
00825 ? he_she[URANGE (0, ch->sex, 2)] : someone;
00826 break;
00827 case 'E':
00828 i = (vch != NULL && can_see (mob, vch))
00829 ? he_she[URANGE (0, vch->sex, 2)] : someone;
00830 break;
00831 case 'J':
00832 i = (rch != NULL && can_see (mob, rch))
00833 ? he_she[URANGE (0, rch->sex, 2)] : someone;
00834 break;
00835 case 'X':
00836 i = (mob->mprog_target != NULL
00837 && can_see (mob, mob->mprog_target)) ? he_she[URANGE (0,
00838 mob->mprog_target->sex,
00839 2)]
00840 : someone; break;
00841 case 'k':
00842 i = him_her[URANGE (0, mob->sex, 2)];
00843 break;
00844 case 'm':
00845 i = (ch != NULL && can_see (mob, ch))
00846 ? him_her[URANGE (0, ch->sex, 2)] : someone;
00847 break;
00848 case 'M':
00849 i = (vch != NULL && can_see (mob, vch))
00850 ? him_her[URANGE (0, vch->sex, 2)] : someone;
00851 break;
00852 case 'K':
00853 if (rch == NULL)
00854 rch = get_random_char (mob);
00855 i = (rch != NULL && can_see (mob, rch))
00856 ? him_her[URANGE (0, rch->sex, 2)] : someone;
00857 break;
00858 case 'Y':
00859 i = (mob->mprog_target != NULL
00860 && can_see (mob, mob->mprog_target)) ? him_her[URANGE (0,
00861 mob->mprog_target->sex,
00862 2)]
00863 : someone; break;
00864 case 'l':
00865 i = his_her[URANGE (0, mob->sex, 2)];
00866 break;
00867 case 's':
00868 i = (ch != NULL && can_see (mob, ch))
00869 ? his_her[URANGE (0, ch->sex, 2)] : someones;
00870 break;
00871 case 'S':
00872 i = (vch != NULL && can_see (mob, vch))
00873 ? his_her[URANGE (0, vch->sex, 2)] : someones;
00874 break;
00875 case 'L':
00876 if (rch == NULL)
00877 rch = get_random_char (mob);
00878 i = (rch != NULL && can_see (mob, rch))
00879 ? his_her[URANGE (0, rch->sex, 2)] : someones;
00880 break;
00881 case 'Z':
00882 i = (mob->mprog_target != NULL
00883 && can_see (mob, mob->mprog_target)) ? his_her[URANGE (0,
00884 mob->mprog_target->sex,
00885 2)]
00886 : someones; break;
00887 case 'o':
00888 i = something;
00889 if (obj1 != NULL && can_see_obj (mob, obj1))
00890 {
00891 one_argument (obj1->name, fname);
00892 i = fname;
00893 }
00894 break;
00895 case 'O':
00896 i = (obj1 != NULL && can_see_obj (mob, obj1))
00897 ? obj1->short_descr : something;
00898 break;
00899 case 'p':
00900 i = something;
00901 if (obj2 != NULL && can_see_obj (mob, obj2))
00902 {
00903 one_argument (obj2->name, fname);
00904 i = fname;
00905 }
00906 break;
00907 case 'P':
00908 i = (obj2 != NULL && can_see_obj (mob, obj2))
00909 ? obj2->short_descr : something;
00910 break;
00911 }
00912
00913 ++str;
00914 while ((*point = *i) != '\0')
00915 ++point, ++i;
00916
00917 }
00918 *point = '\0';
00919
00920 return;
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 #define MAX_NESTED_LEVEL 12
00934 #define BEGIN_BLOCK 0
00935 #define IN_BLOCK -1
00936 #define END_BLOCK -2
00937 #define MAX_CALL_LEVEL 10
00938
00939 void program_flow (int pvnum,
00940 char *source,
00941 CHAR_DATA * mob, CHAR_DATA * ch, const void *arg1,
00942 const void *arg2)
00943 {
00944 CHAR_DATA *rch = NULL;
00945 char *code, *line;
00946 char buf[MAX_STRING_LENGTH];
00947 char control[MAX_INPUT_LENGTH], data[MAX_STRING_LENGTH];
00948
00949 static int call_level;
00950
00951 int level, eval, check;
00952 int state[MAX_NESTED_LEVEL],
00953 cond[MAX_NESTED_LEVEL];
00954
00955 sh_int mvnum = mob->pIndexData->vnum;
00956
00957 if (++call_level > MAX_CALL_LEVEL)
00958 {
00959 bug ("MOBprogs: MAX_CALL_LEVEL exceeded, vnum %d",
00960 mob->pIndexData->vnum);
00961 return;
00962 }
00963
00964
00965
00966
00967 for (level = 0; level < MAX_NESTED_LEVEL; level++)
00968 {
00969 state[level] = IN_BLOCK;
00970 cond[level] = TRUE;
00971 }
00972 level = 0;
00973
00974 code = source;
00975
00976
00977
00978 while (*code)
00979 {
00980 bool first_arg = TRUE;
00981 char *b = buf, *c = control, *d = data;
00982
00983
00984
00985
00986 while (isspace (*code) && *code)
00987 code++;
00988 while (*code)
00989 {
00990 if (*code == '\n' || *code == '\r')
00991 break;
00992 else if (isspace (*code))
00993 {
00994 if (first_arg)
00995 first_arg = FALSE;
00996 else
00997 *d++ = *code;
00998 }
00999 else
01000 {
01001 if (first_arg)
01002 *c++ = *code;
01003 else
01004 *d++ = *code;
01005 }
01006 *b++ = *code++;
01007 }
01008 *b = *c = *d = '\0';
01009
01010 if (buf[0] == '\0')
01011 break;
01012 if (buf[0] == '*')
01013 continue;
01014
01015 line = data;
01016
01017
01018
01019 if (!str_cmp (control, "if"))
01020 {
01021 if (state[level] == BEGIN_BLOCK)
01022 {
01023 sprintf (buf,
01024 "Mobprog: misplaced if statement, mob %d prog %d",
01025 mvnum, pvnum);
01026 bug (buf, 0);
01027 return;
01028 }
01029 state[level] = BEGIN_BLOCK;
01030 if (++level >= MAX_NESTED_LEVEL)
01031 {
01032 sprintf (buf,
01033 "Mobprog: Max nested level exceeded, mob %d prog %d",
01034 mvnum, pvnum);
01035 bug (buf, 0);
01036 return;
01037 }
01038 if (level && cond[level - 1] == FALSE)
01039 {
01040 cond[level] = FALSE;
01041 continue;
01042 }
01043 line = one_argument (line, control);
01044 if ((check = keyword_lookup (fn_keyword, control)) >= 0)
01045 {
01046 cond[level] =
01047 cmd_eval (pvnum, line, check, mob, ch, arg1, arg2, rch);
01048 }
01049 else
01050 {
01051 sprintf (buf,
01052 "Mobprog: invalid if_check (if), mob %d prog %d",
01053 mvnum, pvnum);
01054 bug (buf, 0);
01055 return;
01056 }
01057 state[level] = END_BLOCK;
01058 }
01059 else if (!str_cmp (control, "or"))
01060 {
01061 if (!level || state[level - 1] != BEGIN_BLOCK)
01062 {
01063 sprintf (buf, "Mobprog: or without if, mob %d prog %d",
01064 mvnum, pvnum);
01065 bug (buf, 0);
01066 return;
01067 }
01068 if (level && cond[level - 1] == FALSE)
01069 continue;
01070 line = one_argument (line, control);
01071 if ((check = keyword_lookup (fn_keyword, control)) >= 0)
01072 {
01073 eval =
01074 cmd_eval (pvnum, line, check, mob, ch, arg1, arg2, rch);
01075 }
01076 else
01077 {
01078 sprintf (buf,
01079 "Mobprog: invalid if_check (or), mob %d prog %d",
01080 mvnum, pvnum);
01081 bug (buf, 0);
01082 return;
01083 }
01084 cond[level] = (eval == TRUE) ? TRUE : cond[level];
01085 }
01086 else if (!str_cmp (control, "and"))
01087 {
01088 if (!level || state[level - 1] != BEGIN_BLOCK)
01089 {
01090 sprintf (buf, "Mobprog: and without if, mob %d prog %d",
01091 mvnum, pvnum);
01092 bug (buf, 0);
01093 return;
01094 }
01095 if (level && cond[level - 1] == FALSE)
01096 continue;
01097 line = one_argument (line, control);
01098 if ((check = keyword_lookup (fn_keyword, control)) >= 0)
01099 {
01100 eval =
01101 cmd_eval (pvnum, line, check, mob, ch, arg1, arg2, rch);
01102 }
01103 else
01104 {
01105 sprintf (buf,
01106 "Mobprog: invalid if_check (and), mob %d prog %d",
01107 mvnum, pvnum);
01108 bug (buf, 0);
01109 return;
01110 }
01111 cond[level] = (cond[level] == TRUE)
01112 && (eval == TRUE) ? TRUE : FALSE;
01113 }
01114 else if (!str_cmp (control, "endif"))
01115 {
01116 if (!level || state[level - 1] != BEGIN_BLOCK)
01117 {
01118 sprintf (buf, "Mobprog: endif without if, mob %d prog %d",
01119 mvnum, pvnum);
01120 bug (buf, 0);
01121 return;
01122 }
01123 cond[level] = TRUE;
01124 state[level] = IN_BLOCK;
01125 state[--level] = END_BLOCK;
01126 }
01127 else if (!str_cmp (control, "else"))
01128 {
01129 if (!level || state[level - 1] != BEGIN_BLOCK)
01130 {
01131 sprintf (buf, "Mobprog: else without if, mob %d prog %d",
01132 mvnum, pvnum);
01133 bug (buf, 0);
01134 return;
01135 }
01136 if (level && cond[level - 1] == FALSE)
01137 continue;
01138 state[level] = IN_BLOCK;
01139 cond[level] = (cond[level] == TRUE) ? FALSE : TRUE;
01140 }
01141 else if (cond[level] == TRUE
01142 && (!str_cmp (control, "break")
01143 || !str_cmp (control, "end")))
01144 {
01145 call_level--;
01146 return;
01147 }
01148 else if ((!level || cond[level] == TRUE) && buf[0] != '\0')
01149 {
01150 state[level] = IN_BLOCK;
01151 expand_arg (data, buf, mob, ch, arg1, arg2, rch);
01152 if (!str_cmp (control, "mob"))
01153 {
01154
01155
01156
01157 line = one_argument (data, control);
01158 mob_interpret (mob, line);
01159 }
01160 else
01161 {
01162
01163
01164
01165 interpret (mob, data);
01166 }
01167 }
01168 }
01169 call_level--;
01170 }
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 void mp_act_trigger (
01184 char *argument, CHAR_DATA * mob, CHAR_DATA * ch,
01185 const void *arg1, const void *arg2, int type)
01186 {
01187 MPROG_LIST *prg;
01188
01189 if (!IS_NPC(mob)) return;
01190
01191 for (prg = mob->pIndexData->mprogs; prg != NULL; prg = prg->next)
01192 {
01193 if (prg->trig_type == type
01194 && strstr (argument, prg->trig_phrase) != NULL)
01195 {
01196 program_flow (prg->vnum, prg->code, mob, ch, arg1, arg2);
01197 break;
01198 }
01199 }
01200 return;
01201 }
01202
01203
01204
01205
01206
01207 bool mp_percent_trigger (CHAR_DATA * mob, CHAR_DATA * ch,
01208 const void *arg1, const void *arg2, int type)
01209 {
01210 MPROG_LIST *prg;
01211
01212 for (prg = mob->pIndexData->mprogs; prg != NULL; prg = prg->next)
01213 {
01214 if (prg->trig_type == type
01215 && number_percent () < atoi (prg->trig_phrase))
01216 {
01217 program_flow (prg->vnum, prg->code, mob, ch, arg1, arg2);
01218 return (TRUE);
01219 }
01220 }
01221 return (FALSE);
01222 }
01223
01224 void mp_bribe_trigger (CHAR_DATA * mob, CHAR_DATA * ch, int amount)
01225 {
01226 MPROG_LIST *prg;
01227
01228
01229
01230
01231
01232
01233 for (prg = mob->pIndexData->mprogs; prg; prg = prg->next)
01234 {
01235 if (prg->trig_type == TRIG_BRIBE && amount >= atoi (prg->trig_phrase))
01236 {
01237 program_flow (prg->vnum, prg->code, mob, ch, NULL, NULL);
01238 break;
01239 }
01240 }
01241 return;
01242 }
01243
01244 bool mp_exit_trigger (CHAR_DATA * ch, int dir)
01245 {
01246 CHAR_DATA *mob;
01247 MPROG_LIST *prg;
01248
01249 for (mob = ch->in_room->people; mob != NULL; mob = mob->next_in_room)
01250 {
01251 if (IS_NPC (mob)
01252 && (HAS_TRIGGER (mob, TRIG_EXIT)
01253 || HAS_TRIGGER (mob, TRIG_EXALL)))
01254 {
01255 for (prg = mob->pIndexData->mprogs; prg; prg = prg->next)
01256 {
01257
01258
01259
01260
01261
01262 if (prg->trig_type == TRIG_EXIT
01263 && dir == atoi (prg->trig_phrase)
01264 && mob->position == mob->pIndexData->default_pos
01265 && can_see (mob, ch))
01266 {
01267 program_flow (prg->vnum, prg->code, mob, ch, NULL, NULL);
01268 return TRUE;
01269 }
01270 else
01271 if (prg->trig_type == TRIG_EXALL
01272 && dir == atoi (prg->trig_phrase))
01273 {
01274 program_flow (prg->vnum, prg->code, mob, ch, NULL, NULL);
01275 return TRUE;
01276 }
01277 }
01278 }
01279 }
01280 return FALSE;
01281 }
01282
01283 void mp_give_trigger (CHAR_DATA * mob, CHAR_DATA * ch, OBJ_DATA * obj)
01284 {
01285
01286 char buf[MAX_INPUT_LENGTH], *p;
01287 MPROG_LIST *prg;
01288
01289 for (prg = mob->pIndexData->mprogs; prg; prg = prg->next)
01290 if (prg->trig_type == TRIG_GIVE)
01291 {
01292 p = prg->trig_phrase;
01293
01294
01295
01296 if (is_number (p))
01297 {
01298 if (obj->pIndexData->vnum == atoi (p))
01299 {
01300 program_flow (prg->vnum, prg->code, mob, ch, (void *) obj,
01301 NULL);
01302 return;
01303 }
01304 }
01305
01306
01307
01308 else
01309 {
01310 while (*p)
01311 {
01312 p = one_argument (p, buf);
01313
01314 if (is_name (buf, obj->name) || !str_cmp ("all", buf))
01315 {
01316 program_flow (prg->vnum, prg->code, mob, ch,
01317 (void *) obj, NULL);
01318 return;
01319 }
01320 }
01321 }
01322 }
01323 }
01324
01325 void mp_greet_trigger (CHAR_DATA * ch)
01326 {
01327 CHAR_DATA *mob;
01328
01329 for (mob = ch->in_room->people; mob != NULL; mob = mob->next_in_room)
01330 {
01331 if (IS_NPC (mob)
01332 && (HAS_TRIGGER (mob, TRIG_GREET)
01333 || HAS_TRIGGER (mob, TRIG_GRALL)))
01334 {
01335
01336
01337
01338
01339
01340 if (HAS_TRIGGER (mob, TRIG_GREET)
01341 && mob->position == mob->pIndexData->default_pos
01342 && can_see (mob, ch))
01343 mp_percent_trigger (mob, ch, NULL, NULL, TRIG_GREET);
01344 else if (HAS_TRIGGER (mob, TRIG_GRALL))
01345 mp_percent_trigger (mob, ch, NULL, NULL, TRIG_GRALL);
01346 }
01347 }
01348 return;
01349 }
01350
01351 void mp_hprct_trigger (CHAR_DATA * mob, CHAR_DATA * ch)
01352 {
01353 MPROG_LIST *prg;
01354
01355 for (prg = mob->pIndexData->mprogs; prg != NULL; prg = prg->next)
01356 if ((prg->trig_type == TRIG_HPCNT)
01357 && ((100 * mob->hit / mob->max_hit) < atoi (prg->trig_phrase)))
01358 {
01359 program_flow (prg->vnum, prg->code, mob, ch, NULL, NULL);
01360 break;
01361 }
01362 }