686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
|
if(o->weight>o->inertia) goto fail;
o->inertia-=o->weight;
restart:
if(hit&0x100000) dir=o->dir;
objF=obj_dir(obj,dir);
if(objF==VOIDLINK) goto fail;
oF=objects[objF];
hF=height_at(oF->x,oF->y);
if(dir&1) {
// Diagonal movement
objLF=obj_dir(obj,(dir+1)&7);
objRF=obj_dir(obj,(dir-1)&7);
vol=o->volume;
if(objLF!=VOIDLINK) vol+=volume_at(objects[objLF]->x,objects[objLF]->y);
if(objRF!=VOIDLINK) vol+=volume_at(objects[objRF]->x,objects[objRF]->y);
if(vol<=max_volume) {
objE=objF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0 && !(oE->oflags&(OF_VISUALONLY|OF_DESTROYED))) {
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit|0x80000));
if(v.t) Throw("Type mismatch in HIT/HITBY");
hit=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xFC098F7F:-1);
if(hit&8) goto fail;
if(!(hit&0x11)) {
v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit|0x80000));
if(v.t) Throw("Type mismatch in HIT/HITBY");
hit=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xFC098F7F:-1);
if(hit&8) goto fail;
}
}
objE=obj_below(objE);
}
if(!(hit&0x402008)) {
if(hF<=o->climb || (hit&0x200000)) {
if(hit&0x20000) goto success;
if(move_to(from,obj,oF->x,oF->y)) goto success; else goto fail;
}
}
} else {
// Volume is too much; hit the objects it won't go between
objE=objLF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0 && !(oE->oflags&(OF_VISUALONLY|OF_DESTROYED))) {
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(0x80008));
if(v.t) Throw("Type mismatch in HIT/HITBY");
if(!(v.u&1)) v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(v.u|0x80008));
}
objE=obj_below(objE);
}
objE=objRF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0 && !(oE->oflags&(OF_VISUALONLY|OF_DESTROYED))) {
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(0x80008));
if(v.t) Throw("Type mismatch in HIT/HITBY");
if(!(v.u&1)) v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(v.u|0x80008));
}
objE=obj_below(objE);
}
}
} else {
// Orthogonal movement
if(hit) hit=(hit&0x0C000000)|0x800;
objE=objF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0 && !(oE->oflags&(OF_VISUALONLY|OF_DESTROYED))) {
hit&=~7;
// HIT/HITBY messages
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit));
if(v.t) Throw("Type mismatch in HIT/HITBY");
hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xFC098F7F:-1);
if(hit&8) goto fail;
if(!(hit&0x11)) {
|
|
|
>
|
|
|
|
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
|
if(o->weight>o->inertia) goto fail;
o->inertia-=o->weight;
restart:
if(hit&0x100000) dir=o->dir;
objF=obj_dir(obj,dir);
if(objF==VOIDLINK) goto fail;
oF=objects[objF];
hF=oF?height_at(oF->x,oF->y):0;
if(dir&1) {
// Diagonal movement
objLF=obj_dir(obj,(dir+1)&7);
objRF=obj_dir(obj,(dir-1)&7);
vol=o->volume;
if(objLF!=VOIDLINK) vol+=volume_at(objects[objLF]->x,objects[objLF]->y);
if(objRF!=VOIDLINK) vol+=volume_at(objects[objRF]->x,objects[objRF]->y);
if(vol<=max_volume) {
objE=objF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0) {
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit|0x80000));
if(v.t) Throw("Type mismatch in HIT/HITBY");
hit=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xFC098F7F:-1);
if(hit&8) goto fail;
if(!(hit&0x11)) {
v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit|0x80000));
if(v.t) Throw("Type mismatch in HIT/HITBY");
hit=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xFC098F7F:-1);
if(hit&8) goto fail;
}
}
objE=obj_below(objE);
}
if(!(hit&0x402008)) {
if(hF<=o->climb || (hit&0x200000)) {
if(hit&0x20000) goto success;
if(!oF) goto fail;
if(move_to(from,obj,oF->x,oF->y)) goto success; else goto fail;
}
}
} else {
// Volume is too much; hit the objects it won't go between
objE=objLF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0) {
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(0x80008));
if(v.t) Throw("Type mismatch in HIT/HITBY");
if(!(v.u&1)) v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(v.u|0x80008));
}
objE=obj_below(objE);
}
objE=objRF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0) {
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(0x80008));
if(v.t) Throw("Type mismatch in HIT/HITBY");
if(!(v.u&1)) v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(v.u|0x80008));
}
objE=obj_below(objE);
}
}
} else {
// Orthogonal movement
if(hit) hit=(hit&0x0C000000)|0x800;
objE=objF;
while(objE!=VOIDLINK) {
oE=objects[objE];
if(oE->height>0) {
hit&=~7;
// HIT/HITBY messages
v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit));
if(v.t) Throw("Type mismatch in HIT/HITBY");
hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xFC098F7F:-1);
if(hit&8) goto fail;
if(!(hit&0x11)) {
|
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
|
}
nobjects=0;
free(objects);
objects=0;
gameover=0;
}
static Uint8 execute_animation(Uint8 clock,Uint32 obj) {
Object*o=objects[obj];
Animation*a=o->anim;
if(!(a->step[a->lstep].flag&ANI_ONCE)) return clock;
if(a->ltime>=a->step[a->lstep].speed) {
a->ltime=0;
if(o->image==a->step[a->lstep].end) {
a->status&=~ANISTAT_LOGICAL;
if(classes[o->class]->cflags&CF_COMPATIBLE) lastimage_processing=1;
send_message(VOIDLINK,obj,MSG_LASTIMAGE,NVALUE(0),NVALUE(0),NVALUE(0));
lastimage_processing=0;
} else {
if(a->step[a->lstep].start>a->step[a->lstep].end) --o->image; else ++o->image;
}
}
if(!(a->status&ANISTAT_LOGICAL) || !(a->step[a->lstep].flag&ANI_ONCE)) return clock;
if(clock>a->step[a->lstep].speed-a->ltime) return a->step[a->lstep].speed-a->ltime;
return clock;
}
const char*execute_turn(int key) {
Uint8 busy,clock;
Uint32 m,n,turn;
Object*o;
Value v;
int i;
if(!key) return 0;
if(setjmp(my_env)) return my_error;
if(quiz_text) {
sqlite3_free(quiz_text);
quiz_text=0;
if(key_ignored) {
if(quiz_obj.t) quiz_obj=NVALUE(0); else return 0;
} else if(!quiz_obj.t) {
|
|
|
<
<
<
|
>
>
>
>
|
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
|
}
nobjects=0;
free(objects);
objects=0;
gameover=0;
}
static void execute_animation(Uint32 obj) {
Object*o=objects[obj];
Animation*a=o->anim;
if(!(a->step[a->lstep].flag&ANI_ONCE)) return;
if(a->ltime>=a->step[a->lstep].speed) {
a->ltime=0;
if(o->image==a->step[a->lstep].end) {
a->status&=~ANISTAT_LOGICAL;
if(classes[o->class]->cflags&CF_COMPATIBLE) lastimage_processing=1;
send_message(VOIDLINK,obj,MSG_LASTIMAGE,NVALUE(0),NVALUE(0),NVALUE(0));
lastimage_processing=0;
} else {
if(a->step[a->lstep].start>a->step[a->lstep].end) --o->image; else ++o->image;
}
}
}
const char*execute_turn(int key) {
Uint8 busy,clock;
Uint32 m,n,turn;
Object*o;
Value v;
int i;
if(!key) {
// This is part of initialization; if anything triggered, it must be executed now
all_flushed=1;
goto trig;
}
if(setjmp(my_env)) return my_error;
if(quiz_text) {
sqlite3_free(quiz_text);
quiz_text=0;
if(key_ignored) {
if(quiz_obj.t) quiz_obj=NVALUE(0); else return 0;
} else if(!quiz_obj.t) {
|
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
|
busy=1;
}
if(o->arrived) {
send_message(VOIDLINK,n,MSG_ARRIVED,NVALUE(0),NVALUE(0),NVALUE(turn));
o->arrived=0;
busy=1;
}
if(o->anim && (o->anim->status&ANISTAT_LOGICAL)) clock=execute_animation(clock,n);
if(o->oflags&(OF_BUSY|OF_USERSIGNAL)) busy=1;
} else {
o->departed2=o->departed;
o->departed=0;
o->arrived2=o->arrived;
o->arrived=0;
if(o->oflags&OF_MOVED) o->oflags=(o->oflags|OF_MOVED2)&~OF_MOVED;
}
n=m;
}
}
n=lastobj;
while(n!=VOIDLINK) {
o=objects[n];
if(!(classes[o->class]->cflags&CF_COMPATIBLE)) {
if(o->oflags&OF_MOVED2) send_message(VOIDLINK,n,MSG_MOVED,NVALUE(0),NVALUE(0),NVALUE(turn)),busy=1;
if(o->departed2) send_message(VOIDLINK,n,MSG_DEPARTED,NVALUE(o->departed2),NVALUE(0),NVALUE(turn)),busy=1;
if(o->arrived2) send_message(VOIDLINK,n,MSG_ARRIVED,NVALUE(o->arrived2),NVALUE(0),NVALUE(turn)),busy=1;
o->oflags&=~OF_MOVED2;
o->arrived2=o->departed2=0;
if(o->anim && (o->anim->status&ANISTAT_LOGICAL)) clock=execute_animation(clock,n);
if(o->oflags&(OF_BUSY|OF_USERSIGNAL)) busy=1;
}
n=o->prev;
}
// Ending phase
if(!busy && !all_flushed) {
n=lastobj;
while(n!=VOIDLINK) {
v=send_message(VOIDLINK,n,MSG_END_TURN,NVALUE(turn),NVALUE(0),NVALUE(0));
if(v_bool(v) || objects[n]->arrived || objects[n]->departed) busy=1;
if(objects[n]->oflags&(OF_BUSY|OF_USERSIGNAL|OF_MOVED)) busy=1;
n=objects[n]->prev;
}
turn++;
if(!busy) all_flushed=1;
}
// Clock phase
if(!clock) clock=1;
n=lastobj;
while(n!=VOIDLINK) {
o=objects[n];
if(o->oflags&(OF_BUSY|OF_USERSIGNAL|OF_MOVED)) busy=1;
if(o->arrived || o->departed) busy=1;
if(o->anim && (o->anim->status&ANISTAT_LOGICAL)) {
if(o->anim->step[o->anim->lstep].flag&ANI_ONCE) {
i=o->anim->ltime+clock;
o->anim->ltime=i>255?255:i;
busy=1;
}
}
n=o->prev;
}
if(busy) goto trig;
// Cleanup phase
for(n=0;n<nobjects;n++) if(objects[n] && (objects[n]->oflags&OF_DESTROYED)) objtrash(n);
if(generation_number<=TY_MAXTYPE) return "Too many generations of objects";
|
|
|
>
>
>
>
>
>
>
|
>
>
>
|
<
|
|
|
<
|
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
|
busy=1;
}
if(o->arrived) {
send_message(VOIDLINK,n,MSG_ARRIVED,NVALUE(0),NVALUE(0),NVALUE(turn));
o->arrived=0;
busy=1;
}
if(o->anim && (o->anim->status&ANISTAT_LOGICAL)) execute_animation(n);
if(o->oflags&(OF_BUSY|OF_USERSIGNAL)) busy=1;
} else {
o->departed2=o->departed;
o->departed=0;
o->arrived2=o->arrived;
o->arrived=0;
if(o->oflags&OF_MOVED) o->oflags=(o->oflags|OF_MOVED2)&~OF_MOVED;
}
n=m;
}
}
n=lastobj;
while(n!=VOIDLINK) {
o=objects[n];
if(!(classes[o->class]->cflags&CF_COMPATIBLE)) {
if(o->oflags&OF_MOVED2) send_message(VOIDLINK,n,MSG_MOVED,NVALUE(0),NVALUE(0),NVALUE(turn)),busy=1;
if(o->departed2) send_message(VOIDLINK,n,MSG_DEPARTED,NVALUE(o->departed2),NVALUE(0),NVALUE(turn)),busy=1;
if(o->arrived2) send_message(VOIDLINK,n,MSG_ARRIVED,NVALUE(o->arrived2),NVALUE(0),NVALUE(turn)),busy=1;
o->oflags&=~OF_MOVED2;
o->arrived2=o->departed2=0;
if(o->anim && (o->anim->status&ANISTAT_LOGICAL)) execute_animation(n);
if(o->oflags&(OF_BUSY|OF_USERSIGNAL)) busy=1;
}
n=o->prev;
}
// Ending phase
if(!busy && !all_flushed) {
n=lastobj;
while(n!=VOIDLINK) {
v=send_message(VOIDLINK,n,MSG_END_TURN,NVALUE(turn),NVALUE(0),NVALUE(0));
if(v_bool(v) || objects[n]->arrived || objects[n]->departed) busy=1;
if(objects[n]->oflags&(OF_BUSY|OF_USERSIGNAL|OF_MOVED)) busy=1;
n=objects[n]->prev;
}
turn++;
if(!busy) all_flushed=1;
}
// Clock phase
n=lastobj;
while(n!=VOIDLINK) {
o=objects[n];
if(o->arrived || o->departed) goto trig;
if(o->oflags&OF_MOVED) goto trig;
if(o->anim && (o->anim->status&ANISTAT_LOGICAL) && (o->anim->step[o->anim->lstep].flag&ANI_ONCE)) {
if(o->anim->ltime>=o->anim->step[o->anim->lstep].speed) goto trig;
if(clock>o->anim->step[o->anim->lstep].speed-o->anim->ltime) clock=o->anim->step[o->anim->lstep].speed-o->anim->ltime;
}
n=o->prev;
}
n=lastobj;
while(n!=VOIDLINK) {
o=objects[n];
if(o->oflags&(OF_BUSY|OF_USERSIGNAL|OF_MOVED)) busy=1;
if(o->arrived || o->departed) busy=1;
if(o->anim && (o->anim->status&ANISTAT_LOGICAL) && (o->anim->step[o->anim->lstep].flag&ANI_ONCE)) {
i=o->anim->ltime+clock;
o->anim->ltime=i>255?255:i;
busy=1;
}
n=o->prev;
}
if(busy) goto trig;
// Cleanup phase
for(n=0;n<nobjects;n++) if(objects[n] && (objects[n]->oflags&OF_DESTROYED)) objtrash(n);
if(generation_number<=TY_MAXTYPE) return "Too many generations of objects";
|
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
|
all_flushed=0;
lastimage_processing=0;
vstackptr=0;
move_number=0;
current_key=0;
broadcast(VOIDLINK,0,MSG_INIT,NVALUE(0),NVALUE(0),NVALUE(0),0);
broadcast(VOIDLINK,0,MSG_POSTINIT,NVALUE(0),NVALUE(0),NVALUE(0),0);
if(generation_number<=TY_MAXTYPE) return "Too many generations of objects";
return 0;
}
|
|
|
|
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
|
all_flushed=0;
lastimage_processing=0;
vstackptr=0;
move_number=0;
current_key=0;
broadcast(VOIDLINK,0,MSG_INIT,NVALUE(0),NVALUE(0),NVALUE(0),0);
broadcast(VOIDLINK,0,MSG_POSTINIT,NVALUE(0),NVALUE(0),NVALUE(0),0);
if(gameover) return 0;
return execute_turn(0);
}
|