-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBANK_PLY.asm
600 lines (426 loc) · 15.2 KB
/
BANK_PLY.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
; Copyright (C)2020 Andrew Davie
SLOT 1 ;TODO
NEWBANK BANK_PLY ; ROM SHADOW
;---------------------------------------------------------------------------------------------------
DEF NewPlyInitialise
SUBROUTINE
REFER GenerateAllMoves
REFER negaMax
VEND NewPlyInitialise
; This MUST be called at the start of a new ply
; It initialises the movelist to empty
; x must be preserved
; note that 'alpha' and 'beta' are set externally!!
lda #-1
sta@PLY moveIndex ; no valid moves
sta@PLY bestMove
lda enPassantPawn ; flag/square from last actual move made
sta@PLY enPassantSquare ; used for backtracking, to reset the flag
; The value of the material (signed, 16-bit) is restored to the saved value at the reversion
; of a move. It's quicker to restore than to re-sum. So we save the current evaluation at the
; start of each new ply.
lda Evaluation
sta@PLY savedEvaluation
lda Evaluation+1
sta@PLY savedEvaluation+1
rts
;---------------------------------------------------------------------------------------------------
DEF CheckMoveListFromSquare
SUBROUTINE
REFER IsValidMoveFromSquare
VEND CheckMoveListFromSquare
; X12 in A
; y = -1 on return if NOT FOUND
ldy@RAM moveIndex
bmi .exit
.scan cmp MoveFrom,y
beq .scanned
dey
bpl .scan
.exit rts
.scanned lda@PLY MovePiece,y
sta fromPiece
rts
;---------------------------------------------------------------------------------------------------
DEF GetPieceGivenFromToSquares
SUBROUTINE
REFER GetPiece
VEND GetPieceGivenFromToSquares
; returns piece in A+fromPiece
; or Y=-1 if not found
; We need to get the piece from the movelist because it contains flags (e.g., castling) about
; the move. We need to do from/to checks because moves can have multiple origin/desinations.
; This fixes the move with/without castle flag
ldy@PLY moveIndex
;bmi .fail ; shouldn't happen
.scan lda fromX12
cmp@PLY MoveFrom,y
bne .next
lda toX12
cmp@PLY MoveTo,y
beq .found
.next dey
bpl .scan
.fail rts
.found lda@PLY MovePiece,y
sta fromPiece
rts
;---------------------------------------------------------------------------------------------------
DEF selectmove
SUBROUTINE
COMMON_VARS_ALPHABETA
REFER aiComputerMove
VEND selectmove
; RAM bank already switched in!!!
; returns with RAM bank switched
IF DIAGNOSTICS
lda #0
sta positionCount
sta positionCount+1
sta positionCount+2
;sta maxPly
ENDIF
lda #<INFINITY
sta __beta
lda #>INFINITY
sta __beta+1
lda #<-INFINITY
sta __alpha
lda #>-INFINITY
sta __alpha+1 ; player tries to maximise
ldx #SEARCH_DEPTH
lda #0 ; no captured piece
sta __quiesceCapOnly ; ALL moves to be generated
jsr negaMax
ldx@PLY bestMove
bmi .nomove
; Generate player's moves in reply
; Make the computer move, list player moves (PLY+1), unmake computer move
stx@PLY movePtr
jsr MakeMove
jsr ListPlayerMoves
lda #RAMBANK_PLY
sta SET_BANK_RAM
jsr unmakeMove
; Grab the computer move details for the UI animation
lda #RAMBANK_PLY
sta SET_BANK_RAM
ldx@PLY bestMove
lda@PLY MoveTo,x
sta toX12
lda@PLY MoveFrom,x
sta originX12
sta fromX12
lda@PLY MovePiece,x
sta fromPiece
.nomove
rts
;---------------------------------------------------------------------------------------------------
DEF GenCastleMoveForRook
SUBROUTINE
REFER MakeMove
REFER CastleFixupDraw
VEND GenCastleMoveForRook
clc
lda fromPiece
and #FLAG_CASTLE
beq .exit ; NOT involved in castle!
ldx #4
lda fromX12 ; *destination*
.findCast clc
dex
bmi .exit
cmp KSquare,x
bne .findCast
lda RSquareEnd,x
sta toX12
sta@PLY secondaryBlank
ldy RSquareStart,x
sty fromX12
sty originX12
sty@PLY secondarySquare
lda fromPiece
and #128 ; colour bit
ora #ROOK ; preserve colour
sta fromPiece
sta@PLY secondaryPiece
sec
.exit rts
;---------------------------------------------------------------------------------------------------
DEF CastleFixupDraw
SUBROUTINE
REFER aiSpecialMoveFixup
VEND CastleFixupDraw
; fixup any castling issues
; at this point the king has finished his two-square march
; based on the finish square, we determine which rook we're interacting with
; and generate a 'move' for the rook to position on the other side of the king
IF CASTLING_ENABLED
jsr GenCastleMoveForRook
bcs .phase
ENDIF
SWAP
rts
.phase
; in this siutation (castle, rook moving) we do not change sides yet!
PHASE AI_MoveIsSelected
rts
KSquare .byte 24,28,94,98
RSquareStart .byte 22,29,92,99
RSquareEnd .byte 25,27,95,97
;---------------------------------------------------------------------------------------------------
MAC XCHG ;{name}
lda@PLY {1},x
sta __xchg
lda@PLY {1},y
sta@PLY {1},x
lda __xchg
sta@PLY {1},y
ENDM
DEF Sort
SUBROUTINE
REFER GenerateAllMoves
VAR __xchg, 1
VEND Sort
;lda currentPly
;sta savedBank ; ??
lda __quiesceCapOnly
bmi .exit ; only caps present so already sorted!
ldx@PLY moveIndex
ldy@PLY moveIndex
.next dey
bmi .exit
lda@PLY MoveCapture,y
beq .next
XCHG MoveFrom
XCHG MoveTo
XCHG MovePiece
XCHG MoveCapture
dex
bpl .next
.exit
; Scan for capture of king
ldx@PLY moveIndex
.scanCheck lda@PLY MoveCapture,x
beq .check ; since they're sorted with captures "first" we can exit
and #PIECE_MASK
cmp #KING
beq .check
dex
bpl .scanCheck
lda #0
.check sta flagCheck
rts
;---------------------------------------------------------------------------------------------------
; QUIESCE!
;int Quiesce( int alpha, int beta ) {
; int stand_pat = Evaluate();
; if( stand_pat >= beta )
; return beta;
; if( alpha < stand_pat )
; alpha = stand_pat;
; until( every_capture_has_been_examined ) {
; MakeCapture();
; score = -Quiesce( -beta, -alpha );
; TakeBackMove();
; if( score >= beta )
; return beta;
; if( score > alpha )
; alpha = score;
; }
; return alpha;
;}
DEF quiesce
SUBROUTINE
; pass...
; x = depthleft
; SET_BANK_RAM --> current ply
; __alpha[2] = param alpha
; __beta[2] = param beta
COMMON_VARS_ALPHABETA
REFER selectmove
REFER negaMax
VEND quiesce
lda currentPly
cmp #RAMBANK_PLY + MAX_PLY_DEPTH_BANK -1
bcs .retBeta
; The 'thinkbar' pattern...
lda #0
ldy INPT4
bmi .doThink
lda __thinkbar
asl
asl
asl
asl
ora #2
sta COLUPF
inc __thinkbar
lda __thinkbar
and #15
tay
lda SynapsePattern2,y
.doThink sta PF1
sta PF2
; ^
lda __beta
sta@PLY beta
lda __beta+1
sta@PLY beta+1
lda __alpha
sta@PLY alpha
lda __alpha+1
sta@PLY alpha+1
; int stand_pat = Evaluate();
; if( stand_pat >= beta )
; return beta;
sec
lda Evaluation
sbc@PLY beta
lda Evaluation+1
sbc@PLY beta+1
bvc .spat0
eor #$80
.spat0 bmi .norb ;pl .retBeta ; branch if stand_pat >= beta
.retBeta lda beta
sta __negaMax
lda beta+1
sta __negaMax+1
.abort rts
.norb
; if( alpha < stand_pat )
; alpha = stand_pat;
sec
lda alpha
sbc Evaluation
lda alpha+1
sbc Evaluation+1
bvc .spat1
eor #$80
.spat1 bpl .alpha ; branch if alpha >= stand_pat
; alpha < stand_pat
lda Evaluation
sta@PLY alpha
lda Evaluation+1
sta@PLY alpha+1
.alpha
jsr GenerateAllMoves
lda flagCheck
bne .abort ; pure abort
ldx@PLY moveIndex
bmi .exit
.forChild stx@PLY movePtr
; The movelist has captures ONLY (ref: __quiesceCapOnly != 0)
jsr MakeMove
sec
lda #0
sbc@PLY beta
sta __alpha
lda #0
sbc@PLY beta+1
sta __alpha+1
sec
lda #0
sbc@PLY alpha
sta __beta
lda #0
sbc@PLY alpha+1
sta __beta+1
inc currentPly
lda currentPly
sta SET_BANK_RAM ; self-switch
jsr quiesce
dec currentPly
lda currentPly
sta SET_BANK_RAM
jsr unmakeMove
lda flagCheck ; don't consider moves which leave us in check
bne .inCheck
sec
;lda #0 ; already 0
sbc __negaMax
sta __negaMax
lda #0
sbc __negaMax+1
sta __negaMax+1 ; -negaMax(...)
; if( score >= beta )
; return beta;
sec
lda __negaMax
sbc@PLY beta
lda __negaMax+1
sbc@PLY beta+1
bvc .lab0
eor #$80
.lab0 bmi .nrb2 ; .retBeta ; branch if score >= beta
jmp .retBeta
.nrb2
; if( score > alpha )
; alpha = score;
; }
sec
lda@PLY alpha
sbc __negaMax
lda@PLY alpha+1
sbc __negaMax+1
bvc .lab2
eor #$80
.lab2 bpl .nextMove ; alpha >= score
; score > alpha
lda __negaMax
sta@PLY alpha
lda __negaMax+1
sta@PLY alpha+1
.nextMove ldx@PLY movePtr
dex
bpl .forChild
; return alpha;
.exit
lda@PLY alpha
sta __negaMax
lda@PLY alpha+1
sta __negaMax+1
rts
.inCheck lda #0
sta flagCheck
beq .nextMove
SynapsePattern2
.byte %11000001
.byte %01100000
.byte %00110000
.byte %00011000
.byte %00001100
.byte %00000110
.byte %10000011
.byte %11000001
.byte %10000011
.byte %00000110
.byte %00001100
.byte %00011000
.byte %00110000
.byte %01100000
.byte %11000001
.byte %10000011
;---------------------------------------------------------------------------------------------------
DEF AddMovePly
SUBROUTINE
REFER AddMove
VEND AddMovePly
tya
ldy@PLY moveIndex
iny
sty@PLY moveIndex
sta@PLY MoveTo,y
tax ; used for continuation of sliding moves
lda currentSquare
sta@PLY MoveFrom,y
lda currentPiece
sta@PLY MovePiece,y
lda capture
sta@PLY MoveCapture,y
rts
;---------------------------------------------------------------------------------------------------
CHECK_BANK_SIZE "BANK_PLY"
;---------------------------------------------------------------------------------------------------
; EOF