Code:
/*
* ****************************************************************************
* RP6 ROBOT SYSTEM - RP6 CONTROL M256 Examples
* ****************************************************************************
* Example: Chess
* Author(s): Dirk
* ****************************************************************************
* Description:
* This program for RP6 Control M256 WiFi plays the game chess.
*
* You will find further information here:
* http://de.wikipedia.org/wiki/Chess
* http://en.wikipedia.org/wiki/Chess
*
* ############################################################################
* The Robot does NOT move in this example! You can simply put it on a table
* next to your PC and you should connect it to the PC via the USB Interface!
* You should also connect to it via WIFI.
* ############################################################################
* ****************************************************************************
*/
/*****************************************************************************/
// Includes:
#include "RP6M256Lib.h" // The RP6 M256 Library.
// Always needs to be included!
/*****************************************************************************/
// Defines:
#define HELP // Display help
/*****************************************************************************/
// Functions:
/**
* GET SEED
*
* Gets a starting value for mysrand().
*
*/
uint16_t get_seed(void)
{
uint16_t seed = 0;
uint16_t *p = (uint16_t*) (RAMEND + 1);
extern uint16_t __heap_start;
while (p >= &__heap_start + 1)
seed ^= * (--p);
return seed;
}
/*****************************************************************************/
//###########################################################################
/*****************************************************************************/
// micro-Max chess engine V4.8 by H. G. Muller:
// (http://home.hccnet.nl/h.g.muller/max-src2.html)
/***************************************************************************/
/* micro-Max, */
/* A chess program smaller than 2KB (of non-blank source), by H.G. Muller */
/* Port to Atmel ATMega644 and AVR GCC, by Andre Adrian */
/* (http://www.andreadrian.de/schach/index.html) */
/***************************************************************************/
/* 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 */
/* 26nov2008 no hash table */
/* 29nov2008 all IO via myputchar(), mygetchar(), pseudo random generator */
#define W while
#define M 0x88
#define S 128
#define I 8000
long N, T; /* N=evaluated positions+S, T=recursion limit */
short Q,O,K,R,k=16; /* k=moving side */
char *p,c[5],Z; /* p=pointer to c, c=user input,*/
/* computer output, Z=recursion counter */
char L,
w[]={0,2,2,7,-1,8,12,23}, /* relative piece values */
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 */
b[]={ /* board is left part, center-pts table is right part, and dummy*/
22, 19, 21, 23, 20, 21, 19, 22, 28, 21, 16, 13, 12, 13, 16, 21,
18, 18, 18, 18, 18, 18, 18, 18, 22, 15, 10, 7, 6, 7, 10, 15,
0, 0, 0, 0, 0, 0, 0, 0, 18, 11, 6, 3, 2, 3, 6, 11,
0, 0, 0, 0, 0, 0, 0, 0, 16, 9, 4, 1, 0, 1, 4, 9,
0, 0, 0, 0, 0, 0, 0, 0, 16, 9, 4, 1, 0, 1, 4, 9,
0, 0, 0, 0, 0, 0, 0, 0, 18, 11, 6, 3, 2, 3, 6, 11,
9, 9, 9, 9, 9, 9, 9, 9, 22, 15, 10, 7, 6, 7, 10, 15,
14, 11, 13, 15, 12, 13, 11, 14, 28, 21, 16, 13, 12, 13, 16, 21, 0
};
volatile char breakpoint; /* for debugger */
/* User interface routines */
void myputchar(char c) {
writeChar_WIFI(c);
}
void myputs(const char *s) {
while(*s) myputchar(*s++);
myputchar('\n');
}
char mygetchar(void) {
char tmp;
do {tmp = readChar_WIFI();}
while (tmp == 0);
if(c[0] == 13) c[0] = 10;
return tmp;
// return 10; /* self play computer with computer */
}
/* 16bit pseudo random generator */
#define MYRAND_MAX 65535
unsigned short r = 1; /* pseudo random generator seed */
void mysrand(unsigned short r_) {
r = r_;
}
unsigned short myrand(void) {
return r=((r<<11)+(r<<7)+r)>>1;
}
short D(q,l,e,E,z,n) /* recursive minimax search */
short q,l,e; /* (q,l)=window, e=current eval. score, */
unsigned char E,z,n; /* E=e.p. sqr.z=prev.dest, n=depth; return score*/
{
short m,v,i,P,V,s;
unsigned char t,p,u,x,y,X,Y,H,B,j,d,h,F,G,C;
signed char r;
if (++Z>30) { /* stack underrun check */
breakpoint=1; /* AVR Studio 4 Breakpoint for stack underrun */
myputchar('u');
--Z;return e;
}
q--; /* adj. window: delay bonus */
k^=24; /* change sides */
d=Y=0; /* start iter. from scratch */
X=myrand()&~M; /* start at random field */
W(d++<n||d<3|| /* iterative deepening loop */
z&K==I&&(N<T&d<98|| /* root: deepen upto time */
(K=X,L=Y&~M,d=3))) /* time's up: go do best */
{x=B=X; /* start scan at prev. best */
h=Y&S; /* request try noncastl. 1st*/
P=d<3?I:D(-l,1-l,-e,S,0,d-3); /* Search null move */
m=-P<l|R>35?d>2?-I:e:-P; /* Prune or stand-pat */
++N; /* node count (for timing) */
do{u=b[x]; /* scan board looking for */
if(u&k) /* own piece (inefficient!)*/
{r=p=u&7; /* p = piece type (set r>0) */
j=o[p+16]; /* first step vector f.piece*/
W(r=p>2&r<0?-r:-o[++j]) /* loop over directions o[] */
{A: /* resume normal after best */
y=x;F=G=S; /* (x,y)=move, (F,G)=castl.R*/
do{ /* y traverses ray, or: */
H=y=h?Y^h:y+r; /* sneak in prev. best move */
if(y&M)break; /* board edge hit */
m=E-S&b[E]&&y-E<2&E-y<2?I:m; /* bad castling */
if(p<3&y==E)H^=16; /* shift capt.sqr. H if e.p.*/
t=b[H];if(t&k|p<3&!(y-x&7)-!t)break; /* capt. own, bad pawn mode */
i=37*w[t&7]+(t&192); /* value of capt. piece t */
m=i<0?I:m; /* K capture */
if(m>=l&d>1)goto C; /* abort on fail high */
v=d-1?e:i-p; /* MVV/LVA scoring */
if(d-!t>1) /* remaining depth */
{v=p<6?b[x+8]-b[y+8]:0; /* center positional pts. */
b[G]=b[H]=b[x]=0;b[y]=u|32; /* do move, set non-virgin */
if(!(G&M))b[F]=k+6,v+=50; /* castling: put R & score */
v-=p-4|R>29?0:20; /* penalize mid-game K move */
if(p<3) /* pawns: */
{v-=9*((x-2&M||b[x-2]-u)+ /* structure, undefended */
(x+2&M||b[x+2]-u)-1 /* squares plus bias */
+(b[x^16]==k+36)) /* kling to non-virgin King */
-(R>>2); /* end-game Pawn-push bonus */
V=y+r+1&S?647-p:2*(u&y+16&32); /* promotion or 6/7th bonus */
b[y]+=V;i+=V; /* change piece, add score */
}
v+=e+i;V=m>q?m:q; /* new eval and alpha */
C=d-1-(d>5&p>2&!t&!h);
C=R>29|d<3|P-I?C:d; /* extend 1 ply if in check */
do
s=C>2|v>V?-D(-l,-V,-v, /* recursive eval. of reply */
F,0,C):v; /* or fail low if futile */
W(s>q&++C<d);v=s;
if(z&&K-I&&v+I&&x==K&y==L) /* move pending & in root: */
{Q=-e-i;O=F; /* exit if legal & found */
R+=i>>7;--Z;return l; /* captured non-P material */
}
b[G]=k+6;b[F]=b[y]=0;b[x]=u;b[H]=t; /* undo move,G can be dummy */
}
if(v>m) /* new best, update max,best*/
m=v,X=x,Y=y|S&F; /* mark double move with S */
if(h){h=0;goto A;} /* redo after doing old best*/
if(x+r-y|u&32| /* not 1st step,moved before*/
p>2&(p-4|j-7|| /* no P & no lateral K move,*/
b[G=x+3^r>>1&7]-k-6 /* no virgin R in corner G, */
||b[G^1]|b[G^2]) /* no 2 empty sq. next to R */
)t+=p<5; /* fake capt. for nonsliding*/
else F=y; /* enable e.p. */
}W(!t); /* if not capt. continue ray*/
}}}W((x=x+9&~M)-B); /* next sqr. of board, wrap */
C:if(m>I-M|m<M-I)d=98; /* mate holds to any depth */
m=m+I|P==I?m:0; /* best loses K: (stale)mate*/
if(z&&d>2)
{*c='a'+(X&7);c[1]='8'-(X>>4);c[2]='a'+(Y&7);c[3]='8'-(Y>>4&7);c[4]=0;
breakpoint=2; /* AVR Studio 4 Breakpoint for moves, watch c[] */
// printf("%2d ply, %9d searched, score=%6d by %c%c%c%c\n",d-1,N-S,m,
// 'a'+(X&7),'8'-(X>>4),'a'+(Y&7),'8'-(Y>>4&7));/* uncomment for Kibitz */
}
} /* encoded in X S,8 bits */
k^=24; /* change sides back */
--Z;return m+=m<e; /* delayed-loss bonus */
}
//void print_board(void)
//{
// short N=-1;
// W(++N<121)
// myputchar(N&8&&(N+=7)?10:".?inkbrq?I?NKBRQ"[b[N]&15]); /* Pawn is i*/
//}
// micro-Max chess engine V4.8 end.
/*****************************************************************************/
//###########################################################################
/*****************************************************************************/
void print_new_board(void)
{
myputs(" A B C D E F G H");
short N=-1;
W(++N<121)
{
if (N&8&&(N+=7)) {
myputchar(' ');
writeInteger_WIFI(8-(N>>4), DEC);
#ifdef HELP
myputchar(' ');
myputchar(' ');
switch(N)
{
case 15: myputs("kK = King");
break;
case 31: myputs("qQ = Queen");
break;
case 47: myputs("rR = Rook");
break;
case 63: myputs("nN = Knight");
break;
case 79: myputs("bB = Bishop");
break;
case 95: myputs("iI = Pawn");
break;
case 111: myputs("i = BLACK, I = WHITE Pawn");
break;
case 127: myputs("Move: c2c4<ENTER><ENTER>");
break;
default: myputchar(10);
}
#else
myputchar(10);
#endif
if (N < 127) writeInteger_WIFI(7-(N>>4), DEC);
}
else {
if (!N) myputchar('8');
myputchar(' ');
myputchar(".?inkbrq?I?NKBRQ"[b[N]&15]); /* Pawn is i*/
}
}
myputs(" A B C D E F G H");
}
/*****************************************************************************/
// Main function - The program starts here:
int main(void)
{
initRP6M256(); // Always call this first! The Processor will not work
// correctly otherwise.
initLCD(); // Initialize the LC-Display (LCD)
// Always call this before using the LCD!
// Now write Text via the WIFI Interface:
writeString_P_WIFI("\n\n _______________________\n");
writeString_P_WIFI(" \\| RP6 ROBOT SYSTEM |/\n");
writeString_P_WIFI(" \\_-_-_-_-_-_-_-_-_-_/\n\n");
writeString_P_WIFI("Chess for RP6 CONTROL M256 WIFI!\n");
// Set the four Status LEDs:
setLEDs(0b1111);
mSleep(500);
setLEDs(0b0000);
showScreenLCD("################", "################");
mSleep(1500);
showScreenLCD("RP6v2-M256-WIFI ", "<<LC - DISPLAY>>");
mSleep(1500);
showScreenLCD(" Chess 1.1 ", " ************ ");
mSleep(1500);
clearLCD(); // Clear the whole LCD Screen
/*****************************************************************************/
// micro-Max chess engine V4.8 (initialisation):
mysrand(get_seed()); /* make myrand() calls random */
// micro-Max chess engine V4.8 (play loop):
do{ /* play loop */
print_new_board();
myputs(c);
p=c;W((*p++=mygetchar())>10); /* read input line */
K=I; /* invalid move */
if(*c-10)K=*c-16*c[1]+799,L=c[2]-16*c[3]+799; /* parse entered move */
N=0;T=0x3F; /* T=Computer Play strength */
}W(D(-I,I,Q,O,1,3)>-I+1); /* think or check & do */
print_new_board();
/*****************************************************************************/
return 0;
}
/******************************************************************************
* Additional info
* ****************************************************************************
* Changelog:
* - v. 1.1 New board & help text added 03.01.2014 by Dirk
* - v. 1.0 (initial release) 03.01.2014 by Dirk
*
* ****************************************************************************
*/
/*****************************************************************************/
Lesezeichen