| Hard searches all real teammates for a free cross-ice finish against a keeper
| still in the normal mouth. No geometric "24 better" restriction or keeper-
| velocity requirement. Native pass validation, reception, shot/aim/power remain.
 .text
 .globl _start
_start:
 bra.w shot
 bra.w pass
 bra.w choose
shot:
 movem.l %d0-%d2,-(%sp)
 bsr.w choose
 tst.w %d0
 bpl.s shot_pass
 bsr.w point_choice
 tst.w %d0
 bmi.s shot_native
shot_pass:
 move.l %d0,(%sp)
 movem.l (%sp)+,%d0-%d2
 jmp 0xE4A0
shot_native:
 bsr.w point_carry
 tst.w %d0
 beq.s shot_original
 movem.l (%sp)+,%d0-%d2
 rts
shot_original:
 movem.l (%sp)+,%d0-%d2
 jmp 0x2D8808
pass:
 movem.l %d0-%d2,-(%sp)
 bsr.w choose
 tst.w %d0
 bpl.s pass_selected
 bsr.w point_choice
 tst.w %d0
 bmi.s pass_native
pass_selected:
 move.l %d0,(%sp)
 movem.l (%sp)+,%d0-%d2
 jmp 0xE4A0
pass_native:
 movem.l (%sp)+,%d0-%d2
 tst.w 0xFFFFBEE4
 bne.s threat
 jmp 0xE44C
threat:
 jmp 0xE45E
choose:
 link.w %a6,#-40
 movem.l %d1-%d7/%a0-%a5,-(%sp)
 move.w #-1,-22(%a6)
 move.w #0x7FFF,-20(%a6)
 jsr 0x2D880C
 tst.w %d0
 beq.w done
 btst #2,0xFFFFC2FA
 bne.w done
 btst #1,0x64(%a3)
 bne.w done
 move.w 0x52(%a3),%d0
 cmp.w 0xFFFFB7AA,%d0
 bne.w done
 move.w 0xFFFFB74A,%d1
 move.w %d1,-4(%a6)
 bpl.s carrier_abs
 neg.w %d1
carrier_abs:
 cmpi.w #32,%d1
 blt.w done
 cmpi.w #112,%d1
 bgt.w done
 move.w 0xFFFFB75E,%d1
 btst #7,0x62(%a3)
 bne.s carrier_depth
 neg.w %d1
carrier_depth:
 cmpi.w #160,%d1
 blt.w done
 cmpi.w #280,%d1
 bgt.w done
 move.w %d1,-2(%a6)
 lea 0xFFFFB04A,%a4
 lea 0xFFFFB34A,%a5
 cmpi.w #6,0x52(%a3)
 bcs.s bases
 exg %a4,%a5
bases:
 movea.l %a5,%a1
 moveq #5,%d7
keeper:
 tst.w 0x34(%a1)
 bne.s keeper_next
 btst #2,0x63(%a1)
 bne.s keeper_next
 move.w (%a1),%d1
 move.w %d1,-6(%a6)
 .if !WITH_CENTERED_CROSS
 move.w -4(%a6),%d2
 eor.w %d1,%d2
 bmi.w done
 .endif
keeper_abs:
 tst.w %d1
 bpl.s keeper_positive
 neg.w %d1
keeper_positive:
 .if WITH_CENTERED_CROSS
 cmpi.w #8,%d1
 blt.s keeper_side_ready
 move.w -4(%a6),%d2
 move.w -6(%a6),%d3
 eor.w %d3,%d2
 bmi.w done
keeper_side_ready:
 .else
 cmpi.w #8,%d1
 blt.w done
 .endif
 cmpi.w #40,%d1
 bgt.w done
 move.w 0x14(%a1),%d1
 btst #7,0x62(%a3)
 bne.s keeper_depth
 neg.w %d1
keeper_depth:
 cmpi.w #232,%d1
 blt.w done
 cmpi.w #264,%d1
 bgt.w done
 move.w %d1,-8(%a6)
 bra.s receivers
keeper_next:
 adda.w #128,%a1
 dbra %d7,keeper
 bra.w done
receivers:
 movea.l %a4,%a0
 moveq #5,%d6
receiver:
 cmpa.l %a3,%a0
 beq.w next
 tst.w 0x34(%a0)
 ble.w next
 btst #2,0x63(%a0)
 bne.w next
 btst #5,0x62(%a0)
 bne.w next
 move.w (%a0),%d1
 move.w %d1,-26(%a6)
 beq.s receiver_side
 .if WITH_CENTERED_CROSS
 move.w -4(%a6),%d2                | opposite the passer, including a centered keeper
 .else
 move.w -6(%a6),%d2
 .endif
 eor.w %d2,%d1
 bpl.w next
