choose.asm
Choosing a move: the filter, the contact (or race) net, and a look a ply ahead over the opponent's 21 rolls; and the same look ahead for the cube. Download · All the source
; --------------------------------------------------------------- choose; decide: the play from ROOT with dice DHI >= DLO -> RESULT, and A = 0; if there is none (RESULT = ROOT).;; The filter keeps the best 12 plays, the contact net (or the race net); the best 2 of those; for each, over the opponent's 21 rolls, their; reply is chosen by the filter (best 5) and the reply net (or race), and; the position after it scored by the contact (or race) net. A play; bearing off the last checker is taken at once.;; Plays are kept in lists, best first: a count, a capacity, and from +16,; 16 bytes each: a key of 5 (the score from the opponent's side, lower; better, then the place in generation order, big-endian) and the play's; steps (4 points, $ff after the last, and their 4 dice).decide: di ld hl,ROOT ld de,RESULT call copy64 ld hl,ROOT ld de,TOP12 call plays ret z ld de,WINSTEPS ld a,(WIN) or a jr nz,.done dec hl ld a,h or l ld de,TOP12+21 jr z,.done ; the best 12 to the best 2, from the opponent's side ld hl,ROOT ld de,PA call turn call setbase ld hl,TOP12 ld de,TOP2 ld bc,s_last call restage ; each against the opponent's rolls ld de,TOP2+21 call look ld hl,TOTAL ld de,BEST ld bc,4 ldir ld de,TOP2+37 call look ld hl,(BEST) ld de,(TOTAL) or a sbc hl,de ld hl,(BEST+2) ld de,(TOTAL+2) sbc hl,de ld de,TOP2+21 jp p,.done ld de,TOP2+37.done: call fromroot ld hl,W ld de,RESULT call copy64 ld a,1 ret; look: DE -> a candidate play's steps: TOTAL = the sum over the; opponent's rolls (non-doubles twice) of its value after their reply.look: call fromroot; lookw: the same for the position in W.lookw: ld hl,W ld de,CAND call copy64 ld hl,CAND ld de,PA call copy64 call setbase ld hl,CAND ld de,ROOT2 call turn ld hl,0 ld (TOTAL),hl ld (TOTAL+2),hl inc l ld h,l.roll: ld (RA),hl call TICK ; the caller's, each roll (any registers) call reply call addtot ld hl,(RA) ld a,l cp h call nz,addtot ld hl,(RA) ld a,h cp l inc h jr c,.roll ld h,1 inc l ld a,l cp 7 jr c,.roll ret; ply1: the side on roll's equity in ROOT a ply deeper, for the cube:; over its 21 rolls, its play chosen by the filter and the reply net and; the position after scored by the contact (or race) net, as `look` scores; a candidate against the replies. RES = the mean, rounded toward 0.ply1: di ld hl,ROOT ld de,W call turn call lookw ; RES = -TOTAL / 36 (TOTAL is within 24 bits) ld hl,(TOTAL) ld a,(TOTAL+2) ld c,a ld a,(TOTAL+3) or a push af call m,neg24 ; |TOTAL| xor a ld b,24.d: add hl,hl rl c rla cp 36 jr c,.n sub 36 inc l.n: djnz .d pop af call p,neg24 ; TOTAL is the other side's: ours negated ld (RES),hl ld a,c ld (RES+2),a ret; ply1c: ply1 with the side on roll's plays chosen by the contact (or; race) net rather than the reply net: better, and slower.ply1c: ld a,1 ld (PLYBY),a call ply1 xor a ld (PLYBY),a ret; neg24: CHL = -CHL.neg24: xor a sub l ld l,a ld a,0 sbc a,h ld h,a ld a,0 sbc a,c ld c,a ret; reply: RES = the value to us (CAND) of the opponent's roll RA, RB.reply: ld hl,(RA) ld (DHI),hl ld hl,ROOT2 ld de,TOP5 call plays jr nz,.some ; they cannot move: our position as it is ld hl,CAND ld de,PA call copy64 jp s_last.some: ld a,(WIN) or a jr z,.pick ; they bear off their last checker: 1, 2 or 3 points to them ld hl,WINSTEPS call replay ld hl,W+OPPOFF call total cp 15 ld b,$e0 jr nz,.pts ld hl,W+OPPOFF+18 ld b,7 xor a.bk: or (hl) inc hl djnz .bk ld b,$a0 jr nz,.pts ld b,$c0.pts: ld hl,RES ld (hl),0 inc hl ld (hl),b inc hl ld (hl),$ff ret.pick: dec hl ld a,h or l ld hl,TOP5+21 jr z,.one ld hl,TOP5 ld de,TOP1 ld bc,s_reply ld a,(PLYBY) or a jr z,.by ld bc,s_last.by: call restage ld hl,TOP1+21.one: call replay call fromopp jp s_last; plays: HL -> a board, DE -> a list: its plays, scored by the filter; from the other side, the best in the list. HL = GCOUNT, Z if none. The; filter scores the board turned; the move generator adds each step's; change to that.plays: ld (CURLIST),de xor a ld (de),a ld (WIN),a push hl call total sub 5 sbc a,a ld (WINPOSS),a pop hl push hl ld de,PA call turn ld ix,NET_FILTER call eval ld hl,(RES) ld (FSCORE),hl ld hl,leafs ld (USERFN),hl pop hl call gen ld hl,(GCOUNT) ld a,h or l ret; restage: HL -> a list, DE -> another, BC -> a scorer: the first's plays; scored from the other side, the best in the second.restage: ld (SCORER),bc ld (CURLIST),de xor a ld (de),a ld b,(hl) ld de,16 add hl,de.e: push bc push hl push hl ld de,5 add hl,de call replay call fromopp ld hl,.r push hl ld hl,(SCORER) jp (hl).r: pop hl push hl ld de,5 add hl,de ld de,NEWSTEPS ld bc,8 ldir pop hl inc hl inc hl inc hl ld d,(hl) inc hl ld e,(hl) ld (CURIDX),de call mkkey call linsert pop hl ld de,16 add hl,de pop bc djnz .e ret; addtot: TOTAL += RES.addtot: ld a,(RES+2) rla sbc a,a ld c,a ld hl,RES ld de,TOTAL ld b,3 or a.l: ld a,(de) adc a,(hl) ld (de),a inc hl inc de djnz .l ld a,(de) adc a,c ld (de),a ret; leafs: a generated play: taken at once if it bears off the last; checker, else into the list by its filter score.leafs: ld a,(WIN) or a ret nz ld a,(WINPOSS) or a jr z,.nowin ld hl,W call total or a jr nz,.nowin inc a ld (WIN),a call mksteps ld hl,NEWSTEPS ld de,WINSTEPS ld bc,8 ldir ret.nowin: ld hl,(FSCORE) ld (RES),hl ld a,h rla sbc a,a ld (RES+2),a ld hl,(GCOUNT) ld (CURIDX),hl call mkkey ; a full list: no better than its last, no further ld iy,(CURLIST) ld a,(iy+0) cp (iy+1) jr c,.in ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl ld de,(CURLIST) add hl,de ld de,NEWKEY ld b,3.q: ld a,(de) cp (hl) jr c,.in ret nz inc hl inc de djnz .q ret.in: call mksteps jr linsert; mksteps: NEWSTEPS = the play's steps, $ff for those not taken, and; their dice.mksteps: ld hl,NEWSTEPS ld b,4.c: ld (hl),$ff inc hl djnz .c ld a,(GTARGET) ld b,a ld de,STEPS ld hl,NEWSTEPS.s: ld a,(de) ld (hl),a inc e inc e inc hl djnz .s ld hl,GDIE ld de,NEWSTEPS+4 ld bc,4 ldir ret; linsert: NEWKEY and NEWSTEPS into the list at CURLIST, in their place; if among the best.linsert: ld iy,(CURLIST) push iy pop hl ld de,16 add hl,de ld b,0.f: ld a,b cp (iy+0) jr z,.at push hl ld de,NEWKEY ld c,5.cmp: ld a,(de) cp (hl) jr c,.lt jr nz,.gt inc hl inc de dec c jr nz,.cmp.gt: pop hl ld de,16 add hl,de inc b jr .f.lt: pop hl.at: ld a,b cp (iy+1) ret nc push hl ld a,(iy+0) cp (iy+1) jr c,.room dec a ; full: the last falls off jr .mv.room: inc (iy+0).mv: sub b ; entries to move down jr z,.put ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl ld b,h ld c,l pop hl push hl add hl,bc dec hl ld d,h ld e,l ld a,16 call addea lddr.put: pop de ld hl,NEWKEY ld bc,13 ldir ret; mkkey: NEWKEY from RES and CURIDX.mkkey: ld hl,NEWKEY ld a,(RES+2) xor $80 ld (hl),a inc hl ld a,(RES+1) ld (hl),a inc hl ld a,(RES) ld (hl),a inc hl ld de,(CURIDX) ld (hl),d inc hl ld (hl),e retaddea: add a,e ld e,a ret nc inc d ret; fromroot: DE -> a play's steps: W = ROOT after it.fromroot: ld hl,ROOT ld (GROOT),hl ex de,hl; replay: HL -> a play's steps: W = the board at GROOT after it.replay: push hl ld hl,(GROOT) ld de,W call copy64 pop hl ld b,4.s: ld a,(hl) cp $ff ret z push bc push hl ld b,a ld de,4 add hl,de ld e,(hl) call step pop hl pop bc inc hl djnz .s ret; fromopp: PA/PB = W from the other side.fromopp: ld hl,W ld de,PA; turn: HL -> a board, DE -> 64 bytes: the board from the other side.turn: push hl ld bc,OPPOFF add hl,bc ld c,32 ldir pop hl ld c,32 ldir retcopy64: ld bc,64 ldir ret; The scores of PA/PB, into RES: the contact net, or the race net; the; reply net, or the race net.s_last: call contact jr nc,s_race ld ix,NET_CONTACT jp evals_race: ld ix,NET_RACE jp evals_reply: call contact jr nc,s_race ld ix,NET_REPLY jp eval; setbase: PA/PB as the nets' base (the contact net's only in contact).setbase: ld ix,NET_RACE call rebase ld ix,NET_REPLY call rebase call contact ret nc ld ix,NET_CONTACT jp rebase; init: the work area cleared, the hash values made, the lists' sizes,; and the nets' bases set to no inputs at all.init: ld hl,WORK ld de,WORK+1 ld bc,WORKEND-WORK-1 ld (hl),0 ldir ld hl,1 ld de,RTAB ld b,102.r: ld a,h rra ld a,l rra xor h ld h,a ld a,l rra ld a,h rra xor l ld l,a xor h ld h,a ex de,hl ld (hl),e inc hl ld (hl),d inc hl ex de,hl djnz .r ld a,$ff ld (ECACHE),a ld (ECACHE+34),a ld hl,TOP12+1 ld (hl),12 inc h ld (hl),2 inc h ld (hl),5 inc h ld (hl),1 ld hl,NETS ld b,4.n: push bc ld e,(hl) inc hl ld d,(hl) inc hl push hl push de pop ix ld l,(ix+6) ld h,(ix+7) ld d,(ix+14) ld e,BSUMS ld c,(ix+0) ld b,0 sla c ldir ld e,BBUCK ld a,$ff ld (de),a pop hl pop bc djnz .n ret