runrobot.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  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. do {
  293. if(robot[t1+1]==106) {
  294. //Label- is it so?
  295. if(!str_cmp(&robot[t1+3],mesgcopy)) {
  296. robots[id].cur_prog_line=t1;
  297. robots[id].pos_within_line=0;
  298. robots[id].cycle_count=robots[id].robot_cycle-1;
  299. prepare_robot_mem(temp);
  300. if(robots[id].status==1) robots[id].status=2;
  301. exit_func();
  302. return 0;//Yippe!
  303. }
  304. }
  305. next_cmd:
  306. t1+=robot[t1]+2;
  307. } while(robot[t1]);
  308. prepare_robot_mem(temp);
  309. exit_func();
  310. return 2;
  311. }
  312. char first_prefix=0;//1-3 normal 5-7 is 1-3 but from a REL FIRST cmd
  313. char mid_prefix=0;
  314. char last_prefix=0;//See first_prefix
  315. //Run a set of x/y pairs through the prefixes
  316. void prefix_xy(int&fx,int&fy,int&mx,int&my,int&lx,int&ly,int robotx,
  317. int roboty) {
  318. enter_func("prefix_xy");
  319. if(level_id[player_x+player_y*max_bxsiz]!=127) find_player();
  320. switch(first_prefix) {
  321. case 1:
  322. case 5:
  323. fx+=robotx;
  324. fy+=roboty;
  325. break;
  326. case 2:
  327. case 6:
  328. fx+=player_x;
  329. fy+=player_y;
  330. break;
  331. case 3:
  332. fx+=get_counter("FIRSTXPOS");
  333. fy+=get_counter("FIRSTYPOS");
  334. break;
  335. case 7:
  336. fx+=get_counter("XPOS");
  337. fy+=get_counter("YPOS");
  338. break;
  339. }
  340. switch(mid_prefix) {
  341. case 1:
  342. mx+=robotx;
  343. my+=roboty;
  344. break;
  345. case 2:
  346. mx+=player_x;
  347. my+=player_y;
  348. break;
  349. case 3:
  350. mx+=get_counter("XPOS");
  351. my+=get_counter("YPOS");
  352. break;
  353. }
  354. switch(last_prefix) {
  355. case 1:
  356. case 5:
  357. lx+=robotx;
  358. ly+=roboty;
  359. break;
  360. case 2:
  361. case 6:
  362. lx+=player_x;
  363. ly+=player_y;
  364. break;
  365. case 3:
  366. lx+=get_counter("LASTXPOS");
  367. ly+=get_counter("LASTYPOS");
  368. break;
  369. case 7:
  370. lx+=get_counter("XPOS");
  371. ly+=get_counter("YPOS");
  372. break;
  373. }
  374. if(fx<0) fx=0;
  375. if(fy<0) fy=0;
  376. if(mx<0) mx=0;
  377. if(my<0) my=0;
  378. if(lx<0) lx=0;
  379. if(ly<0) ly=0;
  380. if(fx>=board_xsiz) fx=board_xsiz-1;
  381. if(fy>=board_ysiz) fy=board_ysiz-1;
  382. if(mx>=board_xsiz) mx=board_xsiz-1;
  383. if(my>=board_ysiz) my=board_ysiz-1;
  384. if(lx>=board_xsiz) lx=board_xsiz-1;
  385. if(ly>=board_ysiz) ly=board_ysiz-1;
  386. exit_func();
  387. }
  388. //Move an x/y pair in a given direction. Returns non-0 if edge reached.
  389. char move_dir(int&x,int&y,char dir) {
  390. enter_func("move_dir");
  391. switch(dir) {
  392. case 0:
  393. if(y==0) {
  394. exit_func();
  395. return 1;
  396. }
  397. y--;
  398. break;
  399. case 1:
  400. if(y==board_ysiz-1) {
  401. exit_func();
  402. return 1;
  403. }
  404. y++;
  405. break;
  406. case 2:
  407. if(x==board_xsiz-1) {
  408. exit_func();
  409. return 1;
  410. }
  411. x++;
  412. break;
  413. case 3:
  414. if(x==0) {
  415. exit_func();
  416. return 1;
  417. }
  418. x--;
  419. break;
  420. }
  421. exit_func();
  422. return 0;
  423. }
  424. //Returns the numeric value pointed to OR the numeric value represented
  425. //by the counter string pointed to. (the ptr is at the param within the
  426. //command)
  427. //NOTE- CLIPS COUNTER NAMES!
  428. int parse_param(unsigned char far *robot,int id) {
  429. enter_func("parse_param");
  430. if(robot[0]==0) {//Numeric
  431. #ifdef PROFILE
  432. int t1=(int)robot[1]+(int)(robot[2]<<8);
  433. exit_func();
  434. return t1;
  435. #else
  436. return (int)robot[1]+(int)(robot[2]<<8);
  437. #endif
  438. }
  439. tr_msg(&robot[1],id,ibuff2);
  440. //String
  441. if(str_len(ibuff)>=COUNTER_NAME_SIZE)
  442. ibuff2[COUNTER_NAME_SIZE-1]=0;
  443. #ifdef PROFILE
  444. int t1=get_counter(ibuff2,id);
  445. exit_func();
  446. return t1;
  447. #else
  448. return get_counter(ibuff2,id);
  449. #endif
  450. }
  451. //Returns location of next parameter (pos is loc of current parameter)
  452. unsigned int next_param(unsigned char far *ptr,unsigned int pos) {
  453. return pos+(ptr[pos]?ptr[pos]:2)+1;
  454. }
  455. #define parsedir(a,b,c,d) parsedir(a,b,c,d,_bl[0],_bl[1],_bl[2],_bl[3])
  456. //Internal only. NOTE- IF WE EVER ALLOW ZAPPING OF LABELS NOT IN CURRENT
  457. //ROBOT, USE A COPY OF THE *LABEL BEFORE THE PREPARE_ROBOT_MEM!
  458. char restore_label(unsigned char far *robot,unsigned char far *label) {
  459. unsigned int t1=1,last=0;
  460. do {
  461. if(robot[t1+1]==108) {
  462. //Zapped Label- is it so?
  463. if(!str_cmp(&robot[t1+3],label))
  464. last=t1;
  465. }
  466. next_cmd:
  467. t1+=robot[t1]+2;
  468. } while(robot[t1]);
  469. if(!last) return 0;
  470. robot[last+1]=106;
  471. return 1;
  472. }
  473. char zap_label(unsigned char far *robot,unsigned char far *label) {
  474. unsigned int t1=1;
  475. do {
  476. if(robot[t1+1]==106) {
  477. //Zapped Label- is it so?
  478. if(!str_cmp(&robot[t1+3],label)) {
  479. robot[t1+1]=108;
  480. return 1;
  481. }
  482. }
  483. t1+=robot[t1]+2;
  484. } while(robot[t1]);
  485. return 0;
  486. }
  487. //Turns a color (including those w/??) to a real color (0-255)
  488. unsigned char fix_color(int color,unsigned char def) {
  489. if(color<256) return color;
  490. if(color<272) return (color&15)+(def&240);
  491. if(color<288) return ((color-272)<<4)+(def&15);
  492. return def;
  493. }
  494. void robot_box_display(unsigned char far *robot,int id,char far *label_storage) {
  495. //Important status vars (insert kept in intake.cpp)
  496. long pos=0,old_pos;//Where IN robot?
  497. int key;//Key
  498. int t1,t2;
  499. int old_keyb=curr_table;
  500. label_storage[0]=0;
  501. m_show();
  502. switch_keyb_table(1);
  503. //Draw screen
  504. save_screen(current_pg_seg);
  505. scroll_edging(4);
  506. //Write robot name
  507. if(!robots[id].robot_name[0]) write_string("Interaction",35,4,
  508. scroll_title_color,current_pg_seg);
  509. else write_string(robots[id].robot_name,40-str_len(robots[id].robot_name)/2,
  510. 4,scroll_title_color,current_pg_seg);
  511. //Scan section and mark all invalid counter-controlled options as codes
  512. //249.
  513. do {
  514. if(robot[pos+1]==249) robot[pos+1]=105;
  515. if(robot[pos+1]!=105) goto not_cco;
  516. t1=parse_param(&robot[pos+2],id);
  517. if(!t1) robot[pos+1]=249;
  518. not_cco:
  519. pos+=robot[pos]+2;
  520. } while(robot[pos]);
  521. pos=0;
  522. //Backwards
  523. do {
  524. if(robot[pos+1]==249) robot[pos+1]=105;
  525. if(robot[pos+1]!=105) goto not_cco2;
  526. t1=parse_param(&robot[pos+2],id);
  527. if(!t1) robot[pos+1]=249;
  528. not_cco2:
  529. if(robot[pos-1]==0xFF) break;
  530. pos-=robot[pos-1]+2;
  531. } while(1);
  532. pos=0;
  533. //Loop
  534. do {
  535. //Display scroll
  536. robot_frame(&robot[pos],id);
  537. key=getkey();
  538. old_pos=pos;
  539. switch(key) {
  540. case MOUSE_EVENT:
  541. //Move to line clicked on if mouse is in scroll, else exit
  542. if((mouse_event.cy>=6)&&(mouse_event.cy<=18)&&
  543. (mouse_event.cx>=8)&&(mouse_event.cx<=71)) {
  544. t2=mouse_event.cy-12;
  545. if(t2==0) goto select;
  546. //t2<0 = PGUP t2 lines
  547. //t2>0 = PGDN t2 lines
  548. if(t2<0) goto pgup;
  549. goto pgdn;
  550. }
  551. key=27;
  552. break;
  553. case -72://Up
  554. up_a_line:
  555. //Go back a line (if possible)
  556. if(robot[pos-1]==0xFF) break;//Can't.
  557. pos-=robot[pos-1]+2;
  558. t1=robot[pos+1];
  559. if((t1==106)||(t1==249)) goto up_a_line;
  560. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) pos=old_pos;
  561. //Done.
  562. break;
  563. case -80://Down
  564. down_a_line:
  565. //Go forward a line (if possible)
  566. pos+=robot[pos]+2;
  567. if(robot[pos]==0) pos=old_pos;
  568. else {
  569. t1=robot[pos+1];
  570. if((t1==106)||(t1==249)) goto down_a_line;
  571. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) pos=old_pos;
  572. }
  573. //Done.
  574. break;
  575. case 13://Enter
  576. select:
  577. if((robot[pos+1]!=104)&&(robot[pos+1]!=105)) {//No option
  578. key=27;
  579. break;
  580. }
  581. if(robot[pos+1]==105) t1=1+next_param(robot,pos+2);
  582. else t1=pos+3;
  583. //Goto option! Stores in label_storage
  584. str_cpy(label_storage,&robot[t1]);
  585. //Restore screen and exit
  586. restore_screen(current_pg_seg);
  587. switch_keyb_table(old_keyb);
  588. m_hide();
  589. return;
  590. case -81://Pagedown (by 6 lines)
  591. for(t2=6;t2>0;t2--) {
  592. pgdn:
  593. //Go forward a line (if possible)
  594. old_pos=pos;
  595. pgdn2:
  596. pos+=robot[pos]+2;
  597. if(robot[pos]==0) {
  598. pos=old_pos;
  599. break;
  600. }
  601. t1=robot[pos+1];
  602. if((t1==106)||(t1==249)) goto pgdn2;
  603. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) {
  604. pos=old_pos;
  605. break;
  606. }
  607. }
  608. break;
  609. case -73://Pageup (by 6 lines)
  610. for(t2=-6;t2<0;t2++) {
  611. pgup:
  612. //Go back a line (if possible)
  613. if(robot[pos-1]==0xFF) break;
  614. pos-=robot[pos-1]+2;
  615. t1=robot[pos+1];
  616. if((t1==106)||(t1==249)) goto pgup;
  617. if(((t1<103)&&(t1!=47))||((t1>106)&&(t1<116))||(t1>117)) {
  618. pos=old_pos;
  619. break;
  620. }
  621. }
  622. break;
  623. case -71://Home
  624. t2=-30000;
  625. goto pgup;
  626. case -79://End
  627. t2=30000;
  628. goto pgdn;
  629. default:
  630. beep();
  631. case 27:
  632. case 0:
  633. break;
  634. }
  635. //Continue?
  636. } while(key!=27);
  637. //Scan section and mark all invalid counter-controlled options as codes
  638. //105.
  639. pos=0;
  640. do {
  641. if(robot[pos+1]!=249) goto not_cco3;
  642. robot[pos+1]=105;
  643. not_cco3:
  644. pos+=robot[pos]+2;
  645. } while(robot[pos]);
  646. pos=0;
  647. //Backwards
  648. do {
  649. if(robot[pos+1]!=249) goto not_cco4;
  650. robot[pos+1]=105;
  651. not_cco4:
  652. if(robot[pos-1]==0xFF) break;
  653. pos-=robot[pos-1]+2;
  654. } while(1);
  655. //Restore screen and exit
  656. restore_screen(current_pg_seg);
  657. switch_keyb_table(old_keyb);
  658. m_hide();
  659. }
  660. void robot_frame(unsigned char far *robot,int id) {
  661. //Displays one frame of a robot. The scroll edging, arrows, and title
  662. //must already be shown. Simply prints each line. The pointer points
  663. //to the center line.
  664. int t1,t2,pos=0;
  665. int old_pos=pos;
  666. m_hide();
  667. //Display center line
  668. fill_line(64,8,12,32+(scroll_base_color<<8),current_pg_seg);
  669. display_robot_line(robot,12,id);
  670. //Display lines above center line
  671. for(t1=11;t1>=6;t1--) {
  672. fill_line(64,8,t1,32+(scroll_base_color<<8),current_pg_seg);
  673. //Go backward to previous line
  674. bk2:
  675. if(robot[pos-1]<0xFF) {
  676. pos-=robot[pos-1]+2;
  677. t2=robot[pos+1];
  678. if((t2==106)||(t2==249)) goto bk2;
  679. if(((t2<103)&&(t2!=47))||((t2>106)&&(t2<116))||(t2>117)) {
  680. pos+=robot[pos]+2;
  681. continue;
  682. }
  683. display_robot_line(&robot[pos],t1,id);
  684. }
  685. //Next line...
  686. }
  687. //Display lines below center line
  688. pos=old_pos;
  689. for(t1=13;t1<=18;t1++) {
  690. fill_line(64,8,t1,32+(scroll_base_color<<8),current_pg_seg);
  691. if(robot[pos]==0) continue;
  692. ps2:
  693. pos+=robot[pos]+2;
  694. t2=robot[pos+1];
  695. if((t2==106)||(t2==249)) goto ps2;
  696. if(((t2<103)&&(t2!=47))||((t2>106)&&(t2<116))||(t2>117)) {
  697. pos-=robot[pos-1]+2;
  698. continue;
  699. }
  700. if(robot[pos]) display_robot_line(&robot[pos],t1,id);
  701. //Next line...
  702. }
  703. m_show();
  704. }
  705. void display_robot_line(unsigned char far *robot,int y,int id) {
  706. int t1;
  707. switch(robot[1]) {
  708. case 103://Normal message
  709. tr_msg(&robot[3],id);
  710. ibuff[64]=0;//Clip
  711. write_string(ibuff,8,y,scroll_base_color,current_pg_seg);
  712. break;
  713. case 104://Option
  714. //Skip over label...
  715. t1=1+next_param(robot,2);//t1 is pos of string
  716. color_string(tr_msg(&robot[t1],id),10,y,scroll_base_color,current_pg_seg);
  717. draw_char('',scroll_arrow_color,8,y,current_pg_seg);
  718. break;
  719. case 105://Counter-based option
  720. //Check counter
  721. t1=parse_param(&robot[2],id);
  722. if(!t1) break;//Nothing
  723. //Skip over counter and label...
  724. t1=1+next_param(robot,next_param(robot,2));//t1 is pos of string
  725. color_string(tr_msg(&robot[t1],id),10,y,scroll_base_color,current_pg_seg);
  726. draw_char('',scroll_arrow_color,8,y,current_pg_seg);
  727. break;
  728. case 116://Colored message
  729. color_string(tr_msg(&robot[3],id),8,y,scroll_base_color,current_pg_seg);
  730. break;
  731. case 117://Centered message
  732. t1=str_len_color(tr_msg(&robot[3],id));
  733. t1=40-t1/2;
  734. color_string(ibuff,t1,y,scroll_base_color,current_pg_seg);
  735. break;
  736. }
  737. //Others, like 47 and 106, are blank lines
  738. }
  739. void push_sensor(int id) {
  740. send_robot(sensors[id].robot_to_mesg,"SENSORPUSHED");
  741. }
  742. void step_sensor(int id) {
  743. send_robot(sensors[id].robot_to_mesg,"SENSORON");
  744. }
  745. //Translates message at target to internal buffer, returning location
  746. //of this buffer. && becomes &, &INPUT& becomes the last input string,
  747. //and &COUNTER& becomes the value of COUNTER. The size of the string is
  748. //clipped to 80 chars.
  749. unsigned char ibuff[161];
  750. unsigned char ibuff2[161];//For another use of tr_msg (parse_param)
  751. unsigned char cnam[COUNTER_NAME_SIZE];
  752. unsigned char far *tr_msg(unsigned char far *orig_mesg,int id,
  753. unsigned char far *buffer) {
  754. int sp=0,dp=0,t1;
  755. enter_func("tr_msg");
  756. do {
  757. if(orig_mesg[sp]!='&') buffer[dp++]=orig_mesg[sp++];
  758. else {
  759. if(orig_mesg[++sp]=='&') {
  760. buffer[dp++]='&';
  761. sp++;
  762. }
  763. else {
  764. //Input or Counter?
  765. for(t1=0;t1<(COUNTER_NAME_SIZE-1);t1++) {
  766. cnam[t1]=orig_mesg[sp++];
  767. if(orig_mesg[sp]==0) break;
  768. if(orig_mesg[sp]=='&') {
  769. sp++;
  770. break;
  771. }
  772. }
  773. cnam[++t1]=0;
  774. if(!str_cmp(cnam,"INPUT")) {
  775. //Input
  776. str_cpy(&buffer[dp],input_string);
  777. dp+=str_len(input_string);
  778. }
  779. else {
  780. //Counter
  781. itoa(get_counter(cnam,id),cnam,10);
  782. str_cpy(&buffer[dp],cnam);
  783. dp+=str_len(cnam);
  784. }
  785. }
  786. }
  787. if(dp>80) {
  788. dp=80;
  789. break;
  790. }
  791. } while(orig_mesg[sp]);
  792. buffer[dp]=0;
  793. exit_func();
  794. return buffer;
  795. }