receiver_side:
 move.w (%a0),%d1
 bpl.s receiver_abs
 neg.w %d1
receiver_abs:
 cmpi.w #64,%d1
 bgt.w next
 add.w %d1,%d1
 move.w %d1,-28(%a6)
 move.w 0x14(%a0),%d2
 btst #7,0x62(%a3)
 bne.s receiver_depth
 neg.w %d2
receiver_depth:
 cmpi.w #184,%d2
 blt.w next
 cmpi.w #244,%d2
 bgt.w next
 move.w %d2,-24(%a6)
 subi.w #224,%d2
 bpl.s receiver_cost
 neg.w %d2
receiver_cost:
 add.w %d2,-28(%a6)
 move.w (%a0),%d1
 sub.w -4(%a6),%d1
 move.w %d1,-10(%a6)
 bpl.s span
 neg.w %d1
span:
 cmpi.w #32,%d1
 blt.w next
 cmpi.w #144,%d1
 bgt.w next
 move.w -24(%a6),%d2
 sub.w -2(%a6),%d2
 move.w %d2,-12(%a6)
 bpl.s dy_abs
 neg.w %d2
dy_abs:
 cmpi.w #80,%d2
 bgt.w next
 add.w %d1,%d2
 cmpi.w #180,%d2
 bgt.w next
 move.w %d2,%d3
 lsr.w #2,%d3
 add.w %d3,-28(%a6)
 mulu.w #12,%d2
 move.w %d2,-18(%a6)
 move.w -10(%a6),%d1
 muls.w %d1,%d1
 move.w -12(%a6),%d2
 muls.w %d2,%d2
 add.l %d1,%d2
 move.l %d2,-16(%a6)
 | Receiver must have an actual free native shooting lane.
 move.l %a3,-(%sp)
 movea.l %a0,%a3
 btst #3,0x62(%a3)
 bne.s human_lane
 jsr 0x2DD014
 bra.s lane_return
human_lane:
 jsr 0x2DD018
lane_return:
 movea.l (%sp)+,%a3
 tst.w %d0
 beq.w next
 | Measure separation of the far-post shooting ray from the actual keeper.
 moveq #-16,%d1
 tst.w -6(%a6)
 bpl.s ray_post
 moveq #16,%d1
ray_post:
 sub.w -26(%a6),%d1
 move.w -8(%a6),%d2
 sub.w -24(%a6),%d2
 bmi.s beyond_keeper
 muls.w %d2,%d1
 move.w #264,%d2
 sub.w -24(%a6),%d2
 divs.w %d2,%d1
 add.w -26(%a6),%d1
 sub.w -6(%a6),%d1
 bpl.s ray_abs
 neg.w %d1
ray_abs:
 cmpi.w #24,%d1
 blt.w next
 bra.s ray_cost
beyond_keeper:
 moveq #48,%d1
ray_cost:
 add.w %d1,%d1
 sub.w %d1,-28(%a6)
 btst #3,0x62(%a0)
 beq.s defenders
 subi.w #64,-28(%a6)            | free humans retain co-op priority
defenders:
 movea.l %a5,%a1
 moveq #5,%d7
defender:
 tst.w 0x34(%a1)
 bmi.s defender_next
 btst #2,0x63(%a1)
 bne.s defender_next
 move.w (%a1),%d1
 sub.w (%a0),%d1
 muls.w %d1,%d1
 move.w 0x14(%a1),%d2
 sub.w 0x14(%a0),%d2
 muls.w %d2,%d2
 add.l %d1,%d2
 cmpi.l #676,%d2
 blt.w next
 move.w (%a1),%d1
 sub.w -4(%a6),%d1
 move.w 0x14(%a1),%d2
 btst #7,0x62(%a3)
 bne.s defender_depth
 neg.w %d2
defender_depth:
 sub.w -2(%a6),%d2
 move.w %d1,%d3
 muls.w -10(%a6),%d3
 move.w %d2,%d4
 muls.w -12(%a6),%d4
 add.l %d4,%d3
 ble.s defender_next
 cmp.l -16(%a6),%d3
 bge.s defender_next
 muls.w -12(%a6),%d1
 muls.w -10(%a6),%d2
 sub.l %d2,%d1
 bpl.s corridor_abs
 neg.l %d1
corridor_abs:
 moveq #0,%d2
 move.w -18(%a6),%d2
 cmp.l %d2,%d1
 ble.w next
defender_next:
 adda.w #128,%a1
 dbra %d7,defender
 move.w -28(%a6),%d1
 cmp.w -20(%a6),%d1
 bge.s next
 move.w %d1,-20(%a6)
 move.w 0x52(%a0),-22(%a6)
next:
 adda.w #128,%a0
 dbra %d6,receiver
done:
 moveq #-1,%d0
 move.w -22(%a6),%d0
 movem.l (%sp)+,%d1-%d7/%a0-%a5
 unlk %a6
 rts

| At the point, feed a free forward receiver; otherwise retain the original point-shot decision.
| Returns global teammate or -1 unchanged native fallback.
point_choice:
 movem.l %d1-%d4/%a0,-(%sp)
 jsr 0x2D880C
 tst.w %d0
 beq.w point_no
 btst #2,0xFFFFC2FA
 bne.w point_no
 btst #1,0x64(%a3)
 bne.w point_no
 move.w 0x52(%a3),%d0
 cmp.w 0xFFFFB7AA,%d0
 bne.w point_no
 move.w 0x14(%a3),%d3
 btst #7,0x62(%a3)
 bne.s point_depth
 neg.w %d3
point_depth:
 cmpi.w #88,%d3
 blt.w point_no
 cmpi.w #160,%d3
 bgt.w point_no
 move.w (%a3),%d4
 bpl.s point_abs
 neg.w %d4
point_abs:
 cmpi.w #128,%d4
 bgt.w point_no
 jsr 0x2D89B0
 tst.w %d0
 bmi.s point_shot
 cmpi.w #6,0x52(%a3)
 bcs.s point_global
 addq.w #6,%d0
point_global:
 move.w %d0,%d2
 lsl.w #7,%d0
 lea 0xFFFFB04A,%a0
 adda.w %d0,%a0
 move.w 0x14(%a0),%d1
 btst #7,0x62(%a3)
 bne.s point_receiver_depth
 neg.w %d1
point_receiver_depth:
 addi.w #24,%d3
 cmp.w %d3,%d1
 blt.s point_shot
 moveq #0,%d0
 move.w %d2,%d0
 bra.s point_done
point_shot:
point_no:
 moveq #-1,%d0
point_done:
 movem.l (%sp)+,%d1-%d4/%a0
 rts

| The point carrier may skate into range while a covered forward develops.
| No free pass is discarded; this is called only after both pass scans failed.
point_carry:
 movem.l %d1-%d4/%a0-%a1,-(%sp)
 jsr 0x2D880C
 tst.w %d0
 beq.w carry_no
 btst #2,0xFFFFC2FA
 bne.w carry_no
 btst #1,0x64(%a3)
 bne.w carry_no
 move.w 0x52(%a3),%d0
 cmp.w 0xFFFFB7AA,%d0
 bne.w carry_no
 move.w 0x14(%a3),%d3
 btst #7,0x62(%a3)
 bne.s carry_depth
 neg.w %d3
carry_depth:
 cmpi.w #88,%d3
 blt.w carry_no
 cmpi.w #160,%d3
 bgt.w carry_no
 move.w (%a3),%d0
 bpl.s carry_abs
 neg.w %d0
carry_abs:
 cmpi.w #100,%d0
 bgt.w carry_no
 lea 0xFFFFB04A,%a0
 lea 0xFFFFB34A,%a1
 cmpi.w #6,0x52(%a3)
 bcs.s carry_bases
 exg %a0,%a1
carry_bases:
 moveq #5,%d4
carry_pressure:
 tst.w 0x34(%a1)
 ble.s carry_pressure_next
 btst #2,0x63(%a1)
 bne.s carry_pressure_next
 move.w (%a1),%d1
 sub.w (%a3),%d1
 muls.w %d1,%d1
 move.w 0x14(%a1),%d2
 sub.w 0x14(%a3),%d2
 muls.w %d2,%d2
 add.l %d2,%d1
 cmpi.l #3136,%d1
 blo.w carry_no
carry_pressure_next:
 adda.w #128,%a1
 dbra %d4,carry_pressure
 addi.w #24,%d3
 moveq #5,%d4
carry_friend:
 cmpa.l %a3,%a0
 beq.s carry_friend_next
 tst.w 0x34(%a0)
 ble.s carry_friend_next
 btst #2,0x63(%a0)
 bne.s carry_friend_next
 move.w (%a0),%d0
 cmpi.w #-128,%d0
 blt.s carry_friend_next
 cmpi.w #128,%d0
 bgt.s carry_friend_next
 move.w 0x14(%a0),%d0
 btst #7,0x62(%a3)
 bne.s carry_friend_depth
 neg.w %d0
carry_friend_depth:
 cmpi.w #252,%d0
 bgt.s carry_friend_next
 cmp.w %d3,%d0
 bge.s carry_yes
carry_friend_next:
 adda.w #128,%a0
 dbra %d4,carry_friend
carry_no:
 moveq #0,%d0
 bra.s carry_done
carry_yes:
 moveq #1,%d0
carry_done:
 movem.l (%sp)+,%d1-%d4/%a0-%a1
 rts
