Комментарии 16
Спасибо за совет, обязательно посмотрю. В любом случае, чем короче и лаконичнее программа, тем она лучше. Не всегда красота требует полотен кода.
В любом случае, чем короче и лаконичнее программа, тем она лучше.
(Улыбка Чеширского Кота): как вам, например, такое? :) Оно правда играет в шахматы. Не очень сильно, но играет. Вопрос в том, как? :)
#ifndef AVR_ENGINE_H
#define AVR_ENGINE_H
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
/***************************************************************************/
/* AVR-Max, */
/* A chess program smaller than 2KB (of non-blank source), by H.G. Muller */
/* AVR ATMega88V port, iterative Negamax, by Andre Adrian */
/***************************************************************************/
/* 14dez2008 adr: merge avr_c_io and uMax */
/* 18dez2008 adr: return -l if Negamax stack underrun */
/* 24dez2008 adr: add functions 1=new game, 2=set level, 3=show PV */
/* 26dez2008 adr: bug fix, undo modifications on uMax 4.8 */
/* 29dez2009 adr: Key Debouncing with inhibit (Sperrzeit nach Loslassen) */
/* Stufe (Level)
1 Blitz = min. 0.5s, typ. 7s
2 2*Blitz = min. 1s, typ. 15s
3 4*Blitz = min. 2s, typ. 22s
4 Aktiv/2 = min. 4s, typ.
5 Aktiv = min. 8s, typ. 30s
6 2*Aktiv = min. 16s, typ.
7 Turnier/2 = min. 32s, typ.
8 Turnier = min. 64s, typ.
FN 2*Turnier = min. 128s, typ.
CL 4*Turnier = min. 256s, typ.
*/
struct STRUCT{
short q,l,e; /* Args: (q,l)=window, e=current eval. score */
short m,v, /* m=value of best move so far, v=current evaluation */
V,P;
unsigned char E,z,n; /* Args: E=e.p. sqr.; z=level 1 flag; n=depth */
signed char r; /* step vector current ray */
unsigned char j, /* j=loop over directions (rays) counter */
B,d, /* B=board scan start, d=iterative deepening counter */
h,C, /* h=new ply depth?, C=ply depth? */
u,p, /* u=moving piece, p=moving piece type */
x,y, /* x=origin square, y=target square of current move */
F, /* F=e.p., castling skipped square */
G, /* G=castling R origin (corner) square */
H,t, /* H=capture square, t=piece on capture square */
X,Y, /* X=origin, Y=target square of best move so far */
a; /* D() return address state */
}; /* _=working set, A=stack array, J=stack pointer */
/* Attention: union TIMER assumes little endian CPU or compiler! */
typedef union {
long w;
} TIMER;
/***************************************************************************/
/* micro-Max, */
/* A chess program smaller than 2KB (of non-blank source), by H.G. Muller */
/***************************************************************************/
/* version 4.8 (1953 characters) features: */
/* - recursive negamax search */
/* - all-capture MVV/LVA quiescence search */
/* - (internal) iterative deepening */
/* - best-move-first 'sorting' */
/* - a hash table storing score and best move */
/* - futility pruning */
/* - king safety through magnetic, frozen king in middle-game */
/* - R=2 null-move pruning */
/* - keep hash and repetition-draw detection */
/* - better defense against passers through gradual promotion */
/* - extend check evasions in inner nodes */
/* - reduction of all non-Pawn, non-capture moves except hash move (LMR) */
/* - full FIDE rules (expt under-promotion) and move-legality checking */
void D();
void Init(void);
bool AVRMove(unsigned char *c,bool &mate);
#endif
avrengine.c
#include "avrengine.h"
/***************************************************************************/
/* AVR-Max, */
/* A chess program smaller than 2KB (of non-blank source), by H.G. Muller */
/* AVR ATMega88V port, iterative Negamax, by Andre Adrian */
/***************************************************************************/
/* 14dez2008 adr: merge avr_c_io and uMax */
/* 18dez2008 adr: return -l if Negamax stack underrun */
/* 24dez2008 adr: add functions 1=new game, 2=set level, 3=show PV */
/* 26dez2008 adr: bug fix, undo modifications on uMax 4.8 */
/* 29dez2009 adr: Key Debouncing with inhibit (Sperrzeit nach Loslassen) */
/* Stufe (Level)
1 Blitz = min. 0.5s, typ. 7s
2 2*Blitz = min. 1s, typ. 15s
3 4*Blitz = min. 2s, typ. 22s
4 Aktiv/2 = min. 4s, typ.
5 Aktiv = min. 8s, typ. 30s
6 2*Aktiv = min. 16s, typ.
7 Turnier/2 = min. 32s, typ.
8 Turnier = min. 64s, typ.
FN 2*Turnier = min. 128s, typ.
CL 4*Turnier = min. 256s, typ.
*/
unsigned char st=20; /* Spielstufe (Level) */ //4+2
/* This is the AVR ATMega8 Selbstbau Schachcomputer specific part */
#define WIEDERHOLMS 330
#define INHIBITMS 100 // Sperrzeit nach Loslassen
#define WIEDERHOL ((WIEDERHOLMS+8)/16) // Einheit 16ms
#define INHIBIT ((INHIBITMS+8)/16)
#define SPACE 36
#define FN '9'
#define CL ':'
#define GO ';'
/* better readability of AVR Program memory arrays */
#define o(ndx) (signed char)o[ndx]
#define w(ndx) (signed char)w[ndx]
#define M 0x88 /* Unused bits in valid square */
#define S 128 /* Sign bit of char */
#define I 8000 /* Infinity score */
#define U 18 /* D() Stack array size */
/* better readability of working struct variables */
#define q _.q
#define l _.l
#define e _.e
#define E _.E
#define z _.z
#define n _.n
#define m _.m
#define v _.v
#define V _.V
#define P _.P
#define r _.r
#define j _.j
#define B _.B
#define d _.d
#define h _.h
#define C _.C
#define u _.u
#define p _.p
#define x _.x
#define y _.y
#define F _.F
#define G _.G
#define H _.H
#define t _.t
#define X _.X
#define Y _.Y
#define a _.a
/***************************************************************************/
/* micro-Max, */
/* A chess program smaller than 2KB (of non-blank source), by H.G. Muller */
/***************************************************************************/
/* version 4.8 (1953 characters) features: */
/* - recursive negamax search */
/* - all-capture MVV/LVA quiescence search */
/* - (internal) iterative deepening */
/* - best-move-first 'sorting' */
/* - a hash table storing score and best move */
/* - futility pruning */
/* - king safety through magnetic, frozen king in middle-game */
/* - R=2 null-move pruning */
/* - keep hash and repetition-draw detection */
/* - better defense against passers through gradual promotion */
/* - extend check evasions in inner nodes */
/* - reduction of all non-Pawn, non-capture moves except hash move (LMR) */
/* - full FIDE rules (expt under-promotion) and move-legality checking */
STRUCT _, A[U],*J=A+U; /* _=working set, A=stack array, J=stack pointer */
short Q, /* pass updated eval. score */
K, /* input move, origin square */
i,s, /* temp. evaluation term */
Dq,Dl,De, /* D() arguments */
DD; /* D() return value */
const signed char w[] = {
0,2,2,7,-1,8,12,23}; /* relative piece values */
const signed char o[] = {
-16,-15,-17,0,1,16,0,1,16,15,17,0,14,18,31,33,0, /* step-vector lists */
7,-1,11,6,8,3,6, /* 1st dir. in o[] per piece*/
6,3,5,7,4,5,3,6}; /* initial piece setup */
unsigned char L, /* input move, target square*/
b[129], /* board: half of 16x8+dummy*/
c[5], /* input move ASCII buffer */
k, /* moving side 8=white 16=black*/
O, /* pass e.p. flag at game level*/
R, /* captured non pawn material */
DE,Dz,Dn, /* D() arguments */
Da, /* D() state */
W, /* @ temporary */
hv; /* zeige Hauptvariante */
void D()
{
D:
if (--J<A)
{
++J;
DD=-l;
goto R;
}
q=Dq;
l=Dl;
e=De;
E=DE;
z=Dz;
n=Dn;
a=Da;
--q;
k^=24;
d=X=Y=0;
while(d++<n || d<3 || z&K==I && ((K=X,L=Y&~M,d=3)))
{
x=B=X;
h=Y&S;
if (d<3) P=I;
else
{
*J=_;
Dq=-l;
Dl=1-l;
De=-e;
DE=S;
Dz=0;
Dn=d-3;
Da=0;
goto D;
R0:
_=*J;
P=DD;
}
m=-P<l|R>35?d>2?-I:e:-P;
do
{
u=b[x];
if (u&k)
{
r=p=u&7;
j=o(p+16);
while(r=p>2&r<0?-r:-o(++j))
{
A:
y=x;
F=G=S;
do
{
H=y=h?Y^h:y+r;
if (y&M) break;
m=E-S&b[E]&&y-E<2&E-y<2?I:m;
if (p<3&y==E) H^=16;
t=b[H];
if (t&k|p<3&!(y-x&7)-!t) break;
i=37*w(t&7)+(t&192);
m=i<0?I:m;
if (m>=l&d>1) goto J;
v=d-1?e:i-p;
if (d-!t>1)
{
v=p<6?b[x+8]-b[y+8]:0;
b[G]=b[H]=b[x]=0;
b[y]=u|32;
if (!(G&M)) b[F]=k+6,v+=50;
v-=p-4|R>29?0:20;
if (p<3)
{
v-=9*((x-2&M||b[x-2]-u)+(x+2&M||b[x+2]-u)-1+(b[x^16]==k+36))-(R>>2);
V=y+r+1&S?647-p:2*(u&y+16&32);
b[y]+=V;
i+=V;
}
v+=e+i;
V=m>q?m:q;
C=d-1-(d>5&p>2&!t&!h);
C=R>29|d<3|P-I?C:d;
do
if (C>2|v>V)
{
*J=_;
Dq=-l;
Dl=-V;
De=-v;
DE=F;
Dz=0;
Dn=C;
Da=1;
goto D;
R1:
_=*J;
s=-DD;
}
else s=v;
while (s>q&++C<d);
v=s;
if (z&&K-I&&v+I&&x==K&y==L)
{
Q=-e-i;
O=F;
R+=i>>7;
++J;
DD=l;
goto R;
}
b[G]=k+6;
b[F]=b[y]=0;
b[x]=u;
b[H]=t;
}
if(v>m) m=v,X=x,Y=y|S&F;
if (h)
{
h=0;
goto A;
}
if (x+r-y|u&32|p>2&(p-4|j-7|| b[G=x+3^r>>1&7]-k-6 ||b[G^1]|b[G^2])) t+=p<5;
else F=y;
}
while (!t);
}
}
}
while ((x=x+9&~M)-B);
J:
if (m>I-M|m<M-I) d=98;
m=m+I|P==I?m:0;
}
k^=24;
++J;
DD=m+=m<e;
R:
if (J!=A+U) switch(a)
{
case 0:goto R0;
case 1:goto R1;
}
else return;
}
void Init(void)
{
k=16;O=Q=R=0;
for(W=0;W<sizeof(b);++W)b[W]=0;
W=8;
while(W--)
{
b[W]=(b[W+112]=o(W+24)+8)+8;b[W+16]=18;b[W+96]=9;/* initial board setup*/
L=8;
while(L--) b[16*L+W+8]=(W-4)*(W-4)+(L+L-7)*(L+L-7)/4;/* center-pts table */
}
}
bool AVRMove(unsigned char *c,bool &mate)
{
mate=false;
if(*c-GO)//если ходит человек
{
K=*c-16*c[1]+799,L=c[2]-16*c[3]+799; /* parse entered move */
}
else//если ходит компьютер
{
K=I;
}
Dq=-I;Dl=I;De=Q;DE=O;Dz=1;Dn=3;
Da=0;
D();
if (*c-GO) //ввод доступных ходов
{
if (I==DD)//ход разрешён
{
}
else//ход запрещён
{
return(false);
}
*c=GO;
}
else //ход компьютера
{
c[0]='A'+(K&7);
c[1]='8'-(K>>4);
c[2]='A'+(L&7);
c[3]='8'-(L>>4);
return(true);
}
if (!(DD>-I+1)) mate=true;
return(true);
}
Ух, новый челлендж. Спасибо, возьму на заметку! Может, даже разберу, если очень интересно получится.
Играть левой и правой кнопкой мышки. Правда, ошибочные ходы я забыл отменять — он их пишет как ошибочные, но делает. :) Так что ходите правильно. :)
В любом случае, чем короче и лаконичнее программа, тем она лучше.
https://codegolf.stackexchange.com/ читаете? Содержит тонны всевозможных извращений над кодом.
Лучше закинуть на JSFiddle.net, jsbin.com или gist.github.com.
Или ты сам через десять лет.
Поэтому, основное требование к программе — это её наглядность.
Разумеется, не в программах для первых машин, написанных в кодах с многочисленными ветвлениями. Там экономия памяти мгла иметь и имела значение.
Сейчас об этом говорить не приходится.
В общем случае вы, безусловно, правы, но здесь самоцель кода — его размер. Люди меряются не столько его функциональностью, читабельностью, сколько его размером и скоростью. Они просто экспериментируют. Разбираться в этом очень интересно потому, что здесь содержится максимальная концентрация алгоритмов, хаков, уловок и простых, самых первых человеческих изысканий в области компьютеров, это очень полезно. Может, и пригодится в жизни.
Wolfensteiny 3D — реверс-инжиниринг 251 байтов JavaScript