runrobot.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. // Functions for running those robots during gameplay
  22. #include "profile.h"
  23. #include "error.h"
  24. #include "ezboard.h"
  25. #include "saveload.h"
  26. #include <stdio.h>
  27. #include "palette.h"
  28. #include "egacode.h"
  29. #include "intake.h"
  30. #include "edit.h"
  31. #include "random.h"
  32. #include "beep.h"
  33. #include "getkey.h"
  34. #include "graphics.h"
  35. #include "arrowkey.h"
  36. #include "scrdisp.h"
  37. #include "window.h"
  38. #include "sfx.h"
  39. extern int topindex,backindex;
  40. #include "mod.h"
  41. #include "idarray.h"
  42. #include "runrobot.h"
  43. #include "struct.h"
  44. #include "const.h"
  45. #include "data.h"
  46. #include "string.h"
  47. #include "counter.h"
  48. #include "game.h"
  49. #include "game2.h"
  50. #include "roballoc.h"
  51. #include <stdlib.h>
  52. #pragma warn -sig
  53. char far *item_to_counter[9]={
  54. "GEMS",
  55. "AMMO",
  56. "TIME",
  57. "SCORE",
  58. "HEALTH",
  59. "LIVES",
  60. "LOBOMBS",
  61. "HIBOMBS",
  62. "COINS" };
  63. // Send all robots or robot ID to default labels. For easy
  64. // interface to ASM. Label ids-
  65. //
  66. // 0=touch
  67. // 1=bombed
  68. // 2=invinco } automatically sent to "all"
  69. // 3=pushed
  70. // 4=playershot \
  71. // 5=neutralshot } if no find, try shot
  72. // 6=enemyshot /
  73. // 7=playerhit } automatically sent to "all"
  74. // 8=lazer
  75. // 9=spitfire
  76. //10=justloaded } automatically sent to "all"
  77. //11=justentered } automatically sent to "all"
  78. //12=touchgoop } automatically sent to "all"
  79. //13=playerhurt } automatically sent to "all"
  80. void send_robot_def(int robot_id,char mesg_id) {
  81. enter_func("send_robot_def");
  82. switch(mesg_id) {
  83. case 0:
  84. send_robot_id(robot_id,"TOUCH");
  85. break;
  86. case 1:
  87. send_robot_id(robot_id,"BOMBED");
  88. break;
  89. case 2:
  90. send_robot("ALL","INVINCO");
  91. break;
  92. case 3:
  93. send_robot_id(robot_id,"PUSHED");
  94. break;
  95. case 4:
  96. if(!send_robot_id(robot_id,"PLAYERSHOT")) break;
  97. shot:
  98. send_robot_id(robot_id,"SHOT");
  99. break;
  100. case 5:
  101. if(send_robot_id(robot_id,"NEUTRALSHOT")) goto shot;
  102. break;
  103. case 6:
  104. if(send_robot_id(robot_id,"ENEMYSHOT")) goto shot;
  105. break;
  106. case 7:
  107. send_robot("ALL","PLAYERHIT");
  108. break;
  109. case 8:
  110. send_robot_id(robot_id,"LAZER");
  111. break;
  112. case 9:
  113. send_robot_id(robot_id,"SPITFIRE");
  114. break;
  115. case 10:
  116. send_robot("ALL","JUSTLOADED");
  117. break;
  118. case 11:
  119. send_robot("ALL","JUSTENTERED");
  120. break;
  121. case 12:
  122. send_robot("ALL","GOOPTOUCHED");
  123. break;
  124. case 13:
  125. send_robot("ALL","PLAYERHURT");
  126. break;
  127. }
  128. exit_func();
  129. }
  130. void send_robot(char far *robot,char far *mesg,char ignore_lock) {
  131. int t1,t2,t3,t4,x,y;
  132. char under;
  133. enter_func("send_robot");
  134. if(!str_cmp(robot,"ALL")) {
  135. //Sent to all
  136. for(t1=1;t1<=NUM_ROBOTS;t1++)
  137. if(robots[t1].used)
  138. send_robot_id(t1,mesg,ignore_lock);
  139. }
  140. else {
  141. t1=1;
  142. do {
  143. if(!str_cmp(robot,robots[t1].robot_name))
  144. if(robots[t1].used)
  145. send_robot_id(t1,mesg,ignore_lock);
  146. } while(++t1<=NUM_ROBOTS);
  147. }
  148. //Sensors
  149. //Set t2 to cmd- 0-3 move, 4 die, 256+# char, 512+# color (hex)
  150. t2=-1;//No command yet
  151. //Check movement commands
  152. if(mesg[1]==0) {
  153. t1=mesg[0]; if((t1>='a')&&(t1<='z')) t1-=32;
  154. switch(t1) {
  155. case 'N': t2=0; break;
  156. case 'S': t2=1; break;
  157. case 'E': t2=2; break;
  158. case 'W': t2=3; break;
  159. }
  160. }
  161. //Die?
  162. if(!str_cmp("DIE",mesg)) t2=4;
  163. //Char___? (___ can be ### or 'c')
  164. t1=mesg[4];
  165. mesg[4]=0;
  166. if(!str_cmp("CHAR",mesg)) t2=256;
  167. mesg[4]=t1;
  168. //Color__? (__ is hex)
  169. t1=mesg[5];
  170. mesg[5]=0;
  171. if(!str_cmp("COLOR",mesg)) t2=512;
  172. mesg[5]=t1;
  173. //Get char/color value
  174. if(t2==256) {
  175. if(mesg[4]=='\'') t2+=(unsigned char)(mesg[5]);
  176. else t2+=(unsigned char)(atoi(&mesg[4])&255);
  177. }
  178. else if(t2==512) t2+=(unsigned char)strtol(&mesg[5],NULL,16);
  179. if(t2==-1) {
  180. exit_func();
  181. return;//Not a legal command
  182. }
  183. //Run the sensor cmd
  184. for(t1=1;t1<NUM_SENSORS;t1++) {
  185. if(sensors[t1].used) {
  186. if((!str_cmp(sensors[t1].sensor_name,robot))||
  187. (!str_cmp(robot,"ALL"))) {
  188. //Find sensor
  189. if((t2<256)||(t2>511)) {//Don't bother for a char cmd
  190. under=0;
  191. if(level_under_id[player_x+player_y*max_bxsiz]==122) {
  192. if(level_under_param[player_x+player_y*max_bxsiz]==t1) {
  193. under=1;
  194. x=player_x;
  195. y=player_y;
  196. goto gotit;
  197. }
  198. }
  199. for(x=0;x<board_xsiz;x++) {
  200. for(y=0;y<board_ysiz;y++) {
  201. t3=x+y*max_bxsiz;
  202. if((level_id[t3]==122)&&(level_param[t3]==t1)) goto gotit;
  203. }
  204. }
  205. continue;//??? Not found!
  206. }
  207. gotit:
  208. //Cmd
  209. switch(t2) {
  210. case 0:
  211. case 1:
  212. case 2:
  213. case 3:
  214. if(under) {
  215. //Attempt to move player, then if ok,
  216. //put sensor underneath and delete from
  217. //original space.
  218. t3=_move(x,y,t2,1|2|4|8|16);
  219. if(t3==0) {
  220. //Moved! Find player...
  221. find_player();
  222. goto player_met;
  223. }
  224. else //Sensorthud!
  225. send_robot(sensors[t1].robot_to_mesg,"SENSORTHUD");
  226. //Done.
  227. }
  228. else {
  229. //Attempt to move sensor.
  230. t3=_move(x,y,t2,1|2|4|8|16|128);
  231. if(t3==2) {
  232. step_sensor(t1);
  233. player_met:
  234. t4=player_x+player_y*max_bxsiz;
  235. //Met player- so put under player!
  236. under_player_id=level_under_id[t4];
  237. under_player_param=level_under_param[t4];
  238. under_player_color=level_under_color[t4];
  239. level_under_id[t4]=122;
  240. level_under_param[t4]=t1;
  241. level_under_color[t4]=level_color[x+y*max_bxsiz];
  242. id_remove_top(x,y);
  243. }
  244. else if(t3!=0) {
  245. //Sensorthud!
  246. send_robot(sensors[t1].robot_to_mesg,"SENSORTHUD");
  247. }
  248. //Done.
  249. }
  250. break;
  251. case 4:
  252. if(under) {
  253. id_remove_under(x,y);
  254. clear_sensor(t1);
  255. }
  256. else {
  257. id_remove_top(x,y);
  258. clear_sensor(t1);
  259. }
  260. break;
  261. default:
  262. if((t2>255)&&(t2<512)) sensors[t1].sensor_char=t2-256;
  263. else {
  264. if(under) level_under_color[x+y*max_bxsiz]=t2-512;
  265. else level_color[x+y*max_bxsiz]=t2-512;
  266. }
  267. break;
  268. }
  269. }
  270. }
  271. }
  272. //Done.
  273. exit_func();
  274. }
  275. char send_robot_id(int id,char far *mesg,char ignore_lock) {
  276. unsigned int t1=1;
  277. unsigned char far *robot;
  278. char mesgcopy[257];
  279. enter_func("send_robot_id");
  280. char temp=curr_rmem_status;
  281. if((robots[id].is_locked)&&(!ignore_lock)) {
  282. exit_func();
  283. return 1;//Locked
  284. }
  285. if(robots[id].program_length<3) {
  286. exit_func();
  287. return 2;//No program!
  288. }
  289. str_cpy(mesgcopy,mesg);
  290. prepare_robot_mem(id==NUM_ROBOTS);
  291. robot=&robot_mem[robots[id].program_location];
  292. // Are we going to a subroutine? Returning? - Exo
  293. if(mesgcopy[0] == '#')
  294. {
  295. char far *robot_begin = robot_mem + robots[id].program_location;
  296. // Is there a stack?
  297. if((robot_begin[2] == 107) && (robot_begin[4] == '#') &&
  298. robot_begin[3] > 4)
  299. {
  300. int stack_pos = (int)robot_begin[5];
  301. // Check if the stack position is unitialized (*)
  302. if(stack_pos == '*')
  303. {
  304. stack_pos = 0;
  305. }
  306. // returning?
  307. if((!str_cmp(mesgcopy, "#return")) && (stack_pos != 0))
  308. {
  309. // So return there... but the stack pos must NOT be 0...
  310. robots[id].cur_prog_line =
  311. *((int far *)(robot_begin + 6 + (stack_pos << 1)));
  312. robots[id].pos_within_line=0;
  313. robots[id].cycle_count=robots[id].robot_cycle-1;
  314. prepare_robot_mem(temp);
  315. if(robots[id].status==1) robots[id].status=2;
  316. // And decrease the stack pos.
  317. robot_begin[5] = (char)stack_pos - 1;
  318. exit_func();
  319. return(0); // "Yippee?" :p
  320. }
  321. else
  322. {
  323. // returning to the TOP?
  324. if((!str_cmp(mesgcopy, "#top")) && (stack_pos != 0))
  325. {
  326. // So return there... but the stack pos must NOT be 0...
  327. robots[id].cur_prog_line =
  328. *((int far *)(robot_begin + 6 + 2));
  329. robots[id].pos_within_line=0;
  330. robots[id].cycle_count=robots[id].robot_cycle-1;
  331. prepare_robot_mem(temp);
  332. if(robots[id].status==1) robots[id].status=2;
  333. // And reset the stack pos.
  334. robot_begin[5] = 0;
  335. exit_func();
  336. return(0); // "Yippee?" :p
  337. }
  338. else
  339. {
  340. // Sending.. well it'll continue with the jump, just has to
  341. // put the return address on the stack.
  342. // Stack must NOT be full though. What's the stack size? (robot_begin[3] - 3)/2.
  343. if(stack_pos != ((robot_begin[3] - 3) >> 1))
  344. {
  345. stack_pos++;
  346. // The return position is the NEXT command.
  347. *((int far *)(robot_begin + 6 + (stack_pos << 1))) =
  348. robots[id].cur_prog_line +
  349. *(robot_begin + robots[id].cur_prog_line) + 2;
  350. // Fix stack pos.
  351. robot_begin[5] = (char)stack_pos;
  352. // Continue.
  353. }
  354. }
  355. }
  356. }
  357. }
  358. do {
  359. if(robot[t1+1]==106) {
  360. //Label- is it so?
  361. if(!str_cmp(&robot[t1+3],mesgcopy)) {
  362. robots[id].cur_prog_line=t1;
  363. robots[id].pos_within_line=0;
  364. robots[id].cycle_count=robots[id].robot_cycle-1;
  365. prepare_robot_mem(temp);
  366. if(robots[id].status==1) robots[id].status=2;
  367. exit_func();
  368. return 0;//Yippe!
  369. }
  370. }
  371. next_cmd:
  372. t1+=robot[t1]+2;
  373. } while(robot[t1]);
  374. prepare_robot_mem(temp);
  375. exit_func();
  376. return 2;
  377. }
  378. char first_prefix=0;//1-3 normal 5-7 is 1-3 but from a REL FIRST cmd
  379. char mid_prefix=0;
  380. char last_prefix=0;//See first_prefix
  381. //Run a set of x/y pairs through the prefixes
  382. void prefix_xy(int&fx,int&fy,int&mx,int&my,int&lx,int&ly,int robotx,
  383. int roboty) {
  384. enter_func("prefix_xy");
  385. if(level_id[player_x+player_y*max_bxsiz]!=127) find_player();
  386. switch(first_prefix) {
  387. case 1:
  388. case 5:
  389. fx+=robotx;
  390. fy+=roboty;
  391. break;
  392. case 2:
  393. case 6:
  394. fx+=player_x;
  395. fy+=player_y;
  396. break;
  397. case 3:
  398. fx+=get_counter("FIRSTXPOS");
  399. fy+=get_counter("FIRSTYPOS");
  400. break;
  401. case 7:
  402. fx+=get_counter("XPOS");
  403. fy+=get_counter("YPOS");
  404. break;
  405. }
  406. switch(mid_prefix) {
  407. case 1:
  408. mx+=robotx;
  409. my+=roboty;
  410. break;
  411. case 2:
  412. mx+=player_x;
  413. my+=player_y;
  414. break;
  415. case 3:
  416. mx+=get_counter("XPOS");
  417. my+=get_counter("YPOS");
  418. break;
  419. }
  420. switch(last_prefix) {
  421. case 1:
  422. case 5:
  423. lx+=robotx;
  424. ly+=roboty;
  425. break;
  426. case 2:
  427. case 6:
  428. lx+=player_x;
  429. ly+=player_y;
  430. break;
  431. case 3:
  432. lx+=get_counter("LASTXPOS");
  433. ly+=get_counter("LASTYPOS");
  434. break;
  435. case 7:
  436. lx+=get_counter("XPOS");
  437. ly+=get_counter("YPOS");
  438. break;
  439. }
  440. if(fx<0) fx=0;
  441. if(fy<0) fy=0;
  442. if(mx<0) mx=0;
  443. if(my<0) my=0;
  444. if(lx<0) lx=0;
  445. if(ly<0) ly=0;
  446. if(fx>=board_xsiz) fx=board_xsiz-1;
  447. if(fy>=board_ysiz) fy=board_ysiz-1;
  448. if(mx>=board_xsiz) mx=board_xsiz-1;
  449. if(my>=board_ysiz) my=board_ysiz-1;
  450. if(lx>=board_xsiz) lx=board_xsiz-1;
  451. if(ly>=board_ysiz) ly=board_ysiz-1;
  452. exit_func();
  453. }
  454. //Move an x/y pair in a given direction. Returns non-0 if edge reached.
  455. char move_dir(int&x,int&y,char dir) {
  456. enter_func("move_dir");
  457. switch(dir) {
  458. case 0:
  459. if(y==0) {
  460. exit_func();
  461. return 1;
  462. }
  463. y--;
  464. break;
  465. case 1:
  466. if(y==board_ysiz-1) {
  467. exit_func();
  468. return 1;
  469. }
  470. y++;
  471. break;
  472. case 2:
  473. if(x==board_xsiz-1) {
  474. exit_func();
  475. return 1;
  476. }
  477. x++;
  478. break;
  479. case 3:
  480. if(x==0) {
  481. exit_func();
  482. return 1;
  483. }
  484. x--;
  485. break;
  486. }
  487. exit_func();
  488. return 0;
  489. }
  490. //Returns the numeric value pointed to OR the numeric value represented
  491. //by the counter string pointed to. (the ptr is at the param within the
  492. //command)
  493. //NOTE- CLIPS COUNTER NAMES!
  494. int parse_param(unsigned char far *robot,int id) {
  495. enter_func("parse_param");
  496. if(robot[0]==0) {//Numeric
  497. #ifdef PROFILE
  498. int t1=(int)robot[1]+(int)(robot[2]<<8);
  499. exit_func();
  500. return t1;
  501. #else
  502. return (int)robot[1]+(int)(robot[2]<<8);
  503. #endif
  504. }
  505. tr_msg(&robot[1],id,ibuff2);
  506. //String
  507. if(str_len(ibuff)>=COUNTER_NAME_SIZE)
  508. ibuff2[COUNTER_NAME_SIZE-1]=0;
  509. #ifdef PROFILE
  510. int t1=get_counter(ibuff2,id);
  511. exit_func();
  512. return t1;
  513. #else
  514. return get_counter(ibuff2,id);
  515. #endif
  516. }
  517. //Returns location of next parameter (pos is loc of current parameter)
  518. unsigned int next_param(unsigned char far *ptr,unsigned int pos) {
  519. return pos+(ptr[pos]?ptr[pos]:2)+1;
  520. }
  521. #define parsedir(a,b,c,d) parsedir(a,b,c,d,_bl[0],_bl[1],_bl[2],_bl[3])
  522. //Internal only. NOTE- IF WE EVER ALLOW ZAPPING OF LABELS NOT IN CURRENT
  523. //ROBOT, USE A COPY OF THE *LABEL BEFORE THE PREPARE_ROBOT_MEM!
  524. char restore_label(unsigned char far *robot,unsigned char far *label) {
  525. unsigned int t1=1,last=0;
  526. do {
  527. if(robot[t1+1]==108) {
  528. //Zapped Label- is it so?
  529. if(!str_cmp(&robot[t1+3],label))
  530. last=t1;
  531. }
  532. next_cmd:
  533. t1+=robot[t1]+2;
  534. } while(robot[t1]);
  535. if(!last) return 0;
  536. robot[last+1]=106;
  537. return 1;
  538. }
  539. char zap_label(unsigned char far *robot,unsigned char far *label) {
  540. unsigned int t1=1;
  541. do {
  542. if(robot[t1+1]==106) {
  543. //Zapped Label- is it so?
  544. if(!str_cmp(&robot[t1+3],label)) {
  545. robot[t1+1]=108;
  546. return 1;
  547. }
  548. }
  549. t1+=robot[t1]+2;
  550. } while(robot[t1]);
  551. return 0;
  552. }
  553. //Turns a color (including those w/??) to a real color (0-255)
  554. unsigned char fix_color(int color,unsigned char def) {
  555. if(color<256) return color;
  556. if(color<272) return (color&15)+(def&240);
  557. if(color<288) return ((color-272)<<4)+(def&15);
  558. return def;
  559. }
  560. void robot_box_display(unsigned char far *robot,int id,char far *label_storage) {
  561. //Important status vars (insert kept in intake.cpp)
  562. long pos=0,old_pos;//Where IN robot?
  563. int key;//Key
  564. int t1,t2;
  565. int old_keyb=curr_table;
  566. label_storage[0]=0;
  567. m_show();
  568. switch_keyb_table(1);
  569. //Draw screen
  570. save_screen(current_pg_seg);
  571. scroll_edging(4);
  572. //Write robot name
  573. if(!robots[id].robot_name[0]) write_string("Interaction",35,4,
  574. scroll_title_color,current_pg_seg);
  575. else write_string(robots[id].robot_name,40-str_len(robots[id].robot_name)/2,
  576. 4,scroll_title_color,current_pg_seg);
  577. //Scan section and mark all invalid counter-controlled options as codes
  578. //249.
  579. do {
  580. if(robot[pos+1]==249) robot[pos+1]=105;
  581. if(robot[pos+1]!=105) goto not_cco;
  582. t1=parse_param(&robot[pos+2],id);
  583. if(!t1) robot[pos+1]=249;
  584. not_cco:
  585. pos+=robot[pos]+2;
  586. } while(robot[pos]);
  587. pos=0;
  588. //Backwards
  589. do {
  590. if(robot[pos+1]==249) robot[pos+1]=105;
  591. if(robot[pos+1]!=105) goto not_cco2;
  592. t1=parse_param(&robot[pos+2],id);
  593. if(!t1) robot[pos+1]=249;
  594. not_cco2:
  595. if(robot[pos-1]==0xFF) break;
  596. pos-=robot[pos-1]+2;
  597. } while(1);
  598. pos=0;
  599. //Loop
  600. do {
  601. //Display scroll
  602. robot_frame(&robot[pos],id);
  603. key=getkey();
  604. old_pos=pos;
  605. switch(key) {
  606. case MOUSE_EVENT:
  607. //Move to line clicked on if mouse is in scroll, else exit
  608. if((mouse_event.cy>=6)&&(mouse_event.cy<=18)&&
  609. (mouse_event.cx>=8)&&(mouse_event.cx<=71)) {
  610. t2=mouse_event.cy-12;
  611. if(t2==0) goto select;
  612. //t2<0 = PGUP t2 lines
  613. //t2>0 = PGDN t2 lines
  614. if(t2<0) goto pgup;
  615. goto pgdn;
  616. }
  617. key=27;
  618. break;
  619. case -72://Up
  620. up_a_line:
  621. //Go back a line (if possible)
  622. if(robot[pos-1]==0xFF) break;//Can't.
  623. pos-=robot[pos-1]+2;
  624. t1=robot[pos+1];
  625. if((t1==106)||(t1==249)) goto up_a_line;
  626. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) pos=old_pos;
  627. //Done.
  628. break;
  629. case -80://Down
  630. down_a_line:
  631. //Go forward a line (if possible)
  632. pos+=robot[pos]+2;
  633. if(robot[pos]==0) pos=old_pos;
  634. else {
  635. t1=robot[pos+1];
  636. if((t1==106)||(t1==249)) goto down_a_line;
  637. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) pos=old_pos;
  638. }
  639. //Done.
  640. break;
  641. case 13://Enter
  642. select:
  643. if((robot[pos+1]!=104)&&(robot[pos+1]!=105)) {//No option
  644. key=27;
  645. break;
  646. }
  647. if(robot[pos+1]==105) t1=1+next_param(robot,pos+2);
  648. else t1=pos+3;
  649. //Goto option! Stores in label_storage
  650. str_cpy(label_storage,&robot[t1]);
  651. //Restore screen and exit
  652. restore_screen(current_pg_seg);
  653. switch_keyb_table(old_keyb);
  654. m_hide();
  655. return;
  656. case -81://Pagedown (by 6 lines)
  657. for(t2=6;t2>0;t2--) {
  658. pgdn:
  659. //Go forward a line (if possible)
  660. old_pos=pos;
  661. pgdn2:
  662. pos+=robot[pos]+2;
  663. if(robot[pos]==0) {
  664. pos=old_pos;
  665. break;
  666. }
  667. t1=robot[pos+1];
  668. if((t1==106)||(t1==249)) goto pgdn2;
  669. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) {
  670. pos=old_pos;
  671. break;
  672. }
  673. }
  674. break;
  675. case -73://Pageup (by 6 lines)
  676. for(t2=-6;t2<0;t2++) {
  677. pgup:
  678. //Go back a line (if possible)
  679. if(robot[pos-1]==0xFF) break;
  680. pos-=robot[pos-1]+2;
  681. t1=robot[pos+1];
  682. if((t1==106)||(t1==249)) goto pgup;
  683. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) {
  684. pos=old_pos;
  685. break;
  686. }
  687. }
  688. break;
  689. case -71://Home
  690. t2=-30000;
  691. goto pgup;
  692. case -79://End
  693. t2=30000;
  694. goto pgdn;
  695. default:
  696. beep();
  697. case 27:
  698. case 0:
  699. break;
  700. }
  701. //Continue?
  702. } while(key!=27);
  703. //Scan section and mark all invalid counter-controlled options as codes
  704. //105.
  705. pos=0;
  706. do {
  707. if(robot[pos+1]!=249) goto not_cco3;
  708. robot[pos+1]=105;
  709. not_cco3:
  710. pos+=robot[pos]+2;
  711. } while(robot[pos]);
  712. pos=0;
  713. //Backwards
  714. do {
  715. if(robot[pos+1]!=249) goto not_cco4;
  716. robot[pos+1]=105;
  717. not_cco4:
  718. if(robot[pos-1]==0xFF) break;
  719. pos-=robot[pos-1]+2;
  720. } while(1);
  721. //Restore screen and exit
  722. restore_screen(current_pg_seg);
  723. switch_keyb_table(old_keyb);
  724. m_hide();
  725. }
  726. void robot_frame(unsigned char far *robot,int id) {
  727. //Displays one frame of a robot. The scroll edging, arrows, and title
  728. //must already be shown. Simply prints each line. The pointer points
  729. //to the center line.
  730. int t1,t2,pos=0;
  731. int old_pos=pos;
  732. m_hide();
  733. //Display center line
  734. fill_line(64,8,12,32+(scroll_base_color<<8),current_pg_seg);
  735. display_robot_line(robot,12,id);
  736. //Display lines above center line
  737. for(t1=11;t1>=6;t1--) {
  738. fill_line(64,8,t1,32+(scroll_base_color<<8),current_pg_seg);
  739. //Go backward to previous line
  740. bk2:
  741. if(robot[pos-1]<0xFF) {
  742. pos-=robot[pos-1]+2;
  743. t2=robot[pos+1];
  744. if((t2==106)||(t2==249)) goto bk2;
  745. if(((t2<103)&&(t2!=47))||((t2>106)&&(t2<116))||(t2>117)) {
  746. pos+=robot[pos]+2;
  747. continue;
  748. }
  749. display_robot_line(&robot[pos],t1,id);
  750. }
  751. //Next line...
  752. }
  753. //Display lines below center line
  754. pos=old_pos;
  755. for(t1=13;t1<=18;t1++) {
  756. fill_line(64,8,t1,32+(scroll_base_color<<8),current_pg_seg);
  757. if(robot[pos]==0) continue;
  758. ps2:
  759. pos+=robot[pos]+2;
  760. t2=robot[pos+1];
  761. if((t2==106)||(t2==249)) goto ps2;
  762. if(((t2<103)&&(t2!=47))||((t2>106)&&(t2<116))||(t2>117)) {
  763. pos-=robot[pos-1]+2;
  764. continue;
  765. }
  766. if(robot[pos]) display_robot_line(&robot[pos],t1,id);
  767. //Next line...
  768. }
  769. m_show();
  770. }
  771. void display_robot_line(unsigned char far *robot,int y,int id) {
  772. int t1;
  773. switch(robot[1]) {
  774. case 103://Normal message
  775. tr_msg(&robot[3],id);
  776. ibuff[64]=0;//Clip
  777. write_string(ibuff,8,y,scroll_base_color,current_pg_seg);
  778. break;
  779. case 104://Option
  780. //Skip over label...
  781. t1=1+next_param(robot,2);//t1 is pos of string
  782. color_string(tr_msg(&robot[t1],id),10,y,scroll_base_color,current_pg_seg);
  783. draw_char('',scroll_arrow_color,8,y,current_pg_seg);
  784. break;
  785. case 105://Counter-based option
  786. //Check counter
  787. t1=parse_param(&robot[2],id);
  788. if(!t1) break;//Nothing
  789. //Skip over counter and label...
  790. t1=1+next_param(robot,next_param(robot,2));//t1 is pos of string
  791. color_string(tr_msg(&robot[t1],id),10,y,scroll_base_color,current_pg_seg);
  792. draw_char('',scroll_arrow_color,8,y,current_pg_seg);
  793. break;
  794. case 116://Colored message
  795. color_string(tr_msg(&robot[3],id),8,y,scroll_base_color,current_pg_seg);
  796. break;
  797. case 117://Centered message
  798. t1=str_len_color(tr_msg(&robot[3],id));
  799. t1=40-t1/2;
  800. color_string(ibuff,t1,y,scroll_base_color,current_pg_seg);
  801. break;
  802. }
  803. //Others, like 47 and 106, are blank lines
  804. }
  805. void push_sensor(int id) {
  806. send_robot(sensors[id].robot_to_mesg,"SENSORPUSHED");
  807. }
  808. void step_sensor(int id) {
  809. send_robot(sensors[id].robot_to_mesg,"SENSORON");
  810. }
  811. //Translates message at target to internal buffer, returning location
  812. //of this buffer. && becomes &, &INPUT& becomes the last input string,
  813. //and &COUNTER& becomes the value of COUNTER. The size of the string is
  814. //clipped to 80 chars.
  815. unsigned char ibuff[161];
  816. unsigned char ibuff2[161];//For another use of tr_msg (parse_param)
  817. unsigned char cnam[COUNTER_NAME_SIZE];
  818. unsigned char far *tr_msg(unsigned char far *orig_mesg,int id,
  819. unsigned char far *buffer) {
  820. int sp=0,dp=0,t1;
  821. enter_func("tr_msg");
  822. do {
  823. if(orig_mesg[sp]!='&') buffer[dp++]=orig_mesg[sp++];
  824. else {
  825. if(orig_mesg[++sp]=='&') {
  826. buffer[dp++]='&';
  827. sp++;
  828. }
  829. else {
  830. //Input or Counter?
  831. for(t1=0;t1<(COUNTER_NAME_SIZE-1);t1++) {
  832. cnam[t1]=orig_mesg[sp++];
  833. if(orig_mesg[sp]==0) break;
  834. if(orig_mesg[sp]=='&') {
  835. sp++;
  836. break;
  837. }
  838. }
  839. cnam[++t1]=0;
  840. if(!str_cmp(cnam,"INPUT")) {
  841. //Input
  842. str_cpy(&buffer[dp],input_string);
  843. dp+=str_len(input_string);
  844. }
  845. else {
  846. //Counter
  847. // Now could also be a string
  848. if(!strn_cmp(cnam, "$string", 7))
  849. {
  850. // Write the value of the counter name
  851. int index = cnam[7] + STRING_BASE;
  852. str_cpy(&buffer[dp], counters[index].counter_name);
  853. dp+=str_len(counters[index].counter_name);
  854. }
  855. else
  856. {
  857. // #(counter) is a hex representation.
  858. if(cnam[0] == '+')
  859. {
  860. sprintf(cnam, "%x", get_counter(cnam + 1, id));
  861. }
  862. else
  863. {
  864. if(cnam[0] == '#')
  865. {
  866. char temp[4];
  867. sprintf(temp, "%x", get_counter(cnam + 1, id));
  868. if(temp[1] == 0)
  869. {
  870. temp[2] = 0;
  871. temp[1] = temp[0];
  872. temp[0] = '0';
  873. }
  874. mem_cpy(cnam, temp, 4);
  875. }
  876. else
  877. {
  878. itoa(get_counter(cnam,id),cnam,10);
  879. }
  880. }
  881. str_cpy(&buffer[dp],cnam);
  882. dp+=str_len(cnam);
  883. }
  884. }
  885. }
  886. }
  887. if(dp>80) {
  888. dp=80;
  889. break;
  890. }
  891. } while(orig_mesg[sp]);
  892. buffer[dp]=0;
  893. exit_func();
  894. return buffer;
  895. }