path.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2019 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  19. ******************************************************************************/
  20. /******************************************************************************
  21. * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t *
  22. * *
  23. * coded by Peter Unold 1992 *
  24. * recoded by Igor van den Hoven 2004 *
  25. ******************************************************************************/
  26. #include "tintin.h"
  27. DO_COMMAND(do_path)
  28. {
  29. char arg1[BUFFER_SIZE];
  30. int cnt;
  31. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  32. if (*arg1 == 0)
  33. {
  34. tintin_header(ses, " PATH OPTIONS ");
  35. for (cnt = 0 ; *path_table[cnt].fun != NULL ; cnt++)
  36. {
  37. if (*path_table[cnt].desc)
  38. {
  39. tintin_printf2(ses, " [%-13s] %s", path_table[cnt].name, path_table[cnt].desc);
  40. }
  41. }
  42. tintin_header(ses, "");
  43. return ses;
  44. }
  45. else
  46. {
  47. for (cnt = 0 ; *path_table[cnt].name ; cnt++)
  48. {
  49. if (is_abbrev(arg1, path_table[cnt].name))
  50. {
  51. break;
  52. }
  53. }
  54. if (*path_table[cnt].name == 0)
  55. {
  56. do_path(ses, "");
  57. }
  58. else
  59. {
  60. path_table[cnt].fun(ses, arg);
  61. }
  62. }
  63. return ses;
  64. }
  65. DO_PATH(path_create)
  66. {
  67. struct listroot *root = ses->list[LIST_PATH];
  68. kill_list(root);
  69. root->update = 0;
  70. show_message(ses, LIST_COMMAND, "#PATH CREATE: YOU START MAPPING A NEW PATH.");
  71. SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  72. }
  73. DO_PATH(path_destroy)
  74. {
  75. struct listroot *root = ses->list[LIST_PATH];
  76. kill_list(root);
  77. root->update = 0;
  78. DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  79. show_message(ses, LIST_COMMAND, "#PATH DESTROY: PATH DESTROYED.");
  80. }
  81. DO_PATH(path_start)
  82. {
  83. if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  84. {
  85. show_message(ses, LIST_COMMAND, "#PATH START: ERROR: YOU ARE ALREADY MAPPING A PATH.");
  86. }
  87. else
  88. {
  89. SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  90. show_message(ses, LIST_COMMAND, "#PATH START: YOU START MAPPING A PATH.");
  91. }
  92. }
  93. DO_PATH(path_stop)
  94. {
  95. int index;
  96. struct listroot *root = ses->list[LIST_PATH];
  97. if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  98. {
  99. show_message(ses, LIST_COMMAND, "#PATH STOP: YOU STOP MAPPING A PATH.");
  100. DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  101. }
  102. else
  103. {
  104. if (root->list[root->update]->val64)
  105. {
  106. for (index = 0 ; index < root->used ; index++)
  107. {
  108. root->list[index]->val64 = 0;
  109. }
  110. show_message(ses, LIST_COMMAND, "#PATH STOP: YOU STOP RUNNING A PATH.");
  111. }
  112. else
  113. {
  114. show_message(ses, LIST_COMMAND, "#PATH STOP: YOU ARE NOT MAPPING OR RUNNING A PATH.");
  115. }
  116. }
  117. }
  118. DO_PATH(path_describe)
  119. {
  120. char *dirs[] = {
  121. "west", "west-southwest", "southwest", "south-southwest",
  122. "south", "south-southeast", "southeast", "east-southeast",
  123. "east", "east-northeast", "northeast", "north-northeast",
  124. "north", "north-northwest", "northwest", "west-northwest",
  125. "west" };
  126. char *slopes[] = {
  127. "a steep upward slope", "a steady upward slope", "a slight upward slope",
  128. "the same level",
  129. "a slight downward slope", "a steady downward slope", "a steep downward slope" };
  130. struct listroot *root = ses->list[LIST_PATH];
  131. struct listnode *node;
  132. int a, d, i, s, x, y, z;
  133. i = x = y = z = 0;
  134. i = root->update;
  135. while (i < root->used)
  136. {
  137. node = search_node_list(ses->list[LIST_PATHDIR], root->list[i++]->arg1);
  138. if (node)
  139. {
  140. x += (HAS_BIT(atoi(node->arg3), MAP_EXIT_E) ? 1 : HAS_BIT(atoi(node->arg3), MAP_EXIT_W) ? -1 : 0);
  141. y += (HAS_BIT(atoi(node->arg3), MAP_EXIT_N) ? 1 : HAS_BIT(atoi(node->arg3), MAP_EXIT_S) ? -1 : 0);
  142. z += (HAS_BIT(atoi(node->arg3), MAP_EXIT_U) ? 1 : HAS_BIT(atoi(node->arg3), MAP_EXIT_D) ? -1 : 0);
  143. }
  144. }
  145. a = sqrt(x * x + y * y);
  146. a = sqrt(a * a + z * z);
  147. d = round(16 * (atan2(y, x) + M_PI) / (M_PI * 2));
  148. s = round(12 * (atan2(a, z) - M_PI / 4) / M_PI);
  149. if (x == 0 && y == 0)
  150. {
  151. if (z == 0)
  152. {
  153. if (root->used > 2)
  154. {
  155. tintin_printf2(ses, "The path is %d rooms long and leads back to where you are at.", root->used);
  156. }
  157. else
  158. {
  159. tintin_printf2(ses, "The path is %d rooms long and the destination is right where you are at.", root->used);
  160. }
  161. }
  162. else
  163. {
  164. tintin_printf2(ses, "The path is %d rooms long and the destination lies %d rooms %s of you.", root->used, abs(z), z < 0 ? "below" : "above", s);
  165. }
  166. }
  167. else
  168. {
  169. tintin_printf2(ses, "The path is %d rooms long and the destination lies %d rooms to the %s of you at %s.", root->used, a, dirs[d], slopes[s]);
  170. }
  171. if (root->update == 0)
  172. {
  173. tintin_printf2(ses, "You are at the start of the path.");
  174. }
  175. else if (root->update == root->used)
  176. {
  177. tintin_printf2(ses, "You are at the end of the path.");
  178. }
  179. else
  180. {
  181. tintin_printf2(ses, "You've traversed %d out of %d steps of the path.", root->update, root->used);
  182. }
  183. }
  184. DO_PATH(path_map)
  185. {
  186. struct listroot *root = ses->list[LIST_PATH];
  187. char buf[BUFFER_SIZE];
  188. int i = 0;
  189. if (root->used == 0)
  190. {
  191. show_message(ses, LIST_COMMAND, "#PATH MAP: EMPTY PATH.");
  192. }
  193. else
  194. {
  195. sprintf(buf, "%-7s", "#PATH:");
  196. for (i = 0 ; i < root->update ; i++)
  197. {
  198. cat_sprintf(buf, " %s", root->list[i]->arg1);
  199. }
  200. if (i != root->used)
  201. {
  202. cat_sprintf(buf, " [%s]", root->list[i++]->arg1);
  203. for (i = root->update + 1 ; i < root->used ; i++)
  204. {
  205. cat_sprintf(buf, " %s", root->list[i]->arg1);
  206. }
  207. }
  208. if (root->update == root->used)
  209. {
  210. cat_sprintf(buf, " [ ]");
  211. }
  212. tintin_puts2(ses, buf);
  213. }
  214. }
  215. DO_PATH(path_save)
  216. {
  217. struct listroot *root = ses->list[LIST_PATH];
  218. char result[STRING_SIZE], arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  219. int i;
  220. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  221. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  222. if (root->used == 0)
  223. {
  224. tintin_puts2(ses, "#PATH SAVE: LOAD OR CREATE A PATH FIRST.");
  225. }
  226. else if (*arg2 == 0)
  227. {
  228. show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH SAVE <BACKWARD|FORWARD|LENGTH|POSITION> <VARIABLE NAME>");
  229. }
  230. else if (is_abbrev(arg1, "BACKWARDS"))
  231. {
  232. result[0] = 0;
  233. for (i = root->used - 1 ; i >= 0 ; i--)
  234. {
  235. strcat(result, root->list[i]->arg2);
  236. if (i != 0)
  237. {
  238. cat_sprintf(result, "%c", COMMAND_SEPARATOR);
  239. }
  240. }
  241. set_nest_node_ses(ses, arg2, "%s", result);
  242. show_message(ses, LIST_COMMAND, "#PATH SAVE: BACKWARD PATH SAVED TO {%s}", arg2);
  243. }
  244. else if (is_abbrev(arg1, "FORWARDS"))
  245. {
  246. result[0] = 0;
  247. for (i = 0 ; i < root->used ; i++)
  248. {
  249. strcat(result, root->list[i]->arg1);
  250. if (i != root->used - 1)
  251. {
  252. cat_sprintf(result, "%c", COMMAND_SEPARATOR);
  253. }
  254. }
  255. set_nest_node_ses(ses, arg2, "%s", result);
  256. show_message(ses, LIST_COMMAND, "#PATH SAVE: FORWARD PATH SAVED TO {%s}", arg2);
  257. }
  258. else if (is_abbrev(arg1, "LENGTH"))
  259. {
  260. sprintf(result, "%d", root->used);
  261. set_nest_node_ses(ses, arg2, "%s", result);
  262. show_message(ses, LIST_COMMAND, "#PATH SAVE: PATH LENGTH SAVED TO {%s}", arg2);
  263. }
  264. else if (is_abbrev(arg1, "POSITION"))
  265. {
  266. sprintf(result, "%d", root->update + 1);
  267. set_nest_node_ses(ses, arg2, "%s", result);
  268. show_message(ses, LIST_COMMAND, "#PATH SAVE: PATH POSITION SAVED TO {%s}", arg2);
  269. }
  270. else
  271. {
  272. show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH SAVE <BACKWARD|FORWARD|LENGTH|POSITION> <VARIABLE NAME>");
  273. }
  274. }
  275. DO_PATH(path_load)
  276. {
  277. struct listroot *root = ses->list[LIST_PATH];
  278. char arg1[BUFFER_SIZE], temp[BUFFER_SIZE];
  279. struct listnode *node;
  280. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  281. if ((node = search_nest_node_ses(ses, arg1)) == NULL)
  282. {
  283. arg = arg1;
  284. }
  285. else
  286. {
  287. arg = node->arg2;
  288. }
  289. kill_list(root);
  290. root->update = 0;
  291. while (*arg)
  292. {
  293. if (*arg == ';')
  294. {
  295. arg++;
  296. }
  297. arg = get_arg_in_braces(ses, arg, temp, GET_ALL);
  298. if ((node = search_node_list(root, temp)))
  299. {
  300. insert_node_list(root, node->arg1, node->arg2, "0", "");
  301. }
  302. else
  303. {
  304. insert_node_list(root, temp, temp, "0", "");
  305. }
  306. }
  307. show_message(ses, LIST_COMMAND, "#PATH LOAD: PATH WITH %d NODES LOADED.", root->used);
  308. }
  309. DO_PATH(path_delete)
  310. {
  311. struct listroot *root = ses->list[LIST_PATH];
  312. if (root->used)
  313. {
  314. show_message(ses, LIST_COMMAND, "#PATH DELETE: DELETED MOVE {%s}.", root->list[root->used - 1]->arg1);
  315. delete_index_list(root, root->used - 1);
  316. if (root->update >= root->used)
  317. {
  318. root->update--;
  319. }
  320. }
  321. else
  322. {
  323. tintin_puts(ses, "#PATH DELETE: NO MOVES LEFT.");
  324. }
  325. }
  326. DO_PATH(path_insert)
  327. {
  328. struct listroot *root = ses->list[LIST_PATH];
  329. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  330. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  331. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  332. if (*arg1 == 0 && *arg2 == 0)
  333. {
  334. show_message(ses, LIST_COMMAND, "#PATH INSERT: ERROR: YOU MUST GIVE A COMMAND TO INSERT");
  335. }
  336. else
  337. {
  338. insert_node_list(root, arg1, arg2, "0", "");
  339. show_message(ses, LIST_COMMAND, "#PATH INSERT: FORWARD {%s} BACKWARD {%s}.", arg1, arg2);
  340. if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  341. {
  342. root->update = root->used;
  343. }
  344. }
  345. }
  346. DO_PATH(path_run)
  347. {
  348. int index;
  349. struct listroot *root = ses->list[LIST_PATH];
  350. char arg1[BUFFER_SIZE];
  351. long long total, delay;
  352. push_call("path_run(%p,%p)",ses,arg);
  353. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  354. if (root->update == root->used)
  355. {
  356. tintin_puts(ses, "#PATH RUN: #END OF PATH.");
  357. }
  358. else
  359. {
  360. if (*arg1)
  361. {
  362. delay = (long long) get_number(ses, arg1) * 1000000LL;
  363. total = 0;
  364. DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  365. for (index = root->update ; index < root->used ; index++)
  366. {
  367. root->list[index]->val64 = gtd->utime + total;
  368. total += delay;
  369. }
  370. }
  371. else
  372. {
  373. while (root->update < root->used)
  374. {
  375. script_driver(ses, LIST_COMMAND, root->list[root->update++]->arg1);
  376. }
  377. }
  378. }
  379. pop_call();
  380. return;
  381. }
  382. DO_PATH(path_walk)
  383. {
  384. struct listroot *root = ses->list[LIST_PATH];
  385. char arg1[BUFFER_SIZE];
  386. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  387. DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  388. if (is_abbrev(arg1, "BACKWARDS"))
  389. {
  390. if (root->update == 0)
  391. {
  392. tintin_puts(ses, "#PATH WALK: #START OF PATH.");
  393. }
  394. else
  395. {
  396. script_driver(ses, LIST_COMMAND, root->list[--root->update]->arg2);
  397. if (root->update == 0)
  398. {
  399. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 0, "START OF PATH");
  400. }
  401. }
  402. }
  403. else if (*arg1 == 0 || is_abbrev(arg1, "FORWARDS"))
  404. {
  405. if (root->update == root->used)
  406. {
  407. tintin_puts(ses, "#PATH WALK: #END OF PATH.");
  408. }
  409. else
  410. {
  411. script_driver(ses, LIST_COMMAND, root->list[root->update++]->arg1);
  412. if (root->update == root->used)
  413. {
  414. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 0, "END OF PATH");
  415. }
  416. }
  417. }
  418. else
  419. {
  420. show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH WALK {FORWARD|BACKWARD}.");
  421. }
  422. }
  423. DO_PATH(path_swap)
  424. {
  425. struct listroot *root = ses->list[LIST_PATH];
  426. struct listnode *node;
  427. int a, z;
  428. if (root->used == 0)
  429. {
  430. show_error(ses, LIST_COMMAND, "#PATH SWAP: ERROR: PATH IS EMPTY.");
  431. return;
  432. }
  433. a = 0;
  434. z = root->used - 1;
  435. if (root->update)
  436. {
  437. root->update = root->used - root->update;
  438. }
  439. while (z > a)
  440. {
  441. arg = root->list[z]->arg1;
  442. root->list[z]->arg1 = root->list[z]->arg2;
  443. root->list[z]->arg2 = arg;
  444. arg = root->list[a]->arg1;
  445. root->list[a]->arg1 = root->list[a]->arg2;
  446. root->list[a]->arg2 = arg;
  447. node = root->list[z];
  448. root->list[z--] = root->list[a];
  449. root->list[a++] = node;
  450. }
  451. if (z == a)
  452. {
  453. arg = root->list[z]->arg1;
  454. root->list[z]->arg1 = root->list[z]->arg2;
  455. root->list[z]->arg2 = arg;
  456. }
  457. show_message(ses, LIST_COMMAND, "#PATH SWAP: PATH HAS BEEN SWAPPED.");
  458. }
  459. DO_PATH(path_zip)
  460. {
  461. struct listroot *root = ses->list[LIST_PATH];
  462. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  463. int i, cnt;
  464. cnt = 1;
  465. *arg1 = 0;
  466. *arg2 = 0;
  467. for (i = 0 ; i < root->used ; i++)
  468. {
  469. if (search_node_list(root, root->list[i]->arg1) == NULL || strlen(root->list[i]->arg1) != 1)
  470. {
  471. if (i && search_node_list(root, root->list[i - 1]->arg1) != NULL && strlen(root->list[i - 1]->arg1) == 1)
  472. {
  473. cat_sprintf(arg1, "%c", COMMAND_SEPARATOR);
  474. }
  475. cat_sprintf(arg1, "%s", root->list[i]->arg1);
  476. if (i < root->used - 1)
  477. {
  478. cat_sprintf(arg1, "%c", COMMAND_SEPARATOR);
  479. }
  480. continue;
  481. }
  482. if (i < root->used - 1 && !strcmp(root->list[i]->arg1, root->list[i + 1]->arg1))
  483. {
  484. cnt++;
  485. }
  486. else
  487. {
  488. cat_sprintf(arg1, "%d%s", cnt, root->list[i]->arg1);
  489. cnt = 1;
  490. }
  491. }
  492. for (i = root->used - 1 ; i >= 0 ; i--)
  493. {
  494. if (search_node_list(root, root->list[i]->arg2) == NULL || strlen(root->list[i]->arg2) != 1)
  495. {
  496. if (i != root->used - 1 && search_node_list(root, root->list[i + 1]->arg2) != NULL && strlen(root->list[i + 1]->arg2) == 1)
  497. {
  498. cat_sprintf(arg2, "%c", COMMAND_SEPARATOR);
  499. }
  500. cat_sprintf(arg2, "%s", root->list[i]->arg2);
  501. if (i > 0)
  502. {
  503. cat_sprintf(arg2, "%c", COMMAND_SEPARATOR);
  504. }
  505. continue;
  506. }
  507. if (i > 0 && !strcmp(root->list[i]->arg2, root->list[i - 1]->arg2))
  508. {
  509. cnt++;
  510. }
  511. else
  512. {
  513. cat_sprintf(arg2, "%d%s", cnt, root->list[i]->arg2);
  514. cnt = 1;
  515. }
  516. }
  517. root->update = root->used;
  518. kill_list(root);
  519. insert_node_list(root, arg1, arg2, "0", "");
  520. show_message(ses, LIST_COMMAND, "#PATH ZIP: THE PATH HAS BEEN ZIPPED TO {%s} {%s}.", arg1, arg2);
  521. }
  522. DO_PATH(path_unzip)
  523. {
  524. struct listroot *root = ses->list[LIST_PATH];
  525. char arg1[BUFFER_SIZE], temp[BUFFER_SIZE], *str;
  526. struct listnode *node;
  527. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  528. if ((node = search_nest_node_ses(ses, arg1)) == NULL)
  529. {
  530. arg = arg1;
  531. }
  532. else
  533. {
  534. arg = node->arg2;
  535. }
  536. kill_list(root);
  537. root->update = 0;
  538. while (*arg)
  539. {
  540. if (*arg == ';')
  541. {
  542. arg++;
  543. }
  544. arg = get_arg_in_braces(ses, arg, temp, GET_ALL);
  545. if (is_speedwalk(ses, temp))
  546. {
  547. char dir[2];
  548. int cnt, i;
  549. str = temp;
  550. for (dir[1] = 0 ; *str ; str++)
  551. {
  552. if (isdigit((int) *str))
  553. {
  554. sscanf(str, "%d%c", &cnt, dir);
  555. while (*str != dir[0])
  556. {
  557. str++;
  558. }
  559. }
  560. else
  561. {
  562. cnt = 1;
  563. dir[0] = *str;
  564. }
  565. for (i = 0 ; i < cnt ; i++)
  566. {
  567. if ((node = search_node_list(ses->list[LIST_PATHDIR], dir)))
  568. {
  569. insert_node_list(root, node->arg1, node->arg2, "0", "");
  570. }
  571. else
  572. {
  573. insert_node_list(root, dir, dir, "0", "");
  574. }
  575. }
  576. }
  577. }
  578. else
  579. {
  580. if ((node = search_node_list(ses->list[LIST_PATHDIR], temp)))
  581. {
  582. insert_node_list(root, node->arg1, node->arg2, "0", "");
  583. }
  584. else
  585. {
  586. insert_node_list(root, temp, temp, "0", "");
  587. }
  588. }
  589. }
  590. show_message(ses, LIST_COMMAND, "#PATH UNZIP: PATH WITH %d NODES UNZIPPED.", root->used);
  591. }
  592. DO_PATH(path_goto)
  593. {
  594. struct listroot *root = ses->list[LIST_PATH];
  595. char arg1[BUFFER_SIZE];
  596. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  597. if (is_abbrev(arg1, "END"))
  598. {
  599. root->update = root->used;
  600. show_message(ses, LIST_COMMAND, "#PATH GOTO: POSITION SET TO {%d}.", root->update + 1);
  601. }
  602. else if (is_abbrev(arg1, "START"))
  603. {
  604. root->update = 0;
  605. show_message(ses, LIST_COMMAND, "#PATH GOTO: POSITION SET TO %d.", root->update + 1);
  606. }
  607. else if (is_math(ses, arg1))
  608. {
  609. if (get_number(ses, arg1) < 1 || get_number(ses, arg1) > root->used + 1)
  610. {
  611. show_message(ses, LIST_COMMAND, "#PATH GOTO: POSITION MUST BE BETWEEN 1 AND %d.", root->used + 1);
  612. }
  613. else
  614. {
  615. root->update = get_number(ses, arg1) - 1;
  616. show_message(ses, LIST_COMMAND, "#PATH GOTO: POSITION SET TO %d.", root->update + 1);
  617. }
  618. }
  619. }
  620. DO_PATH(path_move)
  621. {
  622. struct listroot *root = ses->list[LIST_PATH];
  623. char arg1[BUFFER_SIZE];
  624. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  625. if (is_abbrev(arg1, "BACKWARD"))
  626. {
  627. if (root->update == 0)
  628. {
  629. show_message(ses, LIST_COMMAND, "#PATH GOTO: ALREADY AT START OF PATH.", root->update);
  630. }
  631. else
  632. {
  633. root->update--;
  634. show_message(ses, LIST_COMMAND, "#PATH MOVE: POSITION SET TO %d.", root->update);
  635. }
  636. }
  637. else if (is_abbrev(arg1, "FORWARD"))
  638. {
  639. if (root->update == root->used)
  640. {
  641. show_message(ses, LIST_COMMAND, "#PATH MOVE: ALREADY AT END OF PATH.", root->update);
  642. }
  643. else
  644. {
  645. root->update++;
  646. show_message(ses, LIST_COMMAND, "#PATH MOVE: POSITION SET TO %d.", root->update);
  647. }
  648. }
  649. else if (is_math(ses, arg1))
  650. {
  651. root->update = URANGE(0, root->update + get_number(ses, arg1), root->used);
  652. show_message(ses, LIST_COMMAND, "#PATH MOVE: POSITION SET TO %d.", root->update + 1);
  653. }
  654. }
  655. DO_PATH(path_undo)
  656. {
  657. struct listroot *root = ses->list[LIST_PATH];
  658. if (root->used == 0)
  659. {
  660. show_message(ses, LIST_COMMAND, "#PATH UNDO: ERROR: PATH IS EMPTY.");
  661. return;
  662. }
  663. if (root->update != root->used)
  664. {
  665. show_message(ses, LIST_COMMAND, "#PATH UNDO: ERROR: YOUR POSITION IS NOT AT END OF PATH.");
  666. return;
  667. }
  668. if (!HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  669. {
  670. show_message(ses, LIST_COMMAND, "#PATH UNDO: ERROR: YOU ARE NOT CURRENTLY MAPPING A PATH.");
  671. return;
  672. }
  673. DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  674. script_driver(ses, LIST_COMMAND, root->list[root->used - 1]->arg2);
  675. SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  676. delete_index_list(root, root->used - 1);
  677. root->update = root->used;
  678. show_message(ses, LIST_COMMAND, "#PATH MOVE: POSITION SET TO %d.", root->update);
  679. }
  680. void check_append_path(struct session *ses, char *forward, char *backward, int follow)
  681. {
  682. struct listroot *root = ses->list[LIST_PATH];
  683. struct listnode *node;
  684. if (follow)
  685. {
  686. if ((node = search_node_list(ses->list[LIST_PATHDIR], forward)))
  687. {
  688. insert_node_list(root, node->arg1, node->arg2, "0", "");
  689. root->update = root->used;
  690. }
  691. }
  692. else
  693. {
  694. if ((node = search_node_list(ses->list[LIST_PATHDIR], forward)))
  695. {
  696. insert_node_list(root, node->arg1, node->arg2, "0", "");
  697. }
  698. else
  699. {
  700. insert_node_list(root, forward, backward, "0", "");
  701. }
  702. }
  703. }
  704. DO_COMMAND(do_pathdir)
  705. {
  706. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
  707. struct listnode *node;
  708. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  709. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  710. arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
  711. if (*arg1 == 0)
  712. {
  713. show_list(ses->list[LIST_PATHDIR], 0);
  714. }
  715. else if (*arg2 == 0)
  716. {
  717. if (show_node_with_wild(ses, arg1, ses->list[LIST_PATHDIR]) == FALSE)
  718. {
  719. show_message(ses, LIST_PATHDIR, "#NO MATCH(ES) FOUND FOR {%s}.", arg1);
  720. }
  721. }
  722. else
  723. {
  724. if (*arg3 == 0)
  725. {
  726. if ((node = search_node_list(ses->list[LIST_PATHDIR], arg1)) != NULL)
  727. {
  728. strcpy(arg3, node->arg3);
  729. }
  730. else
  731. {
  732. strcpy(arg3, "0");
  733. }
  734. }
  735. else
  736. {
  737. if (!is_math(ses, arg3) || get_number(ses, arg3) < 0 || get_number(ses, arg3) >= 64)
  738. {
  739. show_message(ses, LIST_PATHDIR, "#PATHDIR: THE THIRD ARGUMENT MUST BE A NUMBER BETWEEN 0 and 63.");
  740. return ses;
  741. }
  742. get_number_string(ses, arg3, arg3);
  743. }
  744. update_node_list(ses->list[LIST_PATHDIR], arg1, arg2, arg3, "");
  745. show_message(ses, LIST_PATHDIR, "#OK: DIRECTION {%s} WILL BE REVERSED AS {%s} @ {%s}.", arg1, arg2, arg3);
  746. }
  747. return ses;
  748. }
  749. DO_COMMAND(do_unpathdir)
  750. {
  751. char arg1[BUFFER_SIZE];
  752. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  753. do
  754. {
  755. if (delete_nest_node(ses->list[LIST_PATHDIR], arg1))
  756. {
  757. show_message(ses, LIST_PATHDIR, "#OK. {%s} IS NO LONGER A PATHDIR.", arg1);
  758. }
  759. else
  760. {
  761. delete_node_with_wild(ses, LIST_PATHDIR, arg1);
  762. }
  763. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  764. }
  765. while (*arg1);
  766. return ses;
  767. }
  768. // Old commands, left for backward compatibility
  769. DO_PATH(path_new)
  770. {
  771. struct listroot *root = ses->list[LIST_PATH];
  772. if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  773. {
  774. show_message(ses, LIST_COMMAND, "#PATH NEW: YOU ARE ALREADY MAPPING A PATH.");
  775. }
  776. else
  777. {
  778. kill_list(root);
  779. root->update = 0;
  780. show_message(ses, LIST_COMMAND, "#PATH NEW: YOU ARE NOW MAPPING A PATH.");
  781. SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  782. }
  783. }
  784. DO_PATH(path_end)
  785. {
  786. if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  787. {
  788. show_message(ses, LIST_COMMAND, "#PATH END: YOU ARE NO LONGER MAPPING A PATH.");
  789. DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
  790. }
  791. else
  792. {
  793. show_message(ses, LIST_COMMAND, "#PATH: YOU ARE NOT MAPPING A PATH.");
  794. }
  795. }