Как стать автором
Обновить

Комментарии 16

Посмотрите ещё Mars от Tim Clarke. Где-то и исходник был — там достаточно маленькая программа.

Спасибо за совет, обязательно посмотрю. В любом случае, чем короче и лаконичнее программа, тем она лучше. Не всегда красота требует полотен кода.

В любом случае, чем короче и лаконичнее программа, тем она лучше.


(Улыбка Чеширского Кота): как вам, например, такое? :) Оно правда играет в шахматы. Не очень сильно, но играет. Вопрос в том, как? :)

Шахматы для AVR
avrengine.h

#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);
}


Ух, новый челлендж. Спасибо, возьму на заметку! Может, даже разберу, если очень интересно получится.

Ну тогда вот вам этот блок интегрированный в GUI.
Играть левой и правой кнопкой мышки. Правда, ошибочные ходы я забыл отменять — он их пишет как ошибочные, но делает. :) Так что ходите правильно. :)
В любом случае, чем короче и лаконичнее программа, тем она лучше.

https://codegolf.stackexchange.com/ читаете? Содержит тонны всевозможных извращений над кодом.

Хм. Сохранил когда-то Mars Engine на Java Script. А теперь в поиске фиг его нахожу. Так как Java Script я не знаю и выделить программу чтобы сюда вставить и оно работало прямо на страничке не могу (так-то для С++ под Direct Draw я код давно вынул и переделал), то прикладываю целиком сохранённый html-файл: может, вам удастся выковырять оттуда программу на Java Script.
Посмотрел в архив, он и сохранён был на JSfiddle
Это напоминает мне DOSовский вирус, который размножается и наносит вред. Длина — 33 байта.
Программист, который пишет программу, должен понимать, что когда-нибудь, вероятно, её может править дугой программист.
Или ты сам через десять лет.
Поэтому, основное требование к программе — это её наглядность.
Разумеется, не в программах для первых машин, написанных в кодах с многочисленными ветвлениями. Там экономия памяти мгла иметь и имела значение.
Сейчас об этом говорить не приходится.

В общем случае вы, безусловно, правы, но здесь самоцель кода — его размер. Люди меряются не столько его функциональностью, читабельностью, сколько его размером и скоростью. Они просто экспериментируют. Разбираться в этом очень интересно потому, что здесь содержится максимальная концентрация алгоритмов, хаков, уловок и простых, самых первых человеческих изысканий в области компьютеров, это очень полезно. Может, и пригодится в жизни.

Напомнили об .kkrieger
НЛО прилетело и опубликовало эту надпись здесь

Да, спасибо за совет. Вообще, таких демок красивая можно много найти, разбираться в них очень интересно.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории