最高のAI
#include <stdio.h>
#include <string.h>
#include <time.h>
#define A(x,y) i[a++]=(N){c,c+x,y};
#define B(x,y) j[b++]=(N){c,c+x,y};
#define C(j,k) for (j=0; j<k; j++){
#define D(x) C(_,8)if(!(c+x[_]&136)){ if(p[c+x[_]]*p[c]<0)B(x[_],0)else if(!p[c+x[_]])A(x[_],0)} }
#define J printf(
#define O(v) _=v; while(!(c+_&136)){ x=p[c+_]*p[c]; if(x<0){B(_,0)E; } else if(x>0)E; else A(_,0)_+=v; }
#define X(x) G(x,L)
#define Z(x,y) memcpy(x,y,256);
typedef struct {
F a,b,c;
} N;
F g[]="KSLAU",
p[256],v[]="{ ; } ; { ; ; ; { } ; { ; } { ; } { } ; { ; ; ; { ; } ; } } ; { ; ; { } ; { } } ; { ; ; { { ; ; { } } ; } ; ; { } ; { } } ; { ; ; { { ; { } } ; { ; ; { } ; { { ; ; { } ; ; ; ; { ; } { { ; ; ; { } ; { ; ; ";
F S[]="{}; ",W[256],L[1024];
P q[]={-14,-31,-33,-18,14,31,33,18},r[]={-1,-17,-16,-15,1,17,16,15},_,a,b,c,d,e,t=1,x,y,z;
N i[500],j[500],*k,u;
P f(N *V) {
a=b=0;
C(d,8)
C(e,8)
c=d<<4|e;
if(p[c]==0||p[c]*t<0)continue;
switch(p[c]<0?-p[c]:p[c]){
K 80:
if(56+t*40==(c&112)&&!p[c-32*t])
A(t*-32,0)
if(56+t*-40==(c&112)){
if(!(c-17*t&136)&&p[c-17*t]*t<0){
C(_,5)
B(-17*t,(g[_]^_)*t)}
}
if(!(c-15*t&136)&&p[c-15*t]*t<0){
C(_,5)
B(-15*t,(g[_]^_)*t)}
}
C(_,5)
A(t*-16,(g[_]^_)*t)}
}else{
if(!p[c-16*t])
A(t*-16,0)
if(!(c-(17*t)&136)&&p[c-17*t]*t<0){
B(-17*t,0)
}
if(!(c-(15*t)&136)&&p[c-15*t]*t<0){
B(-15*t,0)
}
}
E;
K 78:D(q)E;
K 81:
K 66:O(17)O(-17)O(15)O(-15)
if(p[c]==66||p[c]==-66)
E;
K 82:O(1)O(-1)O(16)O(-16)E;
K 75:D(r)
} ;
}
}
if ( b > 0 ) {
C(_,b)V[_]=j[_]; }
R b;
} else {
C(_,a)V[_]=i[_]; }
R a;
}
}
F *G(F *n, F *o){
a=b=0;
for(; n[b]; d=0){
do{
d*=4;
d+=W[n[b++]];
} while(++b<8*a+8);
o[a++]=d;
}
o[a]=0;
R o;
}
m(N a){ p[a.b]=a.c?a.c:p[a.a]; p[a.a]=0; }
h(){
J X("{ ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; "));
c=0; C(c,120)c%8==0&&putchar(56-c/16);
if(p[c]<0){
J X("} { { ; { { { ; ; ; { ; } } } ; { "),-p[c]);
} else if(p[c]>0)
J X("} { { ; { { { ; } } } ; { { ; { { "),p[c]);
else
J"| ");
c%8==7?J X("} { { { ; ; { ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; ")),c+=8:0;
}
}
s() {
b=0; C(a,256)
if(v[b]==94){
b++; C(c,v[b]-32)p[a++]=v[b+1]-120;}
b+=2; a--;
} else
p[a]=v[b++]-120;
}
}
P w() {
P v=0;
C(_,120)
p[_]&&(p[_]*t>0&&v--,p[_]*t<0&&v++);
}
v+=f(i); v-=b?100:0;t=-t; v-=f(i); v+=b?100:0;t=-t;
R v;
}
P V(P n, P o) {
P s=-I,G,H,Y;
N M[500];
F u[256];
if(!(n+o))R w()+time(NULL)%9-4;
if(!(H=f(M)))R I;
H<5?H==1?n++:(o<6?o++:0):0;
Z(u,p)
C(G,H)
Z(p,u)
m(M[G]);
t=-t;
s=(e=-V(n-1,o))>s?Y=G,e:s;
t=-t;
}
e=Y;
R s;
}
main(P db, F *bd[]){
N o[500];
F T[256];
C(a,256)W[a]=-1; }
C(a,4)W[S[a]]=a; }
G(v,v); s();
while(1){
h();
b=f(o);
scanf("%s",L);
if(strcmp(L,"quit")==0)R 0;
else if(strcmp(L,"g")==0){
Z(T,p)
J G("} } } ; } ; { } } ; { } } } } ; } } { ; { { { ; } } } ; } { { { ; ; ",L), V(db>1?atoi(bd[1]):3,0));
Z(p,T)m(o[e]); t=-t;
}else{
u.a=896-16*L[1];
u.b=896-16*L[3];
u.a+=L[0]-97;
u.b+=L[2]-97;
u.c=L[4]?L[5]:0;
C(a,b)
if(u.a==o[a].a&&u.b==o[a].b&&u.c==o[a].c)E;
}
a==b?J X("} { ; } } ; { } ; { } ; } } } ; } } ; { } } ; { { ; { { } ; } } ; } } ; } ; } } { { ; ; ")):(m(u),t=-t);
}
}
}
引用元:https://www.ioccc.org/2001/dgbeards.c
審査員・作者による説明:https://github.com/ioccc-src/winner/blob/main/2001/dgbeards.hint
負けるが勝ちのチェス。
$ gcc -DE=break -DF=char -DK=case -DP=int -DR=return -DI=0xFFFF -o dgbeards dgbeards.c
$ ./dgbeards
+---+---+---+---+---+---+---+---+
8| *R| *N| *B| *Q| *K| *B| *N| *R|
+---+---+---+---+---+---+---+---+
7| *P| *P| *P| *P| *P| *P| *P| *P|
+---+---+---+---+---+---+---+---+
6| | | | | | | | |
+---+---+---+---+---+---+---+---+
5| | | | | | | | |
+---+---+---+---+---+---+---+---+
4| | | | | | | | |
+---+---+---+---+---+---+---+---+
3| | | | | | | | |
+---+---+---+---+---+---+---+---+
2| P | P | P | P | P | P | P | P |
+---+---+---+---+---+---+---+---+
1| R | N | B | Q | K | B | N | R |
+---+---+---+---+---+---+---+---+
K(キング)の前のP(ポーン)を前に出してみる。
チェスでは左列から右列へabcdefgh、下行から上行へ12345678の番号が振られていて、どのマスからどのマスへ移動するかを並べて書く。
この場合はe2e4
。
e2e4
+---+---+---+---+---+---+---+---+
8| *R| *N| *B| *Q| *K| *B| *N| *R|
+---+---+---+---+---+---+---+---+
7| *P| *P| *P| *P| *P| *P| *P| *P|
+---+---+---+---+---+---+---+---+
6| | | | | | | | |
+---+---+---+---+---+---+---+---+
5| | | | | | | | |
+---+---+---+---+---+---+---+---+
4| | | | | P | | | |
+---+---+---+---+---+---+---+---+
3| | | | | | | | |
+---+---+---+---+---+---+---+---+
2| P | P | P | P | | P | P | P |
+---+---+---+---+---+---+---+---+
1| R | N | B | Q | K | B | N | R |
+---+---+---+---+---+---+---+---+
次は相手の番。
AIに打たせるならg
と打つ(ちなみに、自分の手番でもg
でAIに代わりに動かしてもらえるし、相手のコマの動かし方を指定することもできる)。
g
Value 129
+---+---+---+---+---+---+---+---+
8| *R| *N| *B| *Q| *K| *B| *N| *R|
+---+---+---+---+---+---+---+---+
7| *P| *P| *P| *P| *P| | *P| *P|
+---+---+---+---+---+---+---+---+
6| | | | | | | | |
+---+---+---+---+---+---+---+---+
5| | | | | | *P| | |
+---+---+---+---+---+---+---+---+
4| | | | | P | | | |
+---+---+---+---+---+---+---+---+
3| | | | | | | | |
+---+---+---+---+---+---+---+---+
2| P | P | P | P | | P | P | P |
+---+---+---+---+---+---+---+---+
1| R | N | B | Q | K | B | N | R |
+---+---+---+---+---+---+---+---+
ポーンは斜めにコマを取れる。 このチェスでは取れるコマがあるときは必ず取らないといけない。 他のムーブはできない。
e4f5
+---+---+---+---+---+---+---+---+
8| *R| *N| *B| *Q| *K| *B| *N| *R|
+---+---+---+---+---+---+---+---+
7| *P| *P| *P| *P| *P| | *P| *P|
+---+---+---+---+---+---+---+---+
6| | | | | | | | |
+---+---+---+---+---+---+---+---+
5| | | | | | P | | |
+---+---+---+---+---+---+---+---+
4| | | | | | | | |
+---+---+---+---+---+---+---+---+
3| | | | | | | | |
+---+---+---+---+---+---+---+---+
2| P | P | P | P | | P | P | P |
+---+---+---+---+---+---+---+---+
1| R | N | B | Q | K | B | N | R |
+---+---+---+---+---+---+---+---+
g
Value 7
+---+---+---+---+---+---+---+---+
8| *R| *N| *B| *Q| *K| *B| *N| *R|
+---+---+---+---+---+---+---+---+
7| *P| | *P| *P| *P| | *P| *P|
+---+---+---+---+---+---+---+---+
6| | | | | | | | |
+---+---+---+---+---+---+---+---+
5| | *P| | | | P | | |
+---+---+---+---+---+---+---+---+
4| | | | | | | | |
+---+---+---+---+---+---+---+---+
3| | | | | | | | |
+---+---+---+---+---+---+---+---+
2| P | P | P | P | | P | P | P |
+---+---+---+---+---+---+---+---+
1| R | N | B | Q | K | B | N | R |
+---+---+---+---+---+---+---+---+
相手はb5にポーンを動かしてきたが、これはf1のB(ビショップ)で取れるので、それ以外の動きは許されない。
このようにコマを進めあって、合法ムーブがなくなったら(全部のコマが取られたら)勝ち。 なお、キングを取られても終わりではない。
負けたらsegfaultする。 これがこのジャンルのプログラムのスポーツマンシップであろうとのこと。
{
と}
と;
と空白からなる文字列リテラルは、IOCCCのサイズ制限を回避しつつテーブルを埋め込むためのテクニック。