โปรแกรมหมากรุกที่เล็กที่สุด


19

แรงบันดาลใจจากนี้บอกบทความล่าสุดของโปรแกรมเมอร์ชาวฝรั่งเศสที่เขียน 487 ไบต์ผู้เล่น 2 คน (มนุษย์กับมนุษย์) โปรแกรมหมากรุกในสภาผมสงสัยว่าโปรแกรมหมากรุกขนาดเล็กอาจจะอยู่ในภาษาอื่น ๆ

รายละเอียด

  • โปรแกรมจะต้องยอมรับการย้ายหมากรุกตามกฎหมายเท่านั้น
  • การประกาศการตรวจสอบ / การตรวจสอบไม่จำเป็น (เพียงต้องการ) แม้ว่ากฎข้อแรกจะใช้ในกรณีของการตรวจสอบ
  • ตามบทความการ castling ไม่จำเป็นต้องใช้งาน
  • นอกจากนี้คุณไม่จำเป็นต้องติดตั้ง en passant
  • อย่างไรก็ตามคุณต้องอนุญาตให้มีการเลื่อนตำแหน่งเมื่อถึงอันดับที่แปด (คุณอาจเลือกบังคับให้เปลี่ยนเป็นราชินี)
  • ขึ้นอยู่กับว่าคุณจะแสดงบอร์ดอย่างไร - เทอร์มินัล ASCII, GUI, ฯลฯ
  • คุณต้องแสดงว่ามันคือเทิร์นไหน

สามารถพบกฎของหมากรุกได้ที่นี่ - ละเว้นกฎทัวร์นาเมนต์ที่ระบุ (เช่นเวลาการสัมผัส) และการจำการโยนและการเดินไม่จำเป็นต้องดำเนินการ


เมื่อคุณพูดว่า "ผู้เล่น 2 คน" ผมเข้าใจชิ้นเพียงแค่ย้ายสำหรับ 2 ผู้เล่นของมนุษย์ไม่ได้เป็นบอเช่นนี้codegolf.stackexchange.com/q/12397/15599 โปรแกรมจะต้องยอมรับการเคลื่อนไหวทางกฎหมายเท่านั้นหรือไม่ ถ้าเป็นเช่นนั้นcodegolf.stackexchange.com/q/10843/15599มีความเกี่ยวข้อง ในที่สุดcodegolf.stackexchange.com/q/8911/15599เป็นเรื่องเกี่ยวกับการตรวจสอบตรวจสอบ / คู่ คุณต้องระบุให้แน่นยิ่งขึ้นว่าโปรแกรมต้องทำอะไรไม่งั้นจะยอมรับได้ว่ามีโปรแกรมที่พิมพ์ตำแหน่งเริ่มต้นจากนั้นก็ยอมรับการเคลื่อนไหวครั้งแรกเช่นการa1 h8ย้ายเกมแนวทแยงมุมไปที่มุมตรงข้ามกระโดดข้ามเบี้ย
Level River St

10
ฉันคิดว่าคุณควรจะต้องใช้ความเพี้ยนและความอดทน! ทำไมพลาดกฎกติกาหมากรุกบ้าง?

3
Kieran คุณอาจต้องการตรวจสอบแซนด์บ็อกซ์ (ดู "เด่นในเมตาดาต้า") สำหรับความท้าทายครั้งต่อไปของคุณ
เลเวลริเวอร์เซนต์

1
ฉันขอแนะนำให้คุณระบุสิ่งที่จะต้องแสดงเมื่อถึงคราว (ซึ่งยังไม่ได้รับการชี้แจง) นอกจากนี้ฉันกังวลเล็กน้อยเกี่ยวกับการที่ผู้คนจะตีความ "รูปแบบที่ไม่ชัดเจน" สำหรับอินพุต แต่ฉันก็อยากรู้เกี่ยวกับมัน
เลเวลริเวอร์เซนต์

1
บางทีคุณอาจสร้างหรือเชื่อมโยงรายการกฎทั้งหมดที่จำเป็นในการท้าทายนี้ได้เช่นคนที่ไม่มีประสบการณ์หมากรุกมาก่อนก็สามารถเข้าร่วมได้เช่นกัน?
ข้อบกพร่อง

คำตอบ:


21

C, 650 600

n=8,t=65,s,f,x,y,p,e,u=10,w=32,z=95;char a[95],b[95]="RNBKQBNR";v(){p=a[s]&z;y=f/u-s/u;x=f-s-y*u;e=x*x+y*y;n=s%u/8|f%u/8|a[s]/w-t/w|a[f]/w==t/w|!(p==75&e<3|p>80&x*y==0|p%5==1&x*x==y*y|p==78&e==5|p==80&x*(z-t)>0&(a[f]-w?e==2:e==1|e==4&s%5==1));if(!n&&p-78)for(e=(f-s)/abs(x*x>y*y?x:y),x=s;(x+=e)-f;)n|=a[x]-w;}main(){for(a[93]=40;n--;a[92]=47)sprintf(a,"%s%cP    p%c \n",a,b[n],b[n]+w);for(;1;){puts(a);for(n=1;n;){putchar(t);scanf("%d%d",&s,&f);v();memcpy(b,a,z);if(!n){a[f]=p-80|f%u%7?a[s]:t+16;a[s]=w;a[f]&z^75||(a[z-t/w]=f);f=a[z-t/w];t^=w;for(n=1,s=80;n&&s--;)v();if(n=!n)memcpy(a,b,z),t^=32;}}}}

เพื่อลดรหัสสำหรับการเริ่มต้นบอร์ดจอแสดงผลมีการเล่นสีขาว (ตัวพิมพ์ใหญ่) จากซ้ายไปขวาและดำ (ตัวพิมพ์เล็ก) เล่นจากขวาไปซ้าย อินพุตอยู่ในรูปแบบของตัวเลขทศนิยม 2 หลักสองตำแหน่ง (ตำแหน่งเริ่มต้นและตำแหน่งสิ้นสุด) ให้ไฟล์ (0-7) และอันดับ (0-7) สำหรับรหัสเพิ่มเติมเล็กน้อย (ลบ 11 จากแต่ละอินพุต) สามารถป้อนข้อมูลให้สอดคล้องกับhttp://en.wikipedia.org/wiki/ICCF_numeric_notation (ตัวเลข 1-8)

นี่เป็นภาพตัวอย่างที่แบล็กเพิ่งทำ Rook's Pawn สีขาวพยายามเคลื่อนไหวที่ผิดกฎหมายต่าง ๆ กับราชินีของเขาก่อนที่จะจับจำนำในที่สุด ไฟเลี้ยวaสำหรับสีดำและAสีขาว

ป้อนคำอธิบายรูปภาพที่นี่

คุณสมบัติที่น่าสนใจของการตรวจสอบของฉันคือการใช้สแควร์ของระยะทางแบบยุคลิด สำหรับอัศวินนี่คือ 1 ^ 2 + 2 ^ 2 = 5 เสมอ แต่ฉันก็ใช้มันเพื่อราชาและผู้จำนำด้วย

การทดสอบเพื่อตรวจสอบทำได้โดยการสำรองกระดานดำเนินการย้ายผู้เล่นและสแกนการเคลื่อนไหวของคู่ต่อสู้ที่เป็นไปได้ทั้งหมด 64 รายการ

โปรแกรมจะต้องจบลงด้วย Ctrl-C ฉันไม่สามารถคิดวิธีที่สง่างามในการทำมันนอกเหนือไปจากการย้ายพิเศษเพื่อจบโปรแกรม เกมหมากรุกจะจบลงจริง ๆ เมื่อผู้เล่นคนหนึ่งไม่สามารถเดินไปตามทางของเขา (รุกฆาตหรือจนมุม) และต้องมีการทดสอบมากมายที่ไม่ได้กำหนดโดยสเป็ค

รหัสแสดงความคิดเห็น

n=8,t=65,s,f,x,y,p,e,u=10,w=32,z=95;                 // 8,10 height and width of board. w=ASCII space, also difference between ucase and lcase
                                                     // 95 is bitmask for conversion lowercase to uppercase, but also used as length of array, etc.
char a[95],b[95]="RNBKQBNR";                         // a is main board, b is backup board (but used at start to hold 1st row data.)

v(){                                                 // validate move in all aspects except check
  p=a[s]&z;                                          // p=uppercase(character on start square)
  y=f/u-s/u;                                         // signed distance in y direction
  x=f-s-y*u;                                         // and x direction
  e=x*x+y*y;                                         // square of Euclidean distance
  n=s%u/8|f%u/8|                                     // n=true if 2nd digit of input out of bounds OR
  a[s]/w-t/w|a[f]/w==t/w|                            // start sq not friendly piece OR finish sq is friendly piece (also eliminates case where start=finish)
  !(                                                 // OR NOT geometry valid
    p==75&e<3|                                       // 'K'(ASCII75) AND euclidean distance squared =1 or 2 OR
    p>80&x*y==0|                                     // 'Q'or'R' AND x or y = 0 OR
    p%5==1&x*x==y*y|                                 // 'Q'or'B' AND abs(x)=abs(y)
    p==78&e==5|                                      // 'N' AND euclidean distance squared = 5
    p==80&x*(z-t)>0&(a[f]-w?e==2:e==1|e==4&s%5==1)   // 'P'(ASCII80):x direction must correspond with case of player (z-t)
  );                                                 // if capturing e=2. Otherwise e=1 (except on start rows 1 and 6, e can be 4)
  if(!n&&p-78)                                       // if not yet invalid and piece not 'N'(ASCII78) 
    for(e=(f-s)/abs(x*x>y*y?x:y),x=s;(x+=e)-f;)      // Set e to the numeric difference to travel 1 square in right direction. Set x to start square
       n|=a[x]-w;                                    // and iterate x through all intervening squares, checking they are blank
}



main(){

  for(a[93]=40;n--;a[92]=47)                         // iterate n through 8 rows of board. vacant spaces in bracket are use to assign start positions of kings to a[92&93] 
    sprintf(a,"%s%cP    p%c \n",a,b[n],b[n]+w);      // build up start position, each row 10 squares wide, including filler space the end and newline

  for(;1;){                                          // loop forever   
    puts(a);                                         // display board
    for(n=1;n;){                                     // loop while move invalid
      putchar(t);                                    // display prompt 'A' for white 'a' for black
      scanf("%d%d",&s,&f);                           // get input
      v();                                           // validate move
      memcpy(b,a,z);                                 // backup board (and king position metadata)  
      if(!n){                                        // if move not yet invalid
        a[f]=p-80|f%u%7?a[s]:t+16;                   // if not a pawn on last row, content of finish square = start square, ELSE queen of correct case (t+16) 
        a[s]=w;                                      // start square becomes blank (ASCII32)
        a[f]&z^75||(a[z-t/w]=f);                     // if finish square king, update king position metadata
        f=a[z-t/w];                                  // to begin scanning to see if king in check, set f to current king position
        t^=w;                                        // and change colour
        for(n=1,s=80;n&&s--;)v();                    // for s=79..0 search for valid opponent move to capture king (stops with n=0)
        if(n=!n)memcpy(a,b,z),t^=32;                 // valid opponent threat on king means invalid player move. Invert n, recover board from backup and change colour back.
      }
    }    
  }
}

รหัสที่ดี! สองแนวคิด: 32 เป็นค่าคงที่ (คุณใช้บ่อย) s,fจำเป็นต้องเริ่มต้นใหม่หรือไม่ ช่องว่างในช่องสี่เหลี่ยมที่ว่างเปล่านั้นเป็น IMO
randomra

@randomra ขอบคุณ! ฉันได้เพิ่มการทดสอบ Check Check ดังนั้นการเล่นกอล์ฟจึงเป็นภารกิจต่อไป ฉันใช้ 32 สำหรับสองสิ่งที่แตกต่างกัน: รหัส ASCII สำหรับช่องว่างและเพื่อแยกความแตกต่างระหว่างบล็อก ASCII ของ 32 (การควบคุม / สัญลักษณ์ / ตัวพิมพ์ใหญ่ / ตัวพิมพ์เล็ก) ฉันจะทำให้มันคงที่ นอกจากนี้ฉันใช้ 95 เป็น bitmask สำหรับการแปลงตัวพิมพ์ใหญ่เป็นตัวพิมพ์เล็ก (แต่ฉันได้วางแผนที่จะใช้หมายเลขเดิมสำหรับสิ่งอื่น ๆ อีกมากมาย) การเริ่มต้นใช้งานของsการพกพาจากระยะก่อนหน้านี้ ฉันลบมันทันที
เลเวลริเวอร์เซนต์

