aboutsummaryrefslogtreecommitdiff
path: root/engines/avalanche/trip5.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/avalanche/trip5.cpp')
-rw-r--r--engines/avalanche/trip5.cpp1888
1 files changed, 1888 insertions, 0 deletions
diff --git a/engines/avalanche/trip5.cpp b/engines/avalanche/trip5.cpp
new file mode 100644
index 0000000000..3674b1ffd7
--- /dev/null
+++ b/engines/avalanche/trip5.cpp
@@ -0,0 +1,1888 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ TRIP5 Trippancy V */
+
+#define __trip5_implementation__
+ /* Trippancy V */ /* Define NOASM to use Pascal instead of asm. */
+/*$S- Fast!*/
+#include "trip5.h"
+
+
+/*#include "Scrolls.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Dropdown.h"*/
+/*#include "Visa.h"*/
+/*#include "Celer.h"*/
+/*#include "Timeout.h"*/
+/*#include "Sequence.h"*/
+/*#include "Enid.h"*/
+
+
+void loadtrip()
+{
+ byte gm;
+
+ for( gm=1; gm <= numtr; gm ++) tr[gm].original();
+ fillchar(aa,sizeof(aa),'\0');
+}
+
+byte checkfeet(integer x1,integer x2,integer oy,integer y, byte yl)
+{
+ byte a,c; integer fv,ff;
+
+/* if not alive then begin checkfeet:=0; exit; end;*/
+ byte checkfeet_result;
+ a=0; setactivepage(2); if (x1<0) x1=0; if (x2>639) x2=639;
+ if (oy<y)
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=oy+yl; ff <= y+yl; ff ++)
+ {
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ } else
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=y+yl; ff <= oy+yl; ff ++)
+ {
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ }
+ checkfeet_result=a; setactivepage(1-cp);
+ return checkfeet_result;
+}
+
+byte geida_ped(byte which)
+{
+ byte geida_ped_result;
+ switch (which) {
+ case 1: geida_ped_result= 7; break;
+ case 2:case 6: geida_ped_result= 8; break;
+ case 3:case 5: geida_ped_result= 9; break;
+ case 4: geida_ped_result=10; break;
+ }
+ return geida_ped_result;
+}
+
+void catamove(byte ped)
+ /* When you enter a new position in the catacombs, this procedure should
+ be called. It changes the Also codes so that they may match the picture
+ on the screen. (Coming soon: It draws up the screen, too.) */
+{
+ longint here;
+ word xy_word;
+ byte fv,ff;
+
+/* XY_word is cat_x+cat_y*256. Thus, every room in the
+ catacombs has a different number for it. */
+
+
+ {
+ xy_word=cat_x+cat_y*256;
+ geida_spin=0;
+ }
+ switch (xy_word) {
+ case 1801: { /* Exit catacombs */
+ fliproom(r__lustiesroom,4);
+ display("Phew! Nice to be out of there!");
+ return;
+ }
+ break;
+ case 1033: { /* Oubliette */
+ fliproom(r__oubliette,1);
+ display("Oh, NO!\231\2");
+ return;
+ }
+ break;
+ case 4: {
+ fliproom(r__geidas,1);
+ return;
+ }
+ break;
+ case 2307: {
+ fliproom(r__lusties,5);
+ display("Oh no... here we go again...");
+ dna.user_moves_avvy=false;
+ tr[1].iy=1; tr[1].ix=0;
+ return;
+ }
+ break;
+ }
+
+ if (~ dna.enter_catacombs_from_lusties_room) load(29);
+ here=catamap[cat_y][cat_x];
+
+ switch (here & 0xf) { /* West. */
+ case 0: { /* no connection (wall) */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* Door. */
+ show_one(28);
+ }
+ break;
+ case 0x1: { /* no connection (wall + shield), */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(29); /* ...shield. */
+ }
+ break;
+ case 0x2: { /* wall with door */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door. */
+ }
+ break;
+ case 0x3: { /* wall with door and shield */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door, and... */
+ show_one(29); /* ...shield. */
+ }
+ break;
+ case 0x4: { /* no connection (wall + window), */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(5); /* ...window. */
+ }
+ break;
+ case 0x5: { /* wall with door and window */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door, and... */
+ show_one(5); /* ...window. */
+ }
+ break;
+ case 0x6: { /* no connection (wall + torches), */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* No door. */
+ show_one(28); /* Wall, plus... */
+ show_one(7); /* ...torches. */
+ }
+ break;
+ case 0x7: { /* wall with door and torches */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door, and... */
+ show_one(7); /* ...torches. */
+ }
+ break;
+ case 0xf: { /* straight-through corridor. */
+ magics[2].op=nix; /* Sloping wall. */
+ magics[3].op=special; /* Straight wall. */
+ }
+ break;
+ }
+
+ /* ---- */
+
+ switch ((cardinal)(here & 0xf0) >> 4) { /* East */
+ case 0: { /* no connection (wall) */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=nix; /* Door. */
+ show_one(19);
+ }
+ break;
+ case 0x1: { /* no connection (wall + window), */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=nix; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(20); /* ...window. */
+ }
+ break;
+ case 0x2: { /* wall with door */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=special; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(21); /* ...door. */
+ }
+ break;
+ case 0x3: { /* wall with door and window */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=special; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(20); /* ...door, and... */
+ show_one(21); /* ...window. */
+ }
+ break;
+ case 0x6: { /* no connection (wall + torches), */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=nix; /* No door. */
+ show_one(19); /* Wall, plus... */
+ show_one(18); /* ...torches. */
+ }
+ break;
+ case 0x7: { /* wall with door and torches */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=special; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(21); /* ...door, and... */
+ show_one(18); /* ...torches. */
+ }
+ break;
+ case 0xf: { /* straight-through corridor. */
+ magics[5].op=nix; /* Sloping wall. */
+ magics[6].op=special; /* Straight wall. */
+ portals[15].op=nix; /* Door. */
+ }
+ break;
+ }
+
+ /* ---- */
+
+ switch ((cardinal)(here & 0xf00) >> 8) { /* South */
+ case 0: { /* No connection. */
+ magics[7].op=bounces;
+ magics[12].op=bounces;
+ magics[13].op=bounces;
+ }
+ break;
+ case 0x1: {
+ show_one(22);
+ { void& with = magics[13];
+ if ((xy_word==2051) & (dna.geida_follows))
+ op=exclaim;
+ else op=special;} /* Right exit south. */
+ magics[7].op=bounces;
+ magics[12].op=bounces;
+ }
+ break;
+ case 0x2: {
+ show_one(23);
+ magics[7].op=special; /* Middle exit south. */
+ magics[12].op=bounces;
+ magics[13].op=bounces;
+ }
+ break;
+ case 0x3: {
+ show_one(24);
+ magics[12].op=special; /* Left exit south. */
+ magics[7].op=bounces;
+ magics[13].op=bounces;
+ }
+ break;
+ }
+
+ switch ((cardinal)(here & 0xf000) >> 12) { /* North */
+ case 0: { /* No connection */
+ magics[1].op=bounces;
+ portals[12].op=nix; /* Door. */
+ }
+ break;
+ /* LEFT handles: */
+/* $1: begin
+ show_one(4);
+ magics[1].op:=bounces; { Left exit north. } { Change magic number! }
+ portals[12].op:=special; { Door. }
+ end;*/
+ case 0x2: {
+ show_one(4);
+ magics[1].op=bounces; /* Middle exit north. */
+ portals[12].op=special; /* Door. */
+ }
+ break;
+/* $3: begin
+ show_one(4);
+ magics[1].op:=bounces; { Right exit north. } { Change magic number! }
+ portals[12].op:=special; { Door. }
+ end;
+ { RIGHT handles: }
+ $4: begin
+ show_one(3);
+ magics[1].op:=bounces; { Left exit north. } { Change magic number! }
+ portals[12].op:=special; { Door. }
+ end;*/
+ case 0x5: {
+ show_one(3);
+ magics[1].op=bounces; /* Middle exit north. */
+ portals[12].op=special; /* Door. */
+ }
+ break;
+/* $6: begin
+ show_one(3);
+ magics[1].op:=bounces; { Right exit north. }
+ portals[12].op:=special; { Door. }
+ end;*/
+ /* ARCHWAYS: */
+ case 0x7:case 0x8:case 0x9: {
+ show_one(6);
+
+ if (((cardinal)(here & 0xf000) >> 12)>0x7) show_one(31);
+ if (((cardinal)(here & 0xf000) >> 12)==0x9) show_one(32);
+
+ magics[1].op=special; /* Middle arch north. */
+ portals[12].op=nix; /* Door. */
+ }
+ break;
+ /* DECORATIONS: */
+ case 0xd: { /* No connection + WINDOW */
+ magics[1].op=bounces;
+ portals[12].op=nix; /* Door. */
+ show_one(14);
+ }
+ break;
+ case 0xe: { /* No connection + TORCH */
+ magics[1].op=bounces;
+ portals[12].op=nix; /* Door. */
+ show_one(8);
+ }
+ break;
+ /* Recessed door: */
+ case 0xf: {
+ magics[1].op=nix; /* Door to Geida's room. */
+ show_one(1);
+ portals[12].op=special; /* Door. */
+ }
+ break;
+ }
+
+ switch (xy_word) {
+ case 514: show_one(17); break; /* [2,2] : "Art Gallery" sign over door. */
+ case 264: show_one(9); break; /* [8,1] : "The Wrong Way!" sign. */
+ case 1797: show_one(2); break; /* [5,7] : "Ite Mingite" sign. */
+ case 258: for( fv=0; fv <= 2; fv ++) /* [2,1] : Art gallery - pictures */
+ {
+ show_one_at(15,130+fv*120,70);
+ show_one_at(16,184+fv*120,78);
+ }
+ break;
+ case 1287: for( fv=10; fv <= 13; fv ++) show_one(fv); break; /* [7,5] : 4 candles. */
+ case 776: show_one(10); break; /* [8,3] : 1 candle. */
+ case 2049: show_one(11); break; /* [1,8] : another candle. */
+ case 257: { show_one(12); show_one(13); } break; /* [1,1] : the other two. */
+ }
+
+ if ((dna.geida_follows) & (ped>0))
+ {
+ triptype& with = tr[2];
+
+ if (! with.quick) /* If we don't already have her... */
+ tr[2].init(5,true); /* ...Load Geida. */
+ apped(2,geida_ped(ped));
+ tr[2].call_eachstep =true;
+ tr[2].eachstep=procgeida_procs;
+ }
+}
+
+void call_special(word which);
+
+ /* This proc gets called whenever you touch a line defined as Special. */
+static void dawndelay()
+ { set_up_timer(2,procdawn_delay,reason_dawndelay); }
+
+void call_special(word which)
+{
+ switch (which) {
+ case 1: { /* Special 1: Room 22: top of stairs. */
+ show_one(1);
+ dna.brummie_stairs=1;
+ magics[10].op=nix;
+ set_up_timer(10,procstairs,reason_brummiestairs);
+ stopwalking();
+ dna.user_moves_avvy=false;
+ }
+ break;
+ case 2: { /* Special 2: Room 22: bottom of stairs. */
+ dna.brummie_stairs=3;
+ magics[11].op=nix;
+ magics[12].op=exclaim;
+ magics[12].data=5;
+ magics[4].op=bounces; /* Now works as planned! */
+ stopwalking();
+ dixi('q',26);
+ dna.user_moves_avvy=true;
+ }
+ break;
+ case 3: { /* Special 3: Room 71: triggers dart. */
+ tr[1].bounce(); /* Must include that. */
+
+ if (~ dna.arrow_triggered)
+ {
+ dna.arrow_triggered=true;
+ apped(2,4); /* The dart starts at ped 4, and... */
+ tr[2].walkto(5); /* flies to ped 5. */
+ tr[2].face=0; /* Only face. */
+ /* Should call some kind of Eachstep procedure which will deallocate
+ the sprite when it hits the wall, and replace it with the chunk
+ graphic of the arrow buried in the plaster. */
+ /* OK! */
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procarrow_procs;
+ }
+ }
+ break;
+
+ case 4: { /* This is the ghost room link. */
+ dusk;
+ tr[1].turn(right); /* you'll see this after we get back from bootstrap */
+ set_up_timer(1,procghost_room_phew,reason_ghost_room_phew);
+ back_to_bootstrap(3);
+ }
+ break;
+
+ case 5: if (dna.friar_will_tie_you_up)
+ { /* Special 5: Room 42: touched tree, and get tied up. */
+ magics[4].op=bounces; /* Boundary effect is now working again. */
+ dixi('q',35);
+ tr[1].done();
+ /*tr[1].vanishifstill:=true;*/
+ show_one(2);
+ dixi('q',36);
+ dna.tied_up=true;
+ dna.friar_will_tie_you_up=false;
+ tr[2].walkto(3);
+ tr[2].vanishifstill=true;
+ tr[2].check_me=true; /* One of them must have Check_Me switched on. */
+ whereis[pfriartuck]=177; /* Not here, then. */
+ set_up_timer(364,prochang_around,reason_hanging_around);
+ }
+ break;
+
+ case 6: { /* Special 6: fall down oubliette. */
+ dna.user_moves_avvy=false;
+ tr[1].ix=3;
+ tr[1].iy=0;
+ tr[1].face=right;
+ set_up_timer(1,procfall_down_oubliette,reason_falling_down_oubliette);
+ }
+ break;
+
+ case 7: { /* Special 7: stop falling down oubliette. */
+ tr[1].visible=false;
+ magics[10].op=nix;
+ stopwalking();
+ lose_timer(reason_falling_down_oubliette);
+ mblit(12,80,38,160,3,0);
+ mblit(12,80,38,160,3,1);
+ display("Oh dear, you seem to be down the bottom of an oubliette.");
+ set_up_timer(200,procmeet_avaroid,reason_meeting_avaroid);
+ }
+ break;
+
+ case 8: /* Special 8: leave du Lustie's room. */
+ if ((geida_follows) & (~ lustie_is_asleep))
+ {
+ dixi('q',63);
+ tr[2].turn(down); tr[2].stopwalk(); tr[2].call_eachstep=false; /* Geida */
+ gameover;
+ }
+ break;
+
+ case 9: { /* Special 9: lose Geida to Robin Hood... */
+ if (~ dna.geida_follows) return; /* DOESN'T COUNT: no Geida. */
+ tr[2].call_eachstep=false; /* She no longer follows Avvy around. */
+ tr[2].walkto(4); /* She walks to somewhere... */
+ tr[1].done(); /* Lose Avvy. */
+ dna.user_moves_avvy=false;
+ set_up_timer(40,procrobin_hood_and_geida,reason_robin_hood_and_geida);
+ }
+ break;
+
+ case 10: { /* Special 10: transfer north in catacombs. */
+ if ((dna.cat_x==4) && (dna.cat_y==1))
+ { /* Into Geida's room. */
+ if (dna.obj[key]) dixi('q',62); else
+ {
+ dixi('q',61);
+ return;
+ }
+ }
+ dusk;
+ dna.cat_y -= 1;
+ catamove(4); if (dna.room!=r__catacombs) return;
+ delavvy;
+ switch ((cardinal)(catamap[cat_y][cat_x] & 0xf00) >> 8) {
+ case 0x1: apped(1,12); break;
+ case 0x3: apped(1,11); break;
+ default: apped(1,4);
+ }
+ getback();
+ dawndelay();
+ }
+ break;
+ case 11: { /* Special 11: transfer east in catacombs. */
+ dusk;
+ dna.cat_x += 1;
+ catamove(1); if (dna.room!=r__catacombs) return;
+ delavvy;
+ apped(1,1);
+ getback();
+ dawndelay();
+ }
+ break;
+ case 12: { /* Special 12: transfer south in catacombs. */
+ dusk;
+ dna.cat_y += 1;
+ catamove(2); if (dna.room!=r__catacombs) return;
+ delavvy;
+ apped(1,2);
+ getback();
+ dawndelay();
+ }
+ break;
+ case 13: { /* Special 13: transfer west in catacombs. */
+ dusk;
+ dna.cat_x -= 1;
+ catamove(3); if (dna.room!=r__catacombs) return;
+ delavvy;
+ apped(1,3);
+ getback();
+ dawndelay();
+ }
+ break;
+ }
+}
+
+void hide_in_the_cupboard();
+
+void open_the_door(byte whither,byte ped,byte magicnum)
+ /* This slides the door open. (The data really ought to be saved in
+ the Also file, and will be next time. However, for now, they're
+ here.) */
+{
+ switch (dna.room) {
+ case r__outsideyours:case r__outsidenottspub:case r__outsideducks:
+ {
+ first_show(1);
+ then_show(2);
+ then_show(3);
+ }
+ break;
+ case r__insidecardiffcastle:
+ {
+ first_show(1);
+ then_show(5);
+ }
+ break;
+ case r__avvysgarden:case r__entrancehall:case r__insideabbey:
+ {
+ first_show(1);
+ then_show(2);
+ }
+ break;
+ case r__musicroom:case r__outsideargentpub:
+ {
+ first_show(5);
+ then_show(6);
+ }
+ break;
+ case r__lusties:
+ switch (magicnum) {
+ case 14: if (dna.avvys_in_the_cupboard)
+ {
+ hide_in_the_cupboard();
+ first_show(8); then_show(7);
+ start_to_close;
+ return;
+ } else
+ {
+ apped(1,6);
+ tr[1].face=right; /* added by TT 12/3/1995 */
+ first_show(8); then_show(9);
+ }
+ break;
+ case 12: {
+ first_show(4); then_show(5); then_show(6);
+ }
+ break;
+ }
+ break;
+ }
+
+ then_flip(whither,ped);
+ start_to_open;
+}
+
+void newspeed()
+ /* Given that you've just changed the speed in triptype.xs, this adjusts
+ ix. */
+{
+ const bytefield lightspace = {40, 199, 47, 199};
+ byte page_;
+
+ {
+ triptype& with = tr[1];
+
+ with.ix=(with.ix / 3)*with.xs;
+ setactivepage(3);
+
+ setfillstyle(1,14);
+ if (with.xs==run) bar(371,199,373,199); else bar(336,199,338,199);
+ setfillstyle(1,9);
+ if (with.xs==run) bar(336,199,338,199); else bar(371,199,373,199);
+
+ setactivepage(1-cp);
+ for( page_=0; page_ <= 1; page_ ++) getset[page_].remember(lightspace);
+ }
+}
+
+triptype* triptype::init(byte spritenum, boolean do_check)
+{
+ const integer idshould = -1317732048;
+ integer gd,gm; varying_string<2> xx;
+ byte fv/*,nds*/;
+ byte aa,bb;
+ longint id; word soa;
+ untyped_file inf;
+
+ if (spritenum==177) return; /* Already running! */
+ str(spritenum,xx); assign(inf,string("sprite")+xx+".avd");
+ reset(inf,1);
+ seek(inf,177);
+ blockread(inf,id,4);
+ if (id!=idshould)
+ {
+ output << '\7';
+ close(inf);
+ exit(0);
+ }
+
+ blockread(inf,soa,2);
+ blockread(inf,a,soa);
+
+ {
+ adxtype& with = a;
+
+ /*nds:=num div seq;*/ totalnum=1;
+ xw=with.xl / 8; if ((with.xl % 8)>0) xw += 1;
+ for( aa=1; aa <= /*nds*seq*/with.num; aa ++)
+ {
+ getmem(sil[totalnum],11*(with.yl+1));
+ getmem(mani[totalnum],with.size-6);
+ for( fv=0; fv <= with.yl; fv ++)
+ {
+ blockread(inf,(*sil[totalnum])[fv],xw);
+ }
+ blockread(inf,*mani[totalnum],with.size-6);
+ totalnum += 1;
+ }
+ }
+
+ /* on; */
+ x=0; y=0; quick=true; visible=false; xs=3; ys=1;
+/* if spritenum=1 then newspeed; { Just for the lights. }*/
+
+ homing=false; ix=0; iy=0; step=0; check_me=do_check;
+ count=0; whichsprite=spritenum; vanishifstill=false;
+ call_eachstep=false;
+ close(inf);
+ return this;
+}
+
+void triptype::original()
+{
+ quick=false; whichsprite=177;
+}
+
+void triptype::andexor()
+{
+ byte picnum; /* Picnum, Picnic, what ye heck */
+ byte lay,laz; /* Limits for Qaz and Qay or equivs. (Laz always = 3). */
+#ifdef NOASM
+ word offs,fv;
+ byte qax,qay,qaz;
+#else
+ word segmani,ofsmani;
+ word ofsaa,realofsaa;
+ word segsil,ofssil;
+ word z; byte xwidth;
+
+#endif
+
+ if ((vanishifstill) && (ix==0) && (iy==0)) return;
+ picnum=face*a.seq+step+1;
+
+ {
+ adxtype& with = a;
+
+ getimage(x,y,x+with.xl,y+with.yl,aa); /* Now loaded into our local buffer. */
+
+ /* Now we've got to modify it! */
+
+ /* Qaz ranges over the width of the sprite/8.
+ Qay " " the height.
+ Qax " " 1 to 4 (the planes). */
+
+ {
+ adxtype& with1 = a;
+
+ #ifdef NOASM
+ laz=xw-1; lay=with1.yl; /* -1's only for Pascal. */
+ #else
+ laz=xw; lay=with1.yl+1; /* +1's only for ASM! */
+ #endif
+ }
+
+ /* ASSEMBLERISED: */
+#ifdef NOASM
+ for( qax=0; qax <= 3; qax ++) /* 3 */
+ for( qay=0; qay <= lay; qay ++) /* 35 */
+ for( qaz=0; qaz <= laz; qaz ++) /* 4 */
+ {
+ offs=5+qay*xw*4+xw*qax+qaz;
+ aa[offs]=aa[offs] & (*sil[picnum])[qay][qaz];
+ }
+
+ for( fv=5; fv <= with.size-2; fv ++)
+ aa[fv]=aa[fv] ^ (*mani[picnum])[fv];
+
+#else
+ /* OK, here's the same thing in assembler...
+
+ AL is Qax,
+ BL is Qay,
+ CL is Qaz,
+ DX is Offs */
+
+ /* For the first part: */
+ xwidth=xw;
+ segsil=seg(*sil[picnum]);
+ ofssil=ofs(*sil[picnum]);
+
+ /* For the first and second parts: */
+ segmani=seg(*mani[picnum]); /* It's easier to do this in Pascal, and */
+ ofsmani=ofs(*mani[picnum])+1; /* besides it only goes round once here. */
+ /* Segment of AA is always the current data segment. */
+ ofsaa=ofs(aa)+5;
+ realofsaa=ofs(aa)-1; /* We may not need this. */
+ z=with.size-7;
+/*
+ asm
+
+ xor ax,ax; { Initialise ax, bx, and cx, using a rather }
+ @QAXloop: { AL }
+
+ xor bx,bx; { nifty speed trick. }
+ @QAYloop: { BL }
+
+ xor cx,cx;
+ @QAZloop: { CL }
+
+ { Right, well, here we are. We have to do some rather nifty array
+ manipulation, stuff like that. We're trying to assemblerise:
+ DX:= 5 + BX * xw * 4 + xw * AX + CX;
+ aa[DX]:=aa[DX] and sil[picnum]^[BL,CL]; }
+
+ push ax; {AXcdx} { OK, we're going to do some strange things }
+ { with ax, so we'd better save it. }
+ mov dx,5; { First of all... set dx to 5. }
+ add dx,cx; { DX now = 5+CX }
+ mul xwidth; { Multiply ax by xw (the Pascal variable.) }
+ add dx,ax; { DX now = 5+CX+xw*AX }
+
+ { Right. Mul only works on ax. Don't ask me why. Ask Intel. Anyway,
+ since ax is saved on the stack, we can move bx over it. Note that
+ if xw was a word, using mul would have destroyed the contents of
+ dx. NOT a good idea! }
+
+ push cx; {CXmul} { We must just borrow cx for a second. }
+ mov ax,bx; { Make ax = bx. }
+ mul xwidth; { Do the same to it as we did to ax before. }
+ mov cl,2;
+ shl ax,cl; { And multiply it by 4 (i.e., shl it by 2.) }
+ add dx,ax; { DX now = 5+CX+xw*AX+xw*BX*4. That's OK. }
+
+ pop cx; {CXmul}
+ pop ax; {AXcdx} { Now we have to get ax and cx back again. }
+
+ { Registers are now returned to original status. }
+
+ { Righto. DX is now all worked out OK. We must now find out the
+ contents of: 1) aa[dx], and 2) (harder) sil[picnum]^[BL,CL]. Gulp. }
+
+ { DS already points to the segment of AA. So... let's use CL to
+ put aa[dx] in, and use BX for the offset. Looks like we're going
+ to have to push a few registers! }
+
+ push ax; { AXaa. Saving loop value of AX. }
+ { Let's use ax to do our dirty work with. }
+ push dx; { Saving Offs(DX.) }
+
+ push bx; { BXaa. Saving loop value of BX. }
+
+ mov bx,realofsaa; { aa is now pointed to by [ds:bx]. }
+ add bx,dx; { Offset is dx bytes. }
+ mov dl,[bx]; { cl now holds the contents of aa[dx]. }
+
+ pop bx; { BXaa. Restoring loop value of BX. }
+
+ { Stack now holds: Offs(DX). }
+
+ { ^^^ That works. Now to find sil[picnum]^[BL,CL]. Our first task is
+ to find the address of sil[picnum]^. Since it's dynamic, we must
+ push and pop ds. }
+
+ push ds; { DXaa. Saving value of Trip5's data segment. }
+ { Push ds. Now we can put the segment of sil[picnum]^... }
+ mov ds,segsil; { ...into ds, and... }
+ mov ax,ofssil; { ...its offset into ax. }
+ { Addr of sil[picnum]^ is now in [ds:ax]. BUT we want a particular
+ offset: to wit, [BL,CL]. Now, siltype is defined so that this offset
+ will be at an offset of (BL*11)+CL. }
+
+ push bx; { Saving loop value of BX. }
+ push cx; { Saving loop value of CX. }
+ push ax; { Saving offset of sil[picnum]^. }
+ { Save them for a bit (!) }
+ mov al,bl; { Put bl into al. }
+ mov bl,11; { ... }
+ mul bl; { ...times it by 11. }
+ mov bx,ax; { Put it back into bx (now = bx*11) }
+ pop ax; { Restoring offset of sil[picnum]^. }
+ { Get ax back again. }
+ add ax,bx; { Add (original bl)*11 to al. }
+ add ax,cx; { Add cl to al. }
+ { AX now holds the offset of sil[picnum]^[bx,cl]. }
+
+ { Stack now holds: loop value of AX, Trip5's DS, lv of BX, lv of CX. }
+
+ { Right. Now the address of sil[picnum]^[bl,cl] is in [ds:ax]. Let's
+ get the elusive byte itself, and put it into ax. Firstly, we must
+ swap ax and bx. }
+
+ xchg ax,bx;
+ mov al,[bx]; { AX now contains sil[picnum]^[bl,cl], AT LAST!! }
+
+ { So now AL contains the sil stuff, and DL holds aa[offs]. }
+
+ and al,dl; { aa[offs]:=aa[offs] and sil[picnum]^[Qay,Qaz]. }
+
+ pop cx; { Restoring loop value of CX. }
+ pop bx; { Restoring loop value of BX. }
+ pop ds; { Restore value of Trip5's data segment. }
+
+ { Right. AL contains the byte we need to replace aa[offs] with.
+ All that's left to do is to put it back. Remember that we already
+ have the segment of aa in the current DS, so... }
+
+ pop dx; { Restore Offs(DX). }
+
+ { Stack is now as when we entered the loop. Since this copy of DX
+ is now being used for the last time, we can muck around with it. }
+
+ { Recap: DX now holds the offset from the start of AA. If we add
+ the offset of aa to it, we'll get the offset of the byte we want.
+ DS is already set up. }
+
+ push bx; { I'm just borrowing bx for a sec. I'll put it back in 5 lines.}
+ mov bx,realofsaa;
+ add dx,bx; { Now aa[offs] is at aa[ds:dx]. }
+ mov bx,dx; { But we can't address memory with dx, so use bx. }
+ mov [bx],al; { Shove it into the memory! }
+ pop bx; { See! I said I would. }
+
+ pop ax; { Restore loop value of AX. }
+
+ { Right, the fancy stuff's all done now. Finish off the loop code. }
+
+ inc cl;
+ cmp cl,laz; { CL must not reach 5. Does it? }
+ jnz @QAZloop; { no, keep going around the QAZloop. }
+
+ inc bl;
+ cmp bl,lay; { BL must not reach 36. Does it? }
+ jnz @QAYloop; { no, keep going around the QAYloop. }
+
+ inc al;
+ cmp al,4; { AL must not reach 4. Does it? }
+ jnz @QAXloop; { no, keep going around the QAXloop. }
+
+ { al, bl and cl are now at their maxima, so we can stop the loops. }
+
+ { *** SECOND ASSEMBLER BIT. *** }
+
+ mov cx,z; { Find the size of the array, -7. }
+ mov bx,ofsmani; { Now find the offset and put that into bx. }
+ mov dx,ofsaa; { We'll use dx to be the same as fv, +5. }
+
+ { DS should already hold the segment of aa. }
+
+ @nextbyte: { Main loop... }
+
+ { Firstly, we must get hold of aa[fv] (here called aa[dx].)}
+ push bx; { We need to "borrow" bx for a second... }
+ mov bx,dx; { Wrong register- shove it into bx. }
+ mov al,[bx]; { Get aa[fv] and put it into al. }
+ pop bx; { Right, you can have bx back again. }
+
+ { Secondly, we must get hold of mani[picnum]^[fv]. }
+ push cx; { Let's borrow cx for this one. }
+ push ds; { we must use ds to point to segmani. }
+ mov ds,segmani; { Find the segment of mani[picnum]^, }
+ mov cl,[bx]; { now get the byte at [ds:bx] and put it into cl. }
+ pop ds; { Put ds back to being the current data segment. }
+
+ { Right: now we can do what we came here for in the first place.
+ AL contains aa[fv], CL contains mani[picnum]^[fv]. }
+
+ xor al,cl; { Xor al with bl. That's it! }
+
+ pop cx; { We don't need cx any more for this now. }
+
+ push bx; { Borrow bx... }
+ mov bx,dx; { Put dx into bx. }
+ mov [bx],al; { Put the changed al back into [ds:bx] (ie, [ds:dx].}
+ pop bx; { Get it back. }
+
+ inc bx; { Add one to bx, for the next char. }
+ inc dx; { And dx, for the same reason. }
+
+ loop @nextbyte; { Keep going round until cx=0. }
+*/
+{;
+}
+#endif
+
+ /* Now.. let's try pasting it back again! */
+
+ putimage(x,y,aa,0);
+ }
+}
+
+void triptype::turn(byte whichway)
+{
+ if (whichway==8) face=0; else face=whichway;
+}
+
+void triptype::appear(integer wx,integer wy, byte wf)
+{
+ x=(wx / 8)*8; y=wy; ox[cp]=wx; oy[cp]=wy; turn(wf);
+ visible=true; ix=0; iy=0;
+}
+
+
+
+
+static boolean collision_check()
+{
+ byte fv;
+
+ boolean collision_check_result;
+ for( fv=1; fv <= numtr; fv ++)
+ if (tr[fv].quick && (tr[fv].whichsprite!=whichsprite) &&
+ ((x+a.xl)>tr[fv].x) &&
+ (x<(tr[fv].x+tr[fv].a.xl)) &&
+ (tr[fv].y==y))
+ {
+ collision_check_result=true;
+ return collision_check_result;
+ }
+ collision_check_result=false;
+ return collision_check_result;
+}
+
+void triptype::walk()
+{
+ byte tc; bytefield r;
+
+
+ if (visible)
+ {
+ {
+ x1=(x / 8)-1;
+ if (x1==255) x1=0;
+ y1=y-2;
+ x2=((x+a.xl) / 8)+1;
+ y2=y+a.yl+2;
+ }
+ getset[1-cp].remember(r);
+ }
+
+ if (~ doing_sprite_run)
+ {
+ ox[cp]=x; oy[cp]=y;
+ if (homing) homestep();
+ x=x+ix; y=y+iy;
+ }
+
+ if (check_me)
+ {
+ if (collision_check())
+ {
+ bounce();
+ return;
+ }
+
+ tc=checkfeet(x,x+a.xl,oy[cp],y,a.yl);
+
+ if ((tc!=0) & (~ doing_sprite_run))
+ { void& with = magics[tc];
+ switch (op) {
+ case exclaim: {
+ bounce(); mustexclaim=true; saywhat=data;
+ }
+ break;
+ case bounces: bounce(); break;
+ case transport: fliproom(hi(data),lo(data)); break;
+ case unfinished: {
+ bounce();
+ display("\7Sorry.\3\rThis place is not available yet!");
+ }
+ break;
+ case special: call_special(data); break;
+ case mopendoor: open_the_door(hi(data),lo(data),tc); break;
+ }}
+ }
+
+ if (~ doing_sprite_run)
+ {
+ count += 1;
+ if (((ix!=0) || (iy!=0)) && (count>1))
+ {
+ step += 1; if (step==a.seq) step=0; count=0;
+ }
+ }
+
+}
+
+void triptype::bounce()
+{
+ x=ox[cp]; y=oy[cp];
+ if (check_me) stopwalking(); else stopwalk();
+ oncandopageswap=false;
+ showrw;
+ oncandopageswap=true;
+}
+
+shortint sgn(integer x)
+{
+ shortint sgn_result;
+ if (x>0) sgn_result=1; else
+ if (x<0) sgn_result=-1; else
+ sgn_result=0; /* x=0 */
+ return sgn_result;
+}
+
+void triptype::walkto(byte pednum)
+{
+ speed(sgn(peds[pednum].x-x)*4,sgn(peds[pednum].y-y));
+ hx=peds[pednum].x-a.xl / 2;
+ hy=peds[pednum].y-a.yl; homing=true;
+}
+
+void triptype::stophoming()
+{
+ homing=false;
+}
+
+void triptype::homestep()
+{
+ integer temp;
+
+ if ((hx==x) && (hy==y))
+ { /* touching the target */
+ stopwalk();
+ return;
+ }
+ ix=0; iy=0;
+ if (hy!=y)
+ {
+ temp=hy-y; if (temp>4) iy=4; else if (temp<-4) iy=-4; else iy=temp;
+ }
+ if (hx!=x)
+ {
+ temp=hx-x; if (temp>4) ix=4; else if (temp<-4) ix=-4; else ix=temp;
+ }
+}
+
+void triptype::speed(shortint xx,shortint yy)
+{
+ ix=xx; iy=yy;
+ if ((ix==0) && (iy==0)) return; /* no movement */
+ if (ix==0)
+ { /* No horz movement */
+ if (iy<0) turn(up); else turn(down);
+ } else
+ {
+ if (ix<0) turn(left); else turn(right);
+ }
+}
+
+void triptype::stopwalk()
+{
+ ix=0; iy=0; homing=false;
+}
+
+void triptype::chatter()
+{
+ talkx=x+a.xl / 2; talky=y; talkf=a.fgc; talkb=a.bgc;
+}
+
+void triptype::set_up_saver(trip_saver_type& v)
+{
+ v.whichsprite=whichsprite;
+ v.face=face;
+ v.step=step;
+ v.x=x;
+ v.y=y;
+ v.ix=ix;
+ v.iy=iy;
+ v.visible=visible;
+ v.homing=homing;
+ v.check_me=check_me;
+ v.count=count;
+ v.xw=xw;
+ v.xs=xs;
+ v.ys=ys;
+ v.totalnum=totalnum;
+ v.hx=hx;
+ v.hy=hy;
+ v.call_eachstep=call_eachstep;
+ v.eachstep=eachstep;
+ v.vanishifstill=vanishifstill;
+}
+
+void triptype::unload_saver(trip_saver_type v)
+{
+ whichsprite=v.whichsprite;
+ face=v.face;
+ step=v.step;
+ x=v.x;
+ y=v.y;
+ ix=v.ix;
+ iy=v.iy;
+ visible=v.visible;
+ homing=v.homing;
+ check_me=v.check_me;
+ count=v.count;
+ xw=v.xw;
+ xs=v.xs;
+ ys=v.ys;
+ totalnum=v.totalnum;
+ hx=v.hx;
+ hy=v.hy;
+ call_eachstep=v.call_eachstep;
+ eachstep=v.eachstep;
+ vanishifstill=v.vanishifstill;
+}
+
+void triptype::savedata(untyped_file& f)
+{
+ trip_saver_type tripsaver;
+
+ set_up_saver(tripsaver);
+
+ {
+ blockwrite(f,tripsaver.whichsprite,1);
+ blockwrite(f,tripsaver.face,1); blockwrite(f,tripsaver.step,1);
+ blockwrite(f,tripsaver.x,2); blockwrite(f,tripsaver.y,2);
+ blockwrite(f,tripsaver.ix,1); blockwrite(f,tripsaver.iy,1);
+ blockwrite(f,tripsaver.visible,1);
+ blockwrite(f,tripsaver.homing,1);
+ blockwrite(f,tripsaver.check_me,1);
+ blockwrite(f,tripsaver.count,1);
+ blockwrite(f,tripsaver.xw,1);
+ blockwrite(f,tripsaver.xs,1); blockwrite(f,tripsaver.ys,1);
+ blockwrite(f,tripsaver.totalnum,1);
+ blockwrite(f,tripsaver.hx,2); blockwrite(f,tripsaver.hy,2);
+ blockwrite(f,tripsaver.call_eachstep,1);
+ blockwrite(f,tripsaver.eachstep,1);
+ blockwrite(f,tripsaver.vanishifstill,1);
+ }
+}
+
+void triptype::loaddata(untyped_file& f)
+{
+ word spritewas,spriteis,saveface,savex,savey,savestep;
+ boolean wasquick;
+ trip_saver_type tripsaver;
+
+
+ wasquick=quick;
+ quick=true; spritewas=whichsprite;
+
+ {
+ blockread(f,tripsaver.whichsprite,1);
+ blockread(f,tripsaver.face,1); blockread(f,tripsaver.step,1);
+ blockread(f,tripsaver.x,2); blockread(f,tripsaver.y,2);
+ blockread(f,tripsaver.ix,1); blockread(f,tripsaver.iy,1);
+
+ if ((! wasquick) || ((unsigned char)tripsaver.whichsprite!=spritewas))
+ {
+ spriteis=tripsaver.whichsprite;
+ savex=tripsaver.x; savey=tripsaver.y; saveface=tripsaver.face; savestep=tripsaver.step;
+
+ if (wasquick) done();
+
+ init(spriteis,tripsaver.check_me);
+
+ appear(savex,savey,saveface); tripsaver.step=savestep;
+ }
+
+ blockread(f,tripsaver.visible,1);
+ blockread(f,tripsaver.homing,1);
+ blockread(f,tripsaver.check_me,1);
+ blockread(f,tripsaver.count,1);
+ blockread(f,tripsaver.xw,1);
+ blockread(f,tripsaver.xs,1); blockread(f,tripsaver.ys,1);
+ blockread(f,tripsaver.totalnum,1);
+ blockread(f,tripsaver.hx,2); blockread(f,tripsaver.hy,2);
+ blockread(f,tripsaver.call_eachstep,1);
+ blockread(f,tripsaver.eachstep,1);
+ blockread(f,tripsaver.vanishifstill,1);
+ }
+
+ unload_saver(tripsaver);
+}
+
+triptype* triptype::done()
+{
+ integer gd,gm; varying_string<2> xx;
+ byte fv/*,nds*/;
+ byte aa,bb;
+ longint id; word soa;
+
+ {
+ adxtype& with = a;
+
+/* nds:=num div seq;*/
+ xw=with.xl / 8; if ((with.xl % 8)>0) xw += 1;
+ for( aa=1; aa <= /*nds*seq*/ with.num; aa ++)
+ {
+ totalnum -= 1;
+ freemem(mani[totalnum],with.size-6);
+ freemem(sil[totalnum],11*(with.yl+1)); /* <<- Width of a siltype. */
+ }
+ }
+
+ quick=false; whichsprite=177;
+ return this;
+}
+
+getsettype* getsettype::init()
+{
+ numleft=0; /* initialise array pointer */
+ return this;
+}
+
+void getsettype::remember(bytefield r)
+{
+ numleft += 1;
+ if (numleft>maxgetset) runerror(runerr_getset_overflow);
+ gs[numleft]=r;
+}
+
+void getsettype::recall(bytefield& r)
+{
+ r=gs[numleft];
+ numleft -= 1;
+}
+
+void rwsp(byte t,byte r)
+{
+ { triptype& with = tr[t]; switch (r) {
+ case up: speed( 0,-with.ys); break; case down: speed( 0, with.ys); break; case left: speed(-with.xs, 0); break;
+ case right: speed( with.xs, 0); break; case ul: speed(-with.xs,-with.ys); break; case ur: speed( with.xs,-with.ys); break;
+ case dl: speed(-with.xs, with.ys); break; case dr: speed( with.xs, with.ys); break;
+ }}
+}
+
+void apped(byte trn,byte np)
+{
+ { triptype& with = tr[trn];
+ {
+ void& with1 = peds[np];
+
+ appear(with.x-with.a.xl / 2,with.y-with.a.yl,dir);
+ rwsp(trn,dir);
+ }}
+}
+
+void getback();
+
+static bytefield r;
+
+
+/* function overlap(x1,y1,x2,y2,x3,y3,x4,y4:word):boolean;
+ begin { By De Morgan's law: }
+ overlap:=(x2>=x3) and (x4>=x1) and (y2>=y3) and (y4>=y1);
+ end;*/
+ /* x1,x2 - as bytefield, but *8. y1,y2 - as bytefield.
+ x3,y3 = mx,my. x4,y4 = mx+16,my+16. */
+static boolean overlaps_with_mouse()
+{
+ boolean overlaps_with_mouse_result;
+ overlaps_with_mouse_result=
+ (x2*8>=mx) && (mx+16>=x1*8) && (y2>=my) && (my+16>=y1);
+ return overlaps_with_mouse_result;
+}
+
+void getback()
+{
+ byte fv;
+ boolean endangered;
+
+
+ endangered=false;
+/* Super_Off;*/
+
+ { getsettype& with = getset[1-cp];
+ while (with.numleft>0)
+ {
+ recall(r);
+
+/* if overlaps_with_mouse and not endangered then
+ begin
+ endangered:=true;
+ blitfix;
+ Super_Off;
+ end;*/
+
+ mblit(x1,y1,x2,y2,3,1-cp);
+ }}
+
+ blitfix;
+ /*if endangered then*/ /*Super_On;*/
+}
+
+/* Eachstep procedures: */
+void follow_avvy_y(byte tripnum)
+{
+ {
+ triptype& with = tr[tripnum];
+
+ if (tr[1].face==left) return;
+ if (with.homing) with.hy=tr[1].y; else
+ {
+ if (with.y<tr[1].y)
+ with.y += 1; else
+ if (with.y>tr[1].y)
+ with.y -= 1; else
+ return;
+ if (with.ix==0) { with.step += 1; if (with.step==with.a.seq) with.step=0; with.count=0; }
+ }
+ }
+}
+
+void back_and_forth(byte tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (! with.homing)
+ {
+ if (with.face==right) walkto(4); else walkto(5);
+ }}
+}
+
+void face_avvy(byte tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (! with.homing)
+ {
+ if (tr[1].x>=with.x) with.face=right;
+ else with.face=left;
+ }}
+}
+
+void arrow_procs(byte tripnum)
+{
+ byte fv;
+
+ { triptype& with = tr[tripnum];
+ if (with.homing)
+ { /* Arrow is still in flight. */
+ /* We must check whether or not the arrow has collided with Avvy's head.
+ This is so if: a) the bottom of the arrow is below Avvy's head,
+ b) the left of the arrow is left of the right of Avvy's head, and
+ c) the right of the arrow is right of the left of Avvy's head. */
+ if (((with.y+with.a.yl)>=tr[1].y) /* A */
+ && (with.x<=(tr[1].x+tr[1].a.xl)) /* B */
+ && ((with.x+with.a.xl)>=tr[1].x)) /* C */
+ { /* OK, it's hit him... what now? */
+
+ tr[2].call_eachstep=false; /* prevent recursion. */
+ dixi('Q',47); /* Complaint! */
+ done(); /* Deallocate the arrow. */
+/* tr[1].done; { Deallocate normal pic of Avvy. }
+
+ off;
+ for fv:=0 to 1 do
+ begin
+ cp:=1-cp;
+ getback;
+ end;
+ on;*/
+
+ gameover;
+
+ dna.user_moves_avvy=false; /* Stop the user from moving him. */
+ set_up_timer(55,procnaughty_duke,reason_naughty_duke);
+ }
+ } else /* Arrow has hit the wall! */
+ {
+ done(); /* Deallocate the arrow. */
+ show_one(3); /* Show pic of arrow stuck into the door. */
+ dna.arrow_in_the_door=true; /* So that we can pick it up. */
+ }}
+}
+
+/*procedure Spludwick_procs(tripnum:byte);
+var fv:byte;
+begin
+ with tr[tripnum] do
+ if not homing then { We only need to do anything if Spludwick *stops*
+ walking. }
+ with dna do
+ begin
+ inc(DogfoodPos);
+ if DogfoodPos=8 then DogfoodPos:=1;
+ walkto(DogfoodPos);
+ end;
+end;*/
+
+void grab_avvy(byte tripnum) /* For Friar Tuck, in Nottingham. */
+{
+ byte fv; integer tox,toy;
+
+ { triptype& with = tr[tripnum];
+ {
+ tox=tr[1].x + 17;
+ toy=tr[1].y - 1;
+ if ((with.x==tox) && (with.y==toy))
+ {
+ with.call_eachstep=false;
+ with.face=left;
+ stopwalk();
+ /* ... whatever ... */
+ } else
+ { /* Still some way to go. */
+ if (with.x<tox)
+ {
+ with.x += 5;
+ if (with.x>tox) with.x=tox;
+ }
+ if (with.y<toy) with.y += 1;
+ with.step += 1; if (with.step==with.a.seq) with.step=0;
+ }
+ }}
+}
+
+void geida_procs(byte tripnum);
+
+static void take_a_step(byte& tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (with.ix==0)
+ { with.step += 1; if (with.step==with.a.seq) with.step=0; with.count=0; }}
+}
+
+
+
+static void spin(byte whichway, byte& tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (with.face!=whichway)
+ {
+ with.face=whichway;
+ if (with.whichsprite==2) return; /* Not for Spludwick */
+
+ dna.geida_spin += 1;
+ dna.geida_time=20;
+ if (dna.geida_spin==5)
+ {
+ display("Steady on, Avvy, you'll make the poor girl dizzy!");
+ dna.geida_spin=0; dna.geida_time=0; /* knock out records */
+ }
+ }}
+}
+
+void geida_procs(byte tripnum)
+{
+ {
+ triptype& with = tr[tripnum];
+
+ if (dna.geida_time>0)
+ {
+ dna.geida_time -= 1;
+ if (dna.geida_time==0) dna.geida_spin=0;
+ }
+
+ if (with.y<(tr[1].y-2))
+ { /* Geida is further from the screen than Avvy. */
+ spin(down, tripnum);
+ with.iy=1; with.ix=0;
+ take_a_step(tripnum);
+ return;
+ } else
+ if (with.y>(tr[1].y+2))
+ { /* Avvy is further from the screen than Geida. */
+ spin(up, tripnum);
+ with.iy=-1; with.ix=0;
+ take_a_step(tripnum);
+ return;
+ }
+
+ with.iy=0;
+ if (with.x<tr[1].x-tr[1].xs*8)
+ {
+ with.ix=tr[1].xs;
+ spin(right, tripnum);
+ take_a_step(tripnum);
+ } else
+ if (with.x>tr[1].x+tr[1].xs*8)
+ {
+ with.ix=-tr[1].xs;
+ spin(left, tripnum);
+ take_a_step(tripnum);
+ } else with.ix=0;
+ }
+}
+
+/* That's all... */
+
+void call_andexors()
+{
+ array<1,5,byte> order;
+ byte fv,temp;
+ boolean ok;
+
+ fillchar(order,5,'\0');
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv];
+ if (with.quick && with.visible)
+ order[fv]=fv;}
+
+ do {
+ ok=true;
+ for( fv=1; fv <= 4; fv ++)
+ if (((order[fv]!=0) && (order[fv+1]!=0))
+ && (tr[order[fv]].y>tr[order[fv+1]].y))
+ { /* Swap them! */
+ temp=order[fv];
+ order[fv]=order[fv+1];
+ order[fv+1]=temp;
+ ok=false;
+ }
+ } while (!ok);
+
+ for( fv=1; fv <= 5; fv ++)
+ if (order[fv]>0)
+ tr[order[fv]].andexor();
+}
+
+void trippancy_link()
+{
+ byte fv;
+
+ if (ddmnow | ontoolbar | seescroll) return;
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv]; if (with.quick) walk();}
+ call_andexors();
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv];
+ if (with.quick && with.call_eachstep)
+ {
+ switch (tr[fv].eachstep) {
+ case procfollow_avvy_y : follow_avvy_y(fv); break;
+ case procback_and_forth : back_and_forth(fv); break;
+ case procface_avvy : face_avvy(fv); break;
+ case procarrow_procs : arrow_procs(fv); break;
+/* PROCSpludwick_procs : spludwick_procs(fv);*/
+ case procgrab_avvy : grab_avvy(fv); break;
+ case procgeida_procs : geida_procs(fv); break;
+ }
+ }}
+ if (mustexclaim)
+ {
+ mustexclaim=false;
+ dixi('x',saywhat);
+ }
+}
+
+void get_back_loretta()
+{
+ byte fv;
+
+/* for fv:=1 to numtr do with tr[fv] do if quick then getback;*/
+ for( fv=1; fv <= numtr; fv ++) if (tr[fv].quick)
+ {
+ getback();
+ return;
+ }
+/* for fv:=0 to 1 do begin cp:=1-cp; getback; end;*/
+}
+
+void stopwalking()
+{
+ tr[1].stopwalk(); dna.rw=stopped; if (alive) tr[1].step=1;
+}
+
+void tripkey(char dir)
+{
+ if ((ctrl==cjoy) | (~ dna.user_moves_avvy)) return;
+
+ { triptype& with = tr[1];
+ {
+ switch (dir) {
+ case 'H': if (rw!=up)
+ { rw=up; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'P': if (rw!=down)
+ { rw=down; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'K': if (rw!=left)
+ { rw=left; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'M': if (rw!=right)
+ { rw=right; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'I': if (rw!=ur)
+ { rw=ur; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'Q': if (rw!=dr)
+ { rw=dr; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'O': if (rw!=dl)
+ { rw=dl; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'G': if (rw!=ul)
+ { rw=ul; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'L': stopwalking(); break;
+ }
+ }}
+}
+
+void readstick()
+{
+ byte jw;
+
+ if (ctrl==ckey) return;
+
+ jw=joyway;
+
+ {
+ triptype& with = tr[1];
+
+ if (jw==stopped) stopwalking(); else
+ {
+ dna.rw=jw; rwsp(1,dna.rw);
+ }
+ }
+
+ if (jw!=oldjw)
+ {
+ showrw;
+ oldjw=jw;
+ }
+
+}
+
+void getsetclear()
+{
+ byte fv;
+
+ for( fv=0; fv <= 1; fv ++) getset[fv].init();
+}
+
+void hide_in_the_cupboard()
+{
+ const char nowt = '\372'; /* As in Acci. */
+
+ {
+ if (avvys_in_the_cupboard)
+ {
+ if (wearing==nowt)
+ display("\6AVVY!\22 Get dressed first!");
+ else
+ {
+ tr[1].visible=true;
+ user_moves_avvy=true;
+ apped(1,3); /* Walk out of the cupboard. */
+ display("You leave the cupboard. Nice to be out of there!");
+ avvys_in_the_cupboard=false;
+ first_show(8); then_show(7); start_to_close;
+ }
+ } else
+ { /* Not hiding in the cupboard */
+ tr[1].visible=false;
+ user_moves_avvy=false;
+ display(string("You walk into the room...\20It seems to be an empty, ")+
+ "but dusty, cupboard. Hmmmm... you leave the door slightly open to "+
+ "avoid suffocation.");
+ avvys_in_the_cupboard=true;
+ show_one(8);
+ }
+ }
+}
+
+void fliproom(byte room,byte ped);
+static integer beforex,beforey;
+static void tidy_after_mouse();
+
+
+static void tidy_up(integer a,integer b,integer c,integer d)
+{
+ bytefield bf;
+
+ {
+ x1=a / 8;
+ y1=b;
+ x2=(c+7) / 8;
+ y2=d;
+ setactivepage(0);
+ rectangle(x1*8,y1,x2*8+7,y2);
+ }
+ getset[0].remember(bf);
+ getset[1].remember(bf);
+}
+
+
+
+static void tidy_after_mouse()
+{
+ tidy_up(beforex,beforey,beforex+15,beforey+15);
+ xycheck;
+ tidy_up(mx,my,mx+15,my+15);
+}
+
+void fliproom(byte room,byte ped)
+{
+ byte fv;
+
+
+ if (~ alive)
+ { /* You can't leave the room if you're dead. */
+ tr[1].ix=0; tr[1].iy=0; /* Stop him from moving. */
+ return;
+ }
+
+ if ((ped==177) && (dna.room==r__lusties))
+ {
+ hide_in_the_cupboard();
+ return;
+ }
+
+ if ((dna.jumpstatus>0) && (dna.room==r__insidecardiffcastle))
+ { /* You can't *jump* out of Cardiff Castle! */
+ tr[1].ix=0;
+ return;
+ }
+
+ xycheck; beforex=mx; beforey=my;
+
+ exitroom(dna.room);
+ dusk; getsetclear();
+
+
+ for( fv=2; fv <= numtr; fv ++)
+ { triptype& with = tr[fv];
+ if (with.quick) done();} /* Deallocate sprite */
+
+ if (dna.room==r__lustiesroom)
+ dna.enter_catacombs_from_lusties_room=true;
+
+ enterroom(room,ped); apped(1,ped);
+ dna.enter_catacombs_from_lusties_room=false;
+ oldrw=dna.rw; dna.rw=tr[1].face; showrw;
+
+ for( fv=0; fv <= 1; fv ++)
+ {
+ cp=1-cp;
+ getback();
+ }
+ dawn;
+
+ /* Tidy up after mouse. I know it's a kludge... */
+/* tidy_after_mouse;*/
+}
+
+boolean infield(byte which)
+ /* returns True if you're within field "which" */
+{
+ integer yy;
+
+ boolean infield_result;
+ { void& with = fields[which]; {
+ triptype& with = tr[1];
+
+ yy=with.y+with.a.yl;
+ infield_result=(with.x>=x1) && (with.x<=x2) && (yy>=y1) && (yy<=y2);
+ }}
+ return infield_result;
+}
+
+boolean neardoor() /* returns True if you're near a door! */
+{
+ integer ux,uy; byte fv; boolean nd;
+
+ boolean neardoor_result;
+ if (numfields<9)
+ { /* there ARE no doors here! */
+ neardoor_result=false;
+ return neardoor_result;
+ }
+ {
+ triptype& with = tr[1];
+
+ ux=with.x;
+ uy=with.y+with.a.yl;
+ } nd=false;
+ for( fv=9; fv <= numfields; fv ++)
+ {
+ void& with = fields[fv];
+
+ if ((ux>=x1) && (ux<=x2) && (uy>=y1) && (uy<=y2)) nd=true;
+ }
+ neardoor_result=nd;
+ return neardoor_result;
+}
+
+void new_game_for_trippancy() /* Called by gyro.newgame */
+{
+ tr[1].visible=false;
+}
+
+void triptype::save_data_to_mem(word& where)
+{
+ trip_saver_type tripsaver;
+
+ set_up_saver(tripsaver);
+ move(tripsaver,mem[storage_seg*where],sizeof(tripsaver));
+ where += sizeof(tripsaver);
+}
+
+void triptype::load_data_from_mem(word& where)
+{
+ word spritewas,spriteis,saveface,savex,savey,savestep;
+ boolean wasquick;
+ trip_saver_type tripsaver;
+
+ move(mem[storage_seg*where],tripsaver,sizeof(tripsaver));
+ where += sizeof(tripsaver);
+ unload_saver(tripsaver);
+
+ spriteis=whichsprite;
+ savex=x; savey=y; saveface=face; savestep=step;
+
+ init(spriteis,check_me);
+
+ appear(savex,savey,saveface); unload_saver(tripsaver);
+ step=savestep;
+}
+
+class unit_trip5_initialize {
+ public: unit_trip5_initialize();
+};
+static unit_trip5_initialize trip5_constructor;
+
+unit_trip5_initialize::unit_trip5_initialize() {
+ getsetclear(); mustexclaim=false;
+}