; ------------------------------------------------------------------ net ; A net scores PA (on roll) against PB from a base position whose ; first-layer sums it keeps: only the inputs that differ are added. ; ; The inputs, as counts: per side and point, one checker, two or more, ; three or more and the number beyond three, then the checkers off (202); ; the pip lead in buckets of 8 (9); each side's checkers back, 1 to 4 or ; more (8); and gnubg's features for each side (50). A net takes the ; first 202, 219 or 269. ; ; The first layer's weights are stored plus 128, as bytes 0 to 255, a row ; of H per input; an input counted k more times adds its row k times, and ; the 128s come off at the end. ; ; A net: +0 H, +1 1 if linear, +2 inputs (2), +4 the rows (2), +6 the ; biases (2), +8 the output weights (2), +10 the output bias (3), +13 its ; base (2), a page: BPOS equ 0 ; the base position (64) BOFF equ 64 ; its inputs: the checkers off (2) BBACK equ 66 ; checkers back (2) BBUCK equ 68 ; the pip lead's bucket ($ff: none) BSUM equ 69 ; its checkers on the board (2) BPIPS equ 71 ; its pips (2 x 2) BFEAT equ 80 ; gnubg's features (50) BSUMS equ 130 ; the first-layer sums (2H) ; NST, from BOFF: the same for PA/PB. ; eval: IX -> a net -> RES = its score of PA/PB (and SUMS, NST, FEAT). eval: ld l,(ix+13) ld h,(ix+14) push hl pop iy ld a,h ld (RPAGE),a ld l,BSUMS ld de,SUMS ld c,(ix+0) ld b,0 sla c ldir ld l,BBACK ld de,NST+2 ld bc,9 ldir ld hl,0 ld (NETK),hl ; the points xor a ld (SIDE),a ld hl,PA call eside ld a,1 ld (SIDE),a ld hl,PB call eside ; the checkers off ld a,(NST+5) neg add a,15 ld (NST),a ld c,a ld b,(iy+BOFF) ld hl,100 call applyi ld a,(NST+6) neg add a,15 ld (NST+1),a ld c,a ld b,(iy+BOFF+1) ld hl,201 call applyi ld a,(ix+2) cp 202 jp z,finish ; the pip lead, plus four buckets, in buckets of 8 ld hl,(NST+9) ld de,(NST+7) or a sbc hl,de ld de,32 add hl,de xor a bit 7,h jr nz,.b ld a,h or a ld a,8 jr nz,.b ld a,l rrca rrca rrca and $1f cp 8 jr c,.b ld a,8 .b: ld (NST+4),a ld b,(iy+BBUCK) cp b jr z,.nb push af ld a,b inc a jr z,.nob dec a ld hl,202 call addhla ld bc,$100 call applyi .nob: pop af ld hl,202 call addhla ld bc,1 call applyi .nb: ; checkers back, as thermometers ld hl,211 ld de,NST+2 call therm ld hl,215 ld de,NST+3 call therm ld a,(ix+2) cp 219 jr z,finish ; gnubg's features push ix ld hl,PA ld de,PB ld ix,FEAT call half ld hl,PB ld de,PA ld ix,FEAT+25 call half pop ix ld hl,FEAT .f: push hl ld c,(hl) ld a,(RPAGE) ld h,a ld b,(hl) ld a,l sub low FEAT ld l,a ld h,0 ld de,219 add hl,de call applyi pop hl inc l ld a,l cp low FEAT+50 jr nz,.f ; finish: RES from SUMS, less the 128 x NETK the stored weights add. finish: ld hl,(NETK) add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ex de,hl ld hl,SUMS ld b,(ix+0) .c: ld a,(hl) sub e ld (hl),a inc l ld a,(hl) sbc a,d ld (hl),a inc l djnz .c bit 0,(ix+1) jr z,.mlp ld hl,(SUMS) ld (RES),hl ld a,h rla sbc a,a ld (RES+2),a ret .mlp: ld a,(ix+10) ld (RES),a ld a,(ix+11) ld (RES+1),a ld a,(ix+12) ld (RES+2),a ld l,(ix+8) ld h,(ix+9) ld (W2P),hl ld hl,SUMS ld b,(ix+0) .h: push bc ld e,(hl) inc l ld d,(hl) inc l push hl ; the sigmoid table's index: the sum halved, within -128..127 sra d rr e ld a,e rla ld a,d adc a,0 jr z,.inr ld a,d rla ld a,255 jr nc,.t xor a jr .t .inr: ld a,e xor $80 .t: ; the table holds its upper half: below, 255 less the mirror sub 128 jr nc,.hi neg ld hl,SIG call index cpl jr .sg .hi: ld hl,SIG call index .sg: or a jr z,.nx0 ld e,a ld d,0 ld hl,(W2P) ld a,(hl) inc hl ld (W2P),hl or a push af jp p,.pos neg .pos: call mul pop af ld de,RES jp m,.sub ld a,(de) add a,l ld (de),a inc de ld a,(de) adc a,h ld (de),a inc de ld a,(de) adc a,0 ld (de),a jr .nx .sub: ld a,(de) sub l ld (de),a inc de ld a,(de) sbc a,h ld (de),a inc de ld a,(de) sbc a,0 ld (de),a jr .nx .nx0: ld hl,(W2P) inc hl ld (W2P),hl .nx: pop hl pop bc djnz .h ret ; rebase: IX -> a net: PA/PB scored (RES), and made its base. rebase: call eval ld a,(RPAGE) ld d,a ld e,0 ld hl,PA ld bc,64 ldir ld hl,NST ld bc,11 ldir ld e,BFEAT ld hl,FEAT ld bc,50 ldir ld e,BSUMS ld hl,SUMS ld c,(ix+0) ld b,0 sla c ldir ret ; therm: HL = the first of 4 inputs, DE -> the new count in NST (the ; base's at the same place in its page): checkers back as a thermometer. therm: ld a,(de) ld c,a ld a,(RPAGE) ld d,a ld a,(de) ld b,a ld e,4 .t: push bc push de push hl ld a,c call gt0 ld c,a ld a,b call gt0 ld b,a call applyi pop hl pop de pop bc inc hl dec b dec c dec e jr nz,.t ret gt0: or a ret z bit 7,a ld a,0 ret nz inc a ret ; eside: HL -> PA or PB (SIDE 0 or 1): each point differing from the ; base's, its inputs' rows added or taken away, and NST's checkers on the ; board, pips and checkers back updated. eside: ld a,(RPAGE) ld d,a ld a,(SIDE) rrca rrca rrca ld e,a ; 0 or 32 ld b,25 .l: ld a,(de) cp (hl) call nz,point inc hl inc e djnz .l ret ; point: 25 - B = the point, A = the base's checkers there, (HL) = ; PA/PB's. point: push bc push de push hl ld c,a ld a,25 sub b ld b,a ld a,c ld (PTOLD),a ld e,a ld a,(hl) ld (PTNEW),a sub e ld c,a ; checkers on the board, and back ld hl,NST+5 ld a,(SIDE) call index ld a,c add a,(hl) ld (hl),a ld a,b cp 18 jr c,.nb ld hl,NST+2 ld a,(SIDE) call index ld a,c add a,(hl) ld (hl),a .nb: ; pips: the point's, C times ld a,(SIDE) add a,a ld hl,NST+7 call index push hl ld e,(hl) inc hl ld d,(hl) .p: ld a,c or a jr z,.pd ld a,b inc a bit 7,c jr nz,.pm dec c add a,e ld e,a jr nc,.p inc d jr .p .pm: inc c ld l,a ld a,e sub l ld e,a jr nc,.p dec d jr .p .pd: pop hl ld (hl),e inc hl ld (hl),d ; its first input's row: 101 x side + 4 x point ld a,(SIDE) or a jr z,.s0 ld a,101 .s0: ld c,a ld a,b add a,a add a,a add a,c ld e,a ld d,0 call mulh ld e,(ix+4) ld d,(ix+5) add hl,de ld (ROWB),hl ; a checker at a time, from the base's count to PA/PB's: adding ; one to a point of n adds the row for one checker (n = 0), for two ; less that for one (1), for three (2), or beyond three (3 or more) .c: ld a,(PTOLD) ld hl,PTNEW cp (hl) jr z,.done ld e,1 jr c,.up dec a ld e,-1 ld (PTOLD),a jr .go .up: inc a ld (PTOLD),a dec a .go: ld hl,(ROWB) ld b,e ld e,(ix+0) ld d,0 or a jr z,.r dec a jr z,.two add hl,de add hl,de dec a jr z,.r add hl,de .r: ld a,b call rows jr .c .two: push hl push de push bc ld a,b neg call rows pop bc pop de pop hl add hl,de jr .r .done: pop hl pop de pop bc ret ; mulh: HL = DE x the net's H, which is 1, 4, 8 or 48. mulh: ex de,hl ld a,(ix+0) srl a ret c add hl,hl add hl,hl cp 2 ret z add hl,hl cp 4 ret z add hl,hl ld d,h ld e,l add hl,hl add hl,de ret ; applyi: HL = an input, B, C = its count in the base and now: its row ; added the difference in times. applyi: ld a,c sub b ret z push af ex de,hl call mulh ld e,(ix+4) ld d,(ix+5) add hl,de pop af ; rows: HL -> a row, A = how many times to add it (negative: take away). ; The weights are popped two at a time, so interrupts must be off; with H ; odd the last pair's second, the next row's first, goes into a spare sum. rows: ld c,a push hl ld l,a rla sbc a,a ld h,a ld de,(NETK) add hl,de ld (NETK),hl pop hl ld a,c .r: push af push hl ld (SPSAVE),sp ld sp,hl ld hl,SUMS ld b,(ix+0) inc b srl b or a jp m,.s .a: pop de ld a,e add a,(hl) ld (hl),a inc l jr nc,.a1 inc (hl) .a1: inc l ld a,d add a,(hl) ld (hl),a inc l jr nc,.a2 inc (hl) .a2: inc l djnz .a jr .e .s: pop de ld a,(hl) sub e ld (hl),a inc l jr nc,.s1 dec (hl) .s1: inc l ld a,(hl) sub d ld (hl),a inc l jr nc,.s2 dec (hl) .s2: inc l djnz .s .e: ld sp,(SPSAVE) pop hl pop af or a jp m,.inc dec a ret z jr .r .inc: inc a ret z jr .r