1
e=y*y+x*x=f-s-u*y=f/u-s/u;คุณสามารถเชื่อมได้รับมอบหมาย:
randomra

@randomra ขอบคุณฉันคิดว่าจะให้ข้อผิดพลาดการคอมไพล์ "l-value required" แต่มันรวบรวมและดูเหมือนว่าจะทำงานได้ดี สมมติว่าค่า l เป็นตัวแปรสุดท้ายก่อนที่=จะดูเหมือนการตีความเท่านั้น เกี่ยวกับe=y*y+x*(x=..ฉันค่อนข้างระวังลำดับการดำเนินการเนื่องจากฉันได้รับคำตอบที่ไม่ถูกต้องจากการโต้แย้งในprintfคำสั่ง แต่ในกรณีนี้ดูเหมือนว่าจะทำงานได้ดีกับ GCC / Cygwin ฉันจะรอการเปลี่ยนแปลงเพิ่มเติมก่อนที่จะรวมไว้ในรหัส สิ่งหนึ่งที่ขาดหายไปคือการตรวจสอบตัวเลขที่อยู่นอกช่วง 0..77 (ซึ่งฉันไม่เห็นตามที่กำหนดโดยมาตรฐาน แต่อย่างไรก็ตาม .. )
เลเวลริเวอร์เซนต์

1
สองการเปลี่ยนแปลงที่เห็นได้ชัด: t^=32การt^=wและการa[95],b[95] a[z],b[z]รหัสสามารถอ่านได้อย่างน่าประหลาดใจ อาจเป็นเพราะความเห็น verbose!
randomra

13

Python 3, 1166 1071 993 ไบต์

ฉันเพิ่งรู้ว่าฉันต้องการที่จะหยุดกษัตริย์ไม่ให้ย้ายเข้ามาตรวจสอบหลังจากที่ฉันทำเสร็จแล้ว แต่นี่คือการส่งของฉัน

h=abs
m=range
l=print
o=" "
a=o*8
j=[list(s)for s in["RNBKQBNR","P"*8,a,a,a,a,"p"*8,"rnbkqbnr"]]
u=False
v=lambda c:(c.lower()==c)==u
while 1:
 l("b"if u else"w")
 for b in j:l(*b)
 q,r,s,t=[int(i)for i in input().split()];P=j[r][q];g=j[t][s];p=P.lower()
 def w():
  if g==o or not v(g):j[t][s]=P;j[r][q]=o;global u;u=not u
 if not v(P):break
 if p=="r"or p=="q":
  for a,b,c,d in[(q,r,s,t),(r,q,t,s)]:
   if a==c:
    x=h(d-b)//(d-b)
    for n in m(b+x,d,x):
     if j[n if b else r][q if b else n]!=o:break
    else:w()
 if p=="b"or p=="q":
  if h(q-s)==h(r-t):
   for n in m(1, h(q-s)):
    if j[r+(n if t>r else-n)][q+(n if s>q else-n)]!=o:break
   else:w()
 if p=="k"and h(q-s)<2 and h(r-t)<2 or(p=="n"and(h(q-s)==2 and h(r-t)==1 or h(r-t)==2 and h(q-s)==1)):w()
 if p=="p":
  f=t-r==(-1 if u else 1)
  if(g!=o and not v(g)and h(q-s)==1 and f)or(g==o and q==s and f)or(g==o and q==s and t-r==(-2 if u else 2)and r==(6 if u else 1)):
   w()
   if t==(0 if u else 7):j[t][s]="q"if u else"Q"

ในการเล่นให้ป้อนหมายเลขที่คั่นด้วยช่องว่างสี่หมายเลข 2 ตัวแรกเป็นพิกัดของชิ้นส่วนที่คุณต้องการย้ายและอันดับที่สองคือตำแหน่งที่คุณต้องการย้ายไป


1
สำหรับการเริ่มต้นบอร์ดของคุณคุณสามารถใช้สิ่งนี้แทนเพื่อการประหยัดที่ยิ่งใหญ่:a=o*8;j=[list(s) for s in ["RNBKQBNR","P"*8,a,a,a,a,"p"*8,"rnbkqbnr"]]
นามแฝง

นอกจากนี้ยังมี.spilt()ค่าเริ่มต้นที่การแยกที่ช่องว่างดังนั้นคุณสามารถใช้input().split()แทนinput().split(" ")
pseudonym117

คุณไม่ต้องการช่องว่างระหว่างตัวอักษรและคำหลัก [ตามลำดับ] (เช่น2and, 1orฯลฯ )
Zacharý

False0!=0สามารถ
Zacharý

ยังไม่ได้ทดสอบ แต่ฉันคิดว่าFalseน่าจะเป็น0- not 0ควรจะทำงานได้ดี ...
อาร์ทิมิสสนับสนุนโมนิก้า

6

ขออภัยในความล่าช้า.

โปรแกรมนี้เรียกว่า ChesSkelet ขณะนี้มันใช้ 352 ไบต์สำหรับรหัสและข้อมูล มันเขียนในชุด Z80 และโดยเฉพาะอย่างยิ่งสำหรับ ZX Xpectrum

หากคุณไม่ต้องการรวบรวมและโหลดในโปรแกรมจำลองคุณสามารถเล่นออนไลน์ในไซต์ ChesSkelet ( http://chesskelet.x10host.com )

โปรแกรมนี้ค่อนข้างเรียบง่ายมีลูปขนาดใหญ่ที่: - หรือ (1) อินพุตสีขาวย้ายหรือ (2) สีดำวิ่งเป็น AI ขนาดเล็กที่จะย้าย - บอร์ดอัพเดทในหน้าจอ อีกครั้งมีคำแนะนำขนาดใหญ่ที่อธิบายถึงโปรแกรมและเทคนิคต่าง ๆ ในเว็บไซต์

; ----------------------------------------------------------------------------- ; CHESSKELET /tseske'let/ ; Alex Garcia (reeagbo), Boria Labs 2018-2019 ; Thanks, @MstrBlinky and @johan_koelman, for your contribution ; Developed with ZXSpin, Notepad++ ; ----------------------------------------------------------------------------- ; Compilation with ZXSpin (all versions) and SpectNetIde (not all versions) ; Run with RANDOMIZE USR 30000 ; ----------------------------------------------------------------------------- ; debug mode: 0 = no, 1 = yes debmod equ 0 ; gramod: 0 = minimal interface, 1 = basic interface, 2 = full interface gramod equ 0 ; feamod: 0 = no features (if fails at legadd 'ret'), 1 = all features feamod equ 0 ; ROM memory addresses clescr equ 3503 laskey equ 23560 ; memory micro-pages (256B, typically H register) used for simple memory access auxsth equ $7D piearh equ $7E movlih equ $7F boasth equ $80 boaath equ $81 boaoph equ $82 canlih equ $83 org 30000 ; code is not directly portable ;------------------------------------------------------------------------------ ; Common code before turns ;------------------------------------------------------------------------------ ; legal moves generation (3B) ----------------------------------------- befmov call genlis ; candidate move list, used for both sides ; switch sides on every loop (6B+1B) ---------------------------------- whomov ld l, h ; (H)L: $7F7F = movlih + gamsta, ++ ld a, (hl) ; load state xor h ; (@johan_koelman) switch turn: bla=0, whi=1 ld (hl), a ; save state back in memory if feamod>0 jp z, blamov else jr z, blamov ; if 0, jump to black moves, jp maybe endif ; clear screen (3B) whimov call clescr ; ROM routine set screen mode ; print board ----------------------------------------------------------------- priboa ; A, B = 0 at this point ; initialization (4B) ld h, boasth ; H(L)= $80, L always 0, load board ++ ld d, piearh ; D(E): piece array pointer, E o/w later priloo ; print colored squares (8B) if gramod>0 ; opt: print colored squares ld a, 19 ; set bright ASCII code rst 16 ; print value ld a, c ; (@MstrBlinky) C is always $21 inc c ; change C parity and %00000001 ; keep Ab0, alternatively 0/1 rst 16 ; print value endif ; print piece (10B) ld a, (hl) ; load piece and %00100000 ; keep color, pih ld b, a ; Bb5: isolate piece color ld e, (hl) ; load piece res 5, e ; uncolor, pih ld a, (de) ; load piece character sub b ; capitalize (-32) only for white pieces rst 16 ; print piece ; next square, end of rank/board detection (15B+1B) inc l ; next square jp m, pricoo ; (@johan_koelman) end of 16x8 board, A=128? ld a, l ; (@MstrBlinky) and $08 ; 8 if end of rank, 0 other cases jr z, priski ; skip if not end of the rank add a, l ; ld l, a ; return result to L ld a, 13 ; A=
    rst 16          ; print char

if gramod>0         ; opt: print colored squares, end of the rank
    inc c           ; change C parity
endif

priski  jr priloo       ; loop through all squares

; print coords (28B+6B)--------------------------------------------------------
pricoo              ; (@MstrBlinky simplified it)
if gramod>0         ; opt: print board coords
    ld bc, $0709        ; B: loop count, C: fixed rank/col

nextce  ld a, $16           ; ASCII control code for AT         
    rst 16              ; print it
        ld a, b         ; set rank
        rst 16              ; print it
        ld a, c         ; set column
        rst 16              ; print it
    ld a, '8'       ; base rank
    sub b           ; decrease rank character (8..1)
    rst 16          ; print rank value

    ld a, $16           ; ASCII control code for AT
        rst 16              ; print it
        ld a, c         ; set rank
        rst 16              ; print it
        ld a, b         ; sets column
        rst 16              ; print it
    ld a, 'a'       ; base column character
    add a, b        ; increase rank character (a..h)
    rst 16          ; print rank value

    dec b           ; loop 8 times
    jp p, nextce        ;
endif

if gramod>0         ; opt:  + "?" for input prompt
    ld a, 13        ; A: set  ASCII code
    rst 16          ; prints it to go to the next line for input
    ld a, '?'       ; set "?" ASCII code
    rst 16          ; print it
endif
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               WHITE MOVES 
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; read chars from keyboard and stores them (16B(+4B+4B))-----------------------
    ; 4 times loop for coord input (3B)
    ld b, 4         ; loop count
    dec d           ; D(E)= $7D =auxsth, E always 0 ++

    ; read key from keyboard loop (8B)
realoo  ld hl, laskey           ; LASTKEY system variable ++
    xor a           ; A=0
    ld (hl), a      ; reset LASTKEY, two birds with 1 stone
wailoo  add a, (hl)             ; load latest value of LASTKEY.
    jr z, wailoo            ; loop until a key is pressed.

    ; skip move/switch sides (4B)
if feamod>0         ; opt: special move, switch sides to play black
    cp 's'          ; if "s" pressed at any time
    jp z, aftmov        ; skip white's move, ### jr maybe
endif
    ; save pressed key and print it (5B)
    inc de          ; (@MstrBlinky) next char, E = 1 to 5
    ld (de), a      ; save char in string
    rst 16          ; print it

    djnz realoo     ; loop for 4 input chars

    ; border reset (4B)
if gramod>1         ; opt: border reset after first white move
    ld a, 7         ; set back to white
    out (254), a        ; set border back to white
endif

; translate coords to square (17B) --------------------------------------------
movchk  ex de, hl       ; (@MstrBlinky routine) DE=end of input string

movloo  ld a, 56        ; rank calc = 8-(rank input-48) = 56-(HL)
    sub (hl)        ; A= 56 - (HL)
    rla         ; move it to high nibble (x16)
    rla         ;
    rla         ;
    rla         ;

    dec hl          ; (@MstrBlinky) run backwards through string
    add a, (hl)     ; rank + column (not 0-7 column)
    sub 'a'         ; make it a 0-7 column

    ld c, b         ; slide results through B and C
    ld b, a         ; at end of 2nd loop everything is in place

    dec l           ; (@MstrBlinky) beginning of input string?
    jr nz, movloo       ; if not, loop again

; search white move in legal move list (24B) ----------------------------------
if feamod>0         ; opt: validate white move
seamov  ld hl, canlis       ; canli pointer ++
    ld a, (hl)      ; number of candidates
    ;inc hl         ; skip to first candidate (+2 bytes)
    ;inc hl         ; removed v0.808, no move in those two bytes

sealoo  ld d, (hl)      ; origin candidate move
    inc hl          ; next byte
    ld e, (hl)      ; target candidate move
    inc hl          ; next byte, for next loop

    ex de, hl       ; candidate pair, DE: HL-canli pointer
    or a            ; reset carry
    sbc hl, bc      ; compare input move with cand. move (Z)
    ex de, hl       ; revert back, canli pointer
    jr z, aftsid        ; move match: jump out. ready to move
                ; B (origin sq), C (target sq) ready here
    dec a           ; count down
    jr nz, sealoo       ; loop until canli covered

    jp whimov       ; if not found, back to move input, jp maybe
else                ; opt: skip validate white move
    jr aftsid       ; Outputs: B: origin square, C: target square
endif
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               BLACK MOVES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
blamov
chomov  ; preparations (7B)----------------------------------------------------
    ld hl, canlis       ; candidate list. No H reuse ++
    ld b, (hl)      ; number of candidates at position 0
    ld c, l         ; C=0, maximum valuation reset
    inc hl          ; skip 2 bytes to first candidate in list
    inc hl          ;
choloo  ; loop through candidates (6B) ----------------------------------------
    ld d, (hl)      ; D: origin candidate square
    inc hl          ; next candidate byte
    ld e, (hl)      ; E: target candidate square
    inc hl          ; next candidate byte
    push bc         ; BC released
    push hl         ; HL is different from here
    ; pieces valuation ----------------------------------------------------
    ; pieces collection (8B)
evatap  ld h, boasth        ; board base ++
    ld l, e         ; target square
    ld b, (hl)      ; black piece value
    ld l, d         ; origin square
    ld c, (hl)      ; white piece value
    res 5, c        ; uncolor white piece; pih

    ; origin attacked square (7B)
evaato  ld a, b         ; target piece always counts
    ld h, boaoph        ; H(L): attacked board base, L: unchanged ++
    bit 7, (hl)     ; target square attacked?
    jr z, evaatt        ; not attacked, skip counting origin piece

if feamod=1         ; opt: rows 2 do not move even if attacked  
    ld a, d         ; 0rrr0ccc, add origin square     
    and $70         ; filter ranks
    cp $60          ; is rank 6?
    ld a, b         ; target piece always counts
    jr z, evaexi        ; skip this move
endif

    ; count origin piece (1B) if attacked, general case
evaatc  add a, c        ; A: 00pppppp, count white

    ; target attacked square (6B)
evaatt  ld l, e         ; H(L): point at target square
    bit 7, (hl)     ; target square attacked?
    jr z, skiato        ; if target not attacked, skip
    sub c           ; if target attacked, count white out  

    ; compensate + prioritize piece valuation(6B)
skiato  ld h, $20       ; prepare H for later rotation and use for A
    add a, h        ; A: 00pppppp, compensate=K+1, pih                                             
    rlca            ; leave space for square weight
    rlca            ; A: pppppp00, piece addition is 5 bits
    ld b, a         ; B: piece addition value
evacol  ld a, e         ; A: 0rrr0ccc
    ; these two values below can be tuned for different opening schemes
    if feamod>0
        add a, 2        ; A: 0rrr0ccc
        and 5           ; A: 00000ccc
    else
        inc a           ; A: 0rrr0ccc
        and 4           ; A: 00000cc0 (weight: 0,0,0,4,4,4,4,0)
    endif

    ; ranks weight (ranks weight is 8..1, aiming for board's end)
evarnk  add hl, hl      ; HL: 00100000 0rrr0ccc (before)
    add hl, hl      ; 
    add hl, hl      ; HL: 000000rr r0ccc000 (after)
    sub h           ; A:  00000cww (w=r+c)
    add a, b        ; total value: pieces + weight

    ; maximum value comparison (12B)
evaexi  pop hl          ; recover canli
    pop bc          ; recover previous maximum value
    cp c            ; compare with current maximum
    jr c, chonoc        ; if current eval (A) <= max eval (C), skip

    ld c, a         ; update best evaluation
    pop af          ; remove old maximum to avoid cascades in stack
                ; ### initial push to compensate?
    push de         ; push best candidates so far

chonoc  dec b           ; decrease loop counter 2 by 2.
    djnz choloo     ; loop through all candidates (canto)

    pop bc          ; recover saved values (B: origin, C: target)

; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               AFTER SIDES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; move piece (8B) -------------------------------------------------------------
    ; inputs here: B: origin square, C: target square
    ; write origin square and read piece in it (4B)
aftsid  ld h, boasth        ; point at board (canlih=$83 before) ++
    ld l, b         ; point at origin square

    ; castling, rook moves, v0.800 (26B)
    ; very innacurate as it may cause false moves
if feamod>0         ; opt: castling, rook move
casroo  ld a, (hl)      ; origin piece
    add a, b        ; + origin square
    sub c           ; - target square
caslon  cp $38          ; $36(king) + $74(ori) - $72(tar)= $38, pih
    jr nz, cassho       ; no long castling
    ld l, $70       ; long castling rook square (a1)
    ld (hl), d      ; erase rook (D=0 here)
    ld l, $73       ; rook destination (d1)
    ld (hl), $25        ; move rook, pih
cassho  cp $34          ; $36(king) + $74(ori) - $76(tar)= $34, pih
    jr nz, casend       ; no short castling
    ld l, $77       ; short castling rook square (h1)
    ld (hl), d      ; erase rook (D=0 here)
    ld l, $75       ; rook destination (f1)
    ld (hl), $25        ; move rook, pih
casend
endif

if feamod>0         ; opt: special move: prom, no under-prom (12B)
    ld a, c         ; A: 0rrr0ccc
    and %01110000       ; A: 0rrr0000
    add a, (hl)     ; A: 0rrxpppp
    cp $22          ; white pawn ($22) on rank 8 ($00), pih
    ld l, b         ; restore origin square
    ld d, (hl)      ; original piece
    ld (hl), 0      ; write origin piece
    jr nz, aftdes       ; if not a pawn, skip
    ld d, $27       ; make piece a queen, pih
else                ; opt: write origin piece, no promotion (3B)
    ld d, (hl)      ; D: get origin piece
    ld (hl), 0      ; write origin piece    
endif

    ; write target square with origin piece (5B)
aftdes  ld l, c         ; (H)L: target square

    ; checkmate with exit (3B), board is not updated in screen
chkmat  bit 4, (hl)     ; captured piece is king ($16)?, pih 
    ret nz          ; (@johan_koelman) return prompt at check mate

aftnok  ld (hl), d      ; write target square
    call genlis     ; update attacked matrix after move
aftmov
; reverse board (22B)----------------------------------------------------------
revboa  ; push full board to stack (7B)
    inc h           ; H = $80 = boasth ++
    ld l, h         ; (H)L: end of board. trick: start from $8080
revlo1  dec l           ; countdown squares
    ld a, (hl)      ; read piece
    push af         ; copy piece to to stack
    jr nz, revlo1       ; loop down to beginning of the board

    ; collect board back ir reverse order + switch color (15B)
    ld l, $78       ; (H)L: end of board again
revlo2  pop af          ; collect piece from stack
    or a            ; is it an empty square?
    jr z, revski        ; if yes, skip
    xor %00100000       ; otherwise, reverse color (b5), pih
revski  dec l           ; countdown squares
    ld (hl), a      ; piece back into board
    jr nz, revlo2       ; loop until beginning of board

    jp befmov       ; back to white move, too far for jr

; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               AUXILIARY ROUTINES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

; genlis: generates list of legal moves (92B + 9B) ----------------------------
; it was not possible to use it in two different places, only procedure in code
genlis
bacata  ; backup attack board in reverse order, used in evaluation (13B)
    ld l, $FF       ; (H)L = $80FF (boaata-1), H always $80 
    ld de, boaopo + $78 ; DE: same thing, 1B passed end of board
bacloo  inc hl          ; HL: increase 16b counter to hop to next page
    dec e           ; E:  decrease 8b counter to hit Z flag
    ld a, (hl)      ; load attack status
    ld (hl), 0      ; clear attack status, no alternative!
    ld (de), a      ; backup attack status
    jr nz, bacloo       ; loop down to square $00
                ; exit values: DE=$8200, HL=$8177

    ; prepare environment (4B)
    inc d           ; D= $83= canlih
    xor a           ; reset
    ld (de), a      ; cantot= 0
    ld b, l         ; B= L = 77, SQUARE COUNT

    ; read piece from board (4B)
squloo  ld h, boasth        ; H: board base ++
    ld l, b         ; point at current loop square
    ld a, (hl)      ; read piece from board

    ; king castling, v0.800 (15B)
    ; only basic rule: no unmoved pieces or attacked squares check
    if feamod>0
    kincas  ld l, a     ; save A (can't use push AF, flags lost)
        add a, b    ; A: 0rrr0xxx + 000ppppp (uncolored white p.)
        cp $AA      ; king($36) at E1($74)= $AA, pih
        ld a, l     ; recover A
        jr nz, kinend   ; if no match, skip adding legal move

        ld c, $72   ; E1-C1 move, rook's move missing
        call legadd ; add king's move
        ld c, $76   ; E1-G1 move, rook's move missing
        call legadd ; add king's move and go on with king's moves
    kinend
    endif

    ; get move type and pointer to move list (6B)
squgon  dec h           ; H(L)= movlih, moves vector base ++
    add a, a        ; x4, each piece vector is 4B long
    add a, a        ;   
    ld l, a         ; (H)L points at the move vector now

    ld d, 2         ; 2 submoves per piece
subloo      ; byte 1 - move type (5B)
        ld a, (hl)      ; move type loaded
        or a            ; =cp 0, 2nd move type not used case
                    ; black/empty: move type=0 leads here
        jr z, squexi        ; ---v exit: square is done
        ld e, a         ; E: MOVE TYPE (B,C,D used here)

        ; pawn 2 squares forward - move type modified (8B)
        if feamod>0     ; opt: special move, pawn 2 sq. forward
        genpw2  add a, b    ; piece square + move type
            and %11111000   ; masked with relevant bits
            cp $88      ; $28(str.pawn)+$60(rnk 6) ### univocal
            jr nz, skppw2   ; if not, skip
            inc e       ; increase radius: 1 -> 2
        skppw2
        endif

        ; byte 2 - movlis delta (3B)
        inc hl          ; next piece sub-entry
        push hl         ; Save HL for 2nd loop  
        ld l, (hl)      ; pointer to move delta

vecloo          ; vector read (8B)
            ld c, b     ; TARGET SQUARE init
            ld a, (hl)  ; vector delta
            or a        ; =cp 0
            jr z, vecexi    ; ---v exit: vectors end with 0, next sq.
            push hl     ; save current delta
            push de     ; save move type + radius
                    ; E: variable radius within loop
            ld d, a     ; D: store delta within loop

celloo              ; prepare x88 check (7B)
                ld a, d     ; delta loaded
                add a, c    ; current target (sq. + delta)
                ld c, a     ; current target
                and $88     ; 0x88, famous OOB trick
                jr nz, vecnex   ; ---v exit: OOB, next vector

                ; read target square (3B)
                inc h       ; H(L)= $80 = boasth ++
                ld l, c     ; point at target square            
                ld a, (hl)  ; read target square content

                ; mark attacked ### str. pawn marked attacked
                    inc h       ; H(L)= $81 = boaath ++
                    ld (hl), h  ; mark attacked ($81)
                    dec h       ; H(L)= $80 = boasth ++

                dec h       ; H(L)= $79= movlih ++
                ; target is white (4B)
                bit 5, a    ; is it white?, pih
                jr nz, vecnex   ; ---v exit: WHITE b4=1, next vector

                ; target not white (3B)
                or a        ; =cp 0, is it empty?, pih
                jr z, taremp    ; if not 0, it's black: legal, no go on

tarbla              ; target is black (7B)
                bit 5, e    ; special move: pawn straight check
                jr nz, vecnex   ; ---v exit: no straight capture, next vector
                ld e, a     ; make radius=0 (=<8 in code, canonical: ld e, 0)
                jr legadj   ;

taremp              ; target is empty (14B)
                bit 4, e    ; special move: pawn on capture check
                jr nz, vecnex   ; ---v exit: no diagonal without capture, next vector     
                dec e       ; decrease radius
legadj
                if feamod=0 ; opt: legadd for basic model
                ; add candidate (B: current square, C: target square) (9B)
                    push hl
                    ld hl, canlis   ; HL: start of candidate list. No H reuse ++
                    inc (hl)    ; +2 to candidate counter to move to next
                    inc (hl)    ; first free position in list
                    ld l, (hl)  ; point at free position

                    ld (hl), b  ; 1) save origin square
                    inc hl      ; move to next byte
                    ld (hl), c  ; 2) save dest square                   
legend                  pop hl      ; recover HL=pointer to vector list
                else        ; opt: legadd call for full model
                    call legadd
                endif

                bit 3, e    ; if radius < 8 (Cb3=0), radius limit
                jr nz, celloo   ; ---^ cell loop

vecnex          ; next vector preparation (5B)
            pop de      ; DE: recover move type + radius
            pop hl      ; HL: recover current vector
            inc hl      ; HL: next vector
            jr vecloo   ; ---^ vector loop

vecexi  ; next square preparation (5B)
    pop hl          ; HL: recover pointer to sub-move list
    inc hl          ; HL: next byte, point at 2nd sub-move
    dec d           ; 2 sub-move iterations loop control
    jr nz, subloo       ; if not 2nd iteration, repeat loop
    ; end of loop (2B)      
squexi  djnz squloo     ; ---^ squares loop
    ret

; legadd: add legal move -------------------------------------------------------
if feamod>0         ; legadd for king castling
legadd              ; (B: current square, C: target square)
    push hl
    ld hl, canlis       ; HL: start of candidate list. No H reuse ++
    inc (hl)        ; +2 to candidate counter to move to next
    inc (hl)        ; first free position in list
    ld l, (hl)      ; point at free position

    ld (hl), b      ; 1) save origin square
    inc hl          ; move to next byte
    ld (hl), c      ; 2) save dest square                   
    pop hl          ; recover HL=pointer to vector list
    ;ret            ; <===== not removed with feamod=0
endif

; -----------------------------------------------------------------------------
; DATA ------------------------------------------------------------------------
; -----------------------------------------------------------------------------

; Memory page: 7700h ----------------------------------------------------------
org $7700
auxstr              ; input string stored here

; Memory page: 7E00h ----------------------------------------------------------
; used to convert values to pieces
org $7E00
if gramod=0         ; opt: space or dot depending on the size
piearr  defb '.'        ; $2B
else
piearr  defb ' '
endif
org $7E02
    defm "pnbr"     ; change this array to any language, pih
org $7E07
    defb 'q'        ; change this array to any language, pih
org $7E16
    defb 'k'        ; change this array to any language, pih

; Memory page: 7F00h ----------------------------------------------------------
; sub-moves and vectors 
org $7F00
; leave empty $00-$04-...-$24 for black pieces/empty square pointers
org $7F88           ; pawn: $22x4=$84
; piece, move type, vector list delta address (18B)
; move type / 0 / 0 / pawn straight / pawn diagonal / DDDD (real radius + 7)
movlis
pawgen  defb    $28, $E3    ; pawn straight
    defb    $18, $E7    ; pawn capture
org $7F8C
knigen  defb    $08, $EA    ;
org $7F90
bisgen  defb    $0E, $E5    ; bishop
org $7F94
roogen  defb    $0E, $E0    ; rook
org $7F9C
quegen  defb    $0E, $E0    ; queen
    defb    $0E, $E5    ;
org $7FD8
kingen  defb    $08, $E0    ; king: $($16+$20)x4=$D8
    defb    $08, $E5    ;

org $7FE0           ; vectors start at: $7FE0 (arbitrary)
; (y, x) move delta pairs (16B)
veclis
strvec  defb    $FF, $01    ; +0, straight vectors
    defb    $10, $F0    ; +3, straight pawn, last half line
org $7FE5
diavec  defb    $0F, $11    ; +5, diagonal vectors
    defb    $EF, $F1    ; +7, diagonal pawn
org $7FEA
knivec  defb    $E1, $F2    ; +10, knight vectors
    defb    $12, $21    ; knight moves listed clockwise
    defb    $1F, $0E    ;
    defb    $EE, $DF    ;
; board status: 0000000 / turn (B=0, W=1)
org $7F7F
gamsta

; Memory page: 8000h ----------------------------------------------------------
    ; board squares format: 00cppppp
    ; pppp (value) : pawn=2, knight=3, bishop=4, rook=5, queen=7, king=$16
    ; c (color): white=1, black=0
    ; initial board setup
if debmod=1         ;opt: fill board for debugging
    org $8000
    boasta  defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--8
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $02, $00, $00, $00 ; <--7
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $23, $00, $00, $00, $00 ; <--6
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--5
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--4
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--3
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--2
        defb $00, $00, $00, $00, $00, $00, $00, $00 
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--1
else                ; opt: reduces board size for gameplay
    org $8000
    boasta  defb $05, $03, $04, $07, $16, $04, $03, $05 
    org $8010
        defb $02, $02, $02, $02, $02, $02, $02, $02
    org $8060           
        defb $22, $22, $22, $22, $22, $22, $22, $22
    org $8070
        defb $25, $23, $24, $27, $36, $24, $23, $25
