path.c 21 KB

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