endif

; Memory page: 8100h ----------------------------------------------------------
org $8100
boaata              ; attacked squares board

; Memory page: 8200h ----------------------------------------------------------
org $8200
boaopo              ; reversed attacked squares board

; Memory page: 8300h ----------------------------------------------------------
; candidate move list at the very end of the program 
org $8300 
canlis  equ $
````

3

> <> , 1467 ไบต์

มันไม่ทำลายสถิติ 487- ไบต์ ...

>   "  :W"av
"RNBQKBNR"a/
"PPPPPPPP"a/
"        "a/
"        "a/
"        "a/
"        "a/
"pppppppp"a/
"rnbqkbnr"a/
   l?!vo29.>
v?)b:i<~
\:8c*-:i:}4c*-:@g:o" "o{{oo" "o}i:o8c*-i:o4c*-
\{:"^")80g"^")-?X
\:"^")48**-
\&3[:}]$:@=3[:}]{:}=*?X&
\:"Q"=?v:"R"=?v
v      >      >&r:4[:}]$-r:4[:}]-{:?!v$:?!v~~&
 ["+-+10"]?$~137*.*731$~$?]"10+-+"[1)<    >)1
\:"Q"=?v:"B"=?v
v      >      >&$:@$:@-r$:@$:@$-{-r4[r$:@$:@+r$:@$:@+{-}]{:?!v$:?!v~~&
 )1["+-11"]?$137*.                     .*733]~~r?{"--11++"[1)<    >
 \>42b*p72b*p32b*p62b*p{{$:@$:@}}4[r
 >$zz$zz$:@{:}=$:@5[:}]=*?v$:@$:@g" "-?X
               .+9*a29$]~~<
\&$:@{:}-:*$:@5[:}]-:*+&
\:"N"=?v
  X?-5&<v
\:"K"=?v
  X?)3&<v
  )-?vX >$:@$:@g:" "=?v"^")80g"^"
     >049*.*942      ~<
\:"P"=?v
 )?X:1=\&~$:@{:}-:*$:@5[:}]80g"^")?$-:2
X      \?v2-?X?X$:@$:@80g"^"(2*1--g" "-?Xv
         >~:?v?X                         >$:@$:@g" "-?Xv
  @@?$~&049*.>1-?X$:@$:@g:" "=?X"^"(80g"^"(=?X         >:880g"^")7*-=&"Q"
\>&80g"^"):&48**+@p" "@p0
>:8%1+$:8,:1%-1+$}$:@$:@g"Kk"&:&?$~=?v~~1+:88*=?X
v                {{1030014103431434~{<
>l2=?v$:@$:@}}$@+2-a%@+2-a%$g"nN"&:&?$~=?X{{
\    >0010200121021222{{
>l2=?v$:@$:@}}$@+1-@+1-$g"kK"&:&?$~=?X{{
v    >$:@1+$:@&:&2*1--g"pP"&:&?$~=?X$:@1-$:@&:&2*1--g"pP"&:&?$~=?X
\"10++r10-+r01++r01+-r11++b11+-b11-+b11--b"
>l2=?v48*4a*6+p44*4a*6+p74a*6+\
   /} }@:$@:${{p+6*a46p+6*a4fp/
 -?\$ zz:9%?!v$zz:9%?!v$:@$:@g:"y"&:&48**-=?X:"q"&:&48**-=?X" "
^~~<         <        <
v    >~~"bW"&?$~80paaoo

ลองที่สนามเด็กเล่นปลา ! (มันใช้ประโยชน์จากข้อบกพร่องสองสามข้อในล่ามดังนั้นฉันจึงไม่สามารถรับประกันได้ว่ามันจะทำงานได้ทุกที่อื่นคุณอาจต้องการเรียกใช้ด้วยความเร็วสูงสุด - อาจใช้เวลาหนึ่งนาทีในการย้าย)

เมื่อคุณเรียกใช้รหัสมันจะพิมพ์

rnbqkbnr
pppppppp




PPPPPPPP
RNBQKBNR

W:  

อักษรตัวใหญ่หมายถึงสีขาวตัวพิมพ์เล็กเป็นตัวแทนของสีดำ จากนั้นคุณสามารถให้การเคลื่อนไหวของคุณเป็นอินพุตในแบบฟอร์ม[a-h][1-8][a-h][1-8]เช่นe2e4ความหมาย "ย้ายชิ้นส่วนe2ไปที่e4" จากนั้นโปรแกรมจะทำการพิมพ์เช่น

W:  P e2 e4

rnbqkbnr
pppppppp


    P   

PPPP PPP
RNBQKBNR

b:  

รูปแบบหลักของหน่วยความจำใน> <> คือสแต็ก อย่างไรก็ตามมันไม่เป็นประโยชน์สำหรับการจัดเก็บกระดานหมากรุก แต่ผมใช้> <> 's ตนเองการปรับเปลี่ยนความสามารถในการจัดเก็บกระดานหมากรุกเป็นส่วนหนึ่งของรหัสที่มาของตัวเองในการเข้าถึงด้วยและgp

ส่วนใหญ่ของรหัสคือการตรวจสอบว่าการย้ายของคุณถูกกฎหมาย มีหลายสิ่งที่ต้องตรวจสอบที่นี่:

  • คุณพยายามที่จะย้ายชิ้นส่วนที่มีอยู่จริงและเป็นของคุณหรือไม่ (บรรทัดที่ 12 ดัชนี 0)
  • สี่เหลี่ยมเริ่มต้นและจุดสิ้นสุดแตกต่างกันหรือไม่ (บรรทัดที่ 14)
  • เป็นไปในทิศทางที่ถูกต้องสำหรับประเภทของชิ้นส่วน (orthogonal สำหรับ rook และ queen, บรรทัดที่ 15–17; ทแยงมุมสำหรับอธิการและราชินี, บรรทัดที่ 18-20, รูปตัว L สำหรับอัศวิน, บรรทัด 24–26; ​​1 ตารางสำหรับกษัตริย์ บรรทัดที่ 27–28 หรือการจำนำบรรทัดที่ 31–35)?
  • ช่องสี่เหลี่ยมระหว่างจุดเริ่มต้นและจุดจบนั้นว่างเปล่าทั้งหมดหรือเปล่า
  • พื้นที่เป้าหมายนั้นว่างเปล่าหรือถูกครอบครองโดยศัตรู (สาย 29–30) หรือไม่?
  • คุณอยู่ในการตรวจสอบหลังจากย้าย (บรรทัด 36–47)?

หากคำถามเหล่านี้มีคำตอบที่ไม่ถูกต้องโปรแกรมจะส่งข้อผิดพลาดและหยุดพัก มิฉะนั้นจะแก้ไขกระดานหมากรุกในซอร์สโค้ดของมันพิมพ์อีกครั้งและรอการย้ายครั้งต่อไป

สำหรับการเคลื่อนย้ายของราชาและอัศวินฉันยืมเลเวลริเวอร์เซนต์ของการตรวจสอบระยะทางแบบยุคลิดสแควร์: สำหรับราชามันน้อยกว่า 3 และสำหรับอัศวินมันคือ 5

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.