Absender: Frank Menzel
Datum: Do, 01.10.2009 21:13:05
Hallo, anbei mal ein Patch, um den bot Schach spielen zu lassen. Weiterhin der Chessparcour. Zur Beschreibung mal aus der Quelle rauskopiert: * Der Bot spielt Schach! Das Schachverhalten ermoeglicht die manuelle Eingabe * eines Schachzuges des Spielers 1 (weiss) ueber das Screeninterface. Nach Betaetigen * der GO-Taste zieht der Bot-Spieler und der Bot fährt auf dem Schachbrett diesen * Zug nach. Nun ist der menschliche Spieler wieder am Zug via Screeneingabe bzw. drückt sofort GO, * um fuer sich den Zug machen zu lassen. Am besten ist es (weil ja die Schachfiguren nicht visualisiert werden), * sich parallel dazu ein echtes Schachbrett aufzubauen und manuell die Zuege nachzuvollziehen. In meinem ersten Test * musste ich eine Niederlage gegen den Bot einstecken:-) * Fuer das Verhalten ist das Chess-Layout zu laden, damit wenigstens die Schachfelder visualisiert werden und damit die * Botfahrten der gegnerischen Schachzuege. Die gruenen Felder stehen hierbei stellvertretend fuer die weissen Felder. * Inspiriert zu diesem Verhalten wurde ich durch folgende Seiten: * http://bralug.de/wiki/BLIT2008-Board_spielt_Schach * Detailliertes zu dem Micro-Max Schach ist hier zu finden: * http://home.hccnet.nl/h.g.muller/max-src2.html * * Brainstorming fuer moegliche Erweiterungen: * Der Bot koennte gegen den anderen spielen ohne Mensch, d.h. Bot 1 ist Spieler 1 und der andere der Gegenspieler. * Jeder bot macht jeweils einen Zug und fährt diesen ab. Danach ist der andere dran. Dies muesste/koennte dann ueber die * bot_2_bot-Kommunikation laufen. Noch schoener waere es natuerlich, echte Spielfiguren auf dem Java3D-Schachbrett zu haben * (oder zuerst auch einfache Objekte), wobei der bot sich jeweils die Figur greift (bot_catch_pillar) und an der Zielposition * ablaedt (bot_unload_pillar)... * Da es mir endlich geglückt war, Eclipse-Galileo mit allem notwendigen Zeugs zu installieren, konnte ich endlich den Patch auf die aktuelle Quelle fertig stellen. So wünsche ich viel Spaß:-) Gruß, Frank
### Eclipse Workspace Patch 1.0 #P ct-Bot Index: bot-logic/bot-logik.c =================================================================== --- bot-logic/bot-logik.c (revision 1618) +++ bot-logic/bot-logik.c (working copy) @@ -346,6 +346,10 @@ insert_behaviour_to_list(&behaviour, new_behaviour(40, bot_follow_object_behaviour, INACTIVE)); #endif + #ifdef BEHAVIOUR_DRIVE_CHESS_AVAILABLE + insert_behaviour_to_list(&behaviour, new_behaviour(39, bot_drive_chess_behaviour, INACTIVE)); + #endif + #ifdef BEHAVIOUR_DRIVE_STACK_AVAILABLE insert_behaviour_to_list(&behaviour, new_behaviour(33, bot_drive_stack_behaviour, INACTIVE)); #endif Index: bot-logic/behaviour_drive_chess.c =================================================================== --- bot-logic/behaviour_drive_chess.c (revision 0) +++ bot-logic/behaviour_drive_chess.c (revision 0) @@ -0,0 +1,746 @@ +/* + * c't-Bot + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your + * option) any later version. + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307, USA. + * + */ + + +/*! + * @file behaviour_drive_chess.c + * @brief Der Bot spielt Schach! Das Schachverhalten ermoeglicht die manuelle Eingabe + * eines Schachzuges des Spielers 1 (weiss) ueber das Screeninterface. Nach Betaetigen + * der GO-Taste zieht der Bot-Spieler und der Bot fährt auf dem Schachbrett diesen + * Zug nach. Nun ist der menschliche Spieler wieder am Zug via Screeneingabe bzw. drückt sofort GO, + * um fuer sich den Zug machen zu lassen. Am besten ist es (weil ja die Schachfiguren nicht visualisiert werden), + * sich parallel dazu ein echtes Schachbrett aufzubauen und manuell die Zuege nachzuvollziehen. In meinem ersten Test + * musste ich eine Niederlage gegen den Bot einstecken:-) + * Fuer das Verhalten ist das Chess-Layout zu laden, damit wenigstens die Schachfelder visualisiert werden und damit die + * Botfahrten der gegnerischen Schachzuege. Die gruenen Felder stehen hierbei stellvertretend fuer die weissen Felder. + * Inspiriert zu diesem Verhalten wurde ich durch folgende Seiten: + * http://bralug.de/wiki/BLIT2008-Board_spielt_Schach + * Detailliertes zu dem Micro-Max Schach ist hier zu finden: + * http://home.hccnet.nl/h.g.muller/max-src2.html + * + * Brainstorming fuer moegliche Erweiterungen: + * Der Bot koennte gegen den anderen spielen ohne Mensch, d.h. Bot 1 ist Spieler 1 und der andere der Gegenspieler. + * Jeder bot macht jeweils einen Zug und fährt diesen ab. Danach ist der andere dran. Dies muesste/koennte dann ueber die + * bot_2_bot-Kommunikation laufen. Noch schoener waere es natuerlich, echte Spielfiguren auf dem Java3D-Schachbrett zu haben + * (oder zuerst auch einfache Objekte), wobei der bot sich jeweils die Figur greift (bot_catch_pillar) und an der Zielposition + * ablaedt (bot_unload_pillar)... + * + * @author Frank Menzel (Menzelfr@xxxxxx) + * @date 15.09.2009 + */ + + + + + + +#include "bot-logic/bot-logik.h" +#include <stdlib.h> +#include "log.h" +#include "rc5-codes.h" +#include "display.h" + +#ifdef BEHAVIOUR_DRIVE_CHESS_AVAILABLE + + +//#define DEBUG_CHESS // Schalter fuer Debugausgaben + + +#ifdef MCU +#undef DEBUG_CHESS +#endif +#ifndef LOG_AVAILABLE +#undef DEBUG_CHESS +#endif +#ifndef DEBUG_CHESS +#undef LOG_DEBUG +#define LOG_DEBUG(a, ...) {} +#endif + + + +/***************************************************************************/ +/* Los geht es mit den benoetigten Routinen fuer das Schachprogramm */ +/* sowie dem Schachprogramm dann selbst */ +/***************************************************************************/ + +/*! Digitstellen des Schachzuges fuer Eingabe als auch fuer Anzeige des berechneten Zuges */ +uint8_t d_0 = '0'; +uint8_t d_1 = '0'; +uint8_t d_2 = '0'; +uint8_t d_3 = '0'; + + + +/*! + * Ausgabe einer Stelle des Zuges auf dem Display + * @param offset Position der anzuzeigenden Stelle + * @param d Ausgabezeichen + */ +void print_move_digit(uint8_t offset, uint8_t d) { + + switch (offset) { + case 0: + d_0=d; + break; + + case 1: + d_1=d; + break; + + case 2: + d_2=d; + break; + + case 3: + d_3=d; + break; + } +} + + + +/*! + * Loeschen der Zug-Anzeigestellen auf dem Display + */ +void clean_move_digits(void) { + d_0=' '; + d_1=' '; + d_2=' '; + d_3=' '; +} + +/*! + * Anzeige der 4 Zug-Zeichenstellen + * @param d0 Zeichen an 1. Stelle + * @param d1 Zeichen an 2. Stelle + * @param d2 Zeichen an 3. Stelle + * @param d3 Zeichen an 4. Stelle + */ +void print_move(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) { + // globale Vars nur setzen, werden vom Display selbst ausgegeben + d_0 = d0; + d_1 = d1; + d_2 = d2; + d_3 = d3; +} + + + +/***************************************************************************/ +/* 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 */ + +#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 */ + +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 */ +} _, 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[] PROGMEM = { + 0,2,2,7,-1,8,12,23}; /* relative piece values */ + +const signed char o[] PROGMEM = { + -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=99; /* @ temporary */ +/*hv;*/ /* zeige Hauptvariante, d.h automat. Zugermittlung oder nicht*/ + + +//********************************************************* +unsigned char st=2; /* Spielstufe (Level) */ + +#define UNIX // at least for this program, MS-Windows is UNIX, Erhoehung Zaehler in jedem Durchlauf + + +long timer; // wird alle 4.096ms erhoeht bzw. durch Increment + +int16_t MaxMoves = 40, MaxTime = 30*40, moves; +long nodes, newNodes; + + +#define F_NEWGAME '3' +#define F_LEVEL '.' +#define F_FAVORIT '?' + +#define CL '9' +#define GO ':' + + + + +//#ifdef PC + #define o(ndx) (signed char)o[ndx] + #define w(ndx) (signed char)w[ndx] +//#else + //#define o(ndx) (signed char)pgm_read_byte_(o+(ndx)) + //#define w(ndx) (signed char)pgm_read_word(w+(ndx)) +//#endif // PC + + +void D(void); + + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +// nein, in dem folgenden Codefragment fusche ich dann nicht mehr rum, es +// scheint sich dabei um das eigentliche Orginal von H.G. Muller zu handeln, +// was sowie keiner versteht... +// F. Menzel: Leider kommen hier diverse Warnings beim Uebersetzen, funktioniert +// aber durch die Vorrangregeln prima. Mir ist es leider nicht geglückt, +// die Klammern entsprechend richtig zu setzen, damit die Quelle +// warnungsfrei wird +//TODO: Klammernsetzung fuer Warnungsfreiheit +/* -------------------------------------------------------------------------- */ +/* 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 + + +/* ***************************************************************************** + * MEL: hier kommen leider lauter Warnungen, ist aber der Originalcode, welcher + * wohl mit Absicht genau so geschrieben wurde; + * ist mir leider nicht geglueckt, die Klammern an der richtigen Stelle zu setzen + * vielleicht kann das ja jemand anderes machen mit tieferem C-Wissen??? + *******************************************************************************/ + + +void D() /* iterative Negamax search */ +{ + +D:if (--J<A) { /* stack pointer decrement and underrun check */ + ++J;DD=-l;goto R; /* simulated return */ + } + q=Dq;l=Dl;e=De;E=DE;z=Dz;n=Dn; /* load arguments */ + a=Da; /* load return address state*/ + + --q; /* adj. window: delay bonus */ + k^=24; /* change sides */ + d=X=Y=0; /* start iter. from scratch */ + while(d++<n||d<3|| /* iterative deepening loop */ + z&K==I&&(timer<0&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*/ + if(d<3)P=I;else + {*J=_;Dq=-l;Dl=1-l;De=-e;DE=S;Dz=0;Dn=d-3; /* save locals, arguments */ + Da=0;goto D; /* Search null move */ +R0:_=*J;P=DD; /* load locals, return value*/ + } + m=-P<l|R>35?d>2?-I:e:-P; /* Prune or stand-pat */ +#ifdef UNIX + ++timer; /* node count (for timing) */ +#endif + 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*/ + while(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 J; /* 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 + if(C>2|v>V) + {*J=_;Dq=-l;Dl=-V;De=-v;DE=F;Dz=0;Dn=C; /* save locals, arguments */ + Da=1;goto D; /* iterative eval. of reply */ +R1: _=*J;s=-DD; /* load locals, return value*/ + }else s=v; /* or fail low if futile */ + while(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;++J;DD=l;goto R; /* 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. */ + }while(!t); /* if not capt. continue ray*/ + }}}while((x=x+9&~M)-B); /* next sqr. of board, wrap */ +J: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&hv&d>2) { + print_move('a'+(X&7), '8'-(X>>4), 'a'+(Y&7), '8'-(Y>>4&7)); + }*/ + } /* encoded in X S,8 bits */ + k^=24; /* change sides back */ + ++J;DD=m+=m<e; /* delayed-loss bonus */ +R:if (J!=A+U) switch(a){case 0:goto R0;case 1:goto R1;} + else return; +} + + + +/* ***************************************************************************** + * Ende der Original-Schachroutinen + * Beginn der Routinen des Verhaltens und natuerlich Verhalten selbst + *******************************************************************************/ +#ifdef PC +#define OFFSET 240; /*!< Offsetwert, um genau von einer Sim-Schachfeld-Position zur naechsten zu kommen */ +#else +// fuer MCU anpassen je nach Groesse des echten Schachbrettes +#define OFFSET 240; /*!< Offsetwert, um genau von einer Sim-Schachfeld-Position zur naechsten zu kommen */ +#endif + +static uint8_t state = 0; /*!< Status des Verhaltens */ + + +uint8_t white; /*!< Kennung welcher Spieler gerade dran ist, nur Schwarz wird vom Bot gefahren */ + + + +/*! + * Umwandeln der Zug-Zeichenstellen in Bot-Worldkoordinaten zum Abfahren des Zuges auf dem Sim-Schachfeld + * @param x_c 1. Stelle der Zugangabe (a bei Zug a2) + * @param y_c 2. Stelle der Zugangabe (2 bei Zug a2) + * @param *wx x-Koordinate fuer Bot-Zielposition + * @param *wy y-Koordinate fuer Bot-Zielposition + */ +void chess2worldkoords(char x_c, char y_c, int16_t *wx, int16_t *wy) { + //aus Klein- Grossbuchstaben machen und Offsetwert zu-/abrechnen + *wx=(x_c-97) * -OFFSET; /* nach Rechts x-Richtung, Werte werden negativ und um 1 Offsetfeld verschoben */ + *wx=*wx-OFFSET + *wy=(y_c-49) * OFFSET; /* nach Oben y-Richtung, Werte positiver aber um 1 Offset-Feld verschoben */ + *wy=*wy+OFFSET; +} + + +/*! + * Aufgerufene Routine nach Taste GO; der eingegebene Zug wird geparst bzw. ein neuer Schachzug ermittelt + * Ist die manuelle Zugeingabe erforderlich oder der Zug war nicht gueltig, erscheint auf dem Display ZU G? + * Routine wurde etwas von der Original-Schachroutine fuer diese Zwecke abgewandelt, enthaelt aber auch deren + * Initialisierungen, die man wohl nicht unbedingt verstehen muss bzw. erklaeren kann:-) Naeheres wohl auf der + * o.a. Website + * @result Rueckgabe der ausgefuehrten Aktion bzw. Status nach GO + * 1: manueller Zug geparst und gueltig; + * 2: Zug vom Prog berechnet; + * 0: sonst (Zug nicht gueltig) + */ +uint8_t chess_go(void) { + uint8_t result; + + result =0; + + if(*c-GO) { + /* parse entered move */ + K=*c-16*c[1]+799; + L=c[2]-16*c[3]+799; + LOG_DEBUG("Zug wurde eingegeben und parsen"); + } else { + K=I; + timer = -128<<st; /* set time control */ + clean_move_digits(); + LOG_DEBUG("Ich denke..."); + } + + Dq=-I;Dl=I;De=Q;DE=O;Dz=1;Dn=3; /* store arguments of D() */ + Da=0; /* state */ + + D(); + if(*c-GO) { // Zugeingabe vorhanden + if(I==DD) { // Zug ist gueltig + LOG_DEBUG("eing. Zug war gueltig"); + result = 1; + } else { // .. ungueltig + print_move('Z', 'U', 'G', '?'); + LOG_DEBUG("Zug? war nicht gueltig"); + } + *c=GO; + } else { // Computerzug + result = 2; + ++moves; // Zuganzahl erhoehen + print_move('a'+(K&7), '8'-(K>>4), 'a'+(L&7), '8'-(L>>4&7)); // Displayausgabe + LOG_DEBUG("Computerzug Zug %1d",moves); + LOG_DEBUG("Zug aus D() von %c %c nach %c %c",'a'+(K&7), '8'-(K>>4), 'a'+(L&7), '8'-(L>>4&7)); + if(!(DD>-I+1)){ + print_move('M', 'A', 'T', 'T'); // Displayausgabe + LOG_DEBUG("-- SCHACH MATT! --"); + } + } + + return result; +} + + +/*! + * Initialisierungen fuer neues Spiel + * aus Originalquelle uebernommen, naeheres dazu sicher auf o.a. Website + */ +void new_game_init(void) { + + LOG_DEBUG("Neues Spiel"); + print_move ('S', 'H', 'A', 'H'); + + k=16; + O=Q=R=0; + for(W=0; W < sizeof b; ++W) b[W]=0; + for(W=0; W < sizeof c; ++W) c[W]=0; // damit beim naechsten Start auch wieder Zugeingabe ausgegeben wird + W=8; + while(W--) { /* initial board setup*/ + b[W]=(b[W+112]=o(W+24)+8)+8; + + b[W+16]=18; + b[W+96]=9; + L=8; + while(L--) b[16*L+W+8]=(W-4)*(W-4)+(L+L-7)*(L+L-7)/4; /* center-pts table */ + } /*(in unused half b[])*/ + + W=4; + moves=0; // Anzahl Zuege ruecksetzen + white=0; // Spieler init. +} + + +// Status des Verhaltens +#define NEWGAME_STATE 0 +#define GO_STATE 1 +#define GO_STATE_NEXT 2 +#define CO_END 99 + + +/*! + * Das eigentliche Schach-Fahrverhalten + * Fuer den Bot-Spieler Schwarz wird nach dessen Zugberechnung der Zug vom Bot nachgefahren, fährt also von der Zug-Startposition + * zur Zug-Endposition. Das Verhalten ist dann damit abgeschlossen + * @param *data Der Verhaltensdatensatz + */ +void bot_drive_chess_behaviour(Behaviour_t * data) { +int16_t wx; // zur Umwandlung des Zuges in Botkoordinaten +int16_t wy; +uint8_t res_go; //Status nach GO + + switch (state) { + case NEWGAME_STATE: + /* Neues Spiel wird gestartet */ + LOG_DEBUG("-NEWGAME-"); + state=GO_STATE; + new_game_init(); + break; + + + case GO_STATE: + /* Einsprung fuer GO nach Zugeingabe */ + LOG_DEBUG("GO STATE"); + state = CO_END; + + res_go=chess_go(); + + if (res_go==1) { // nach man. Zug gleich Computerzug hinterher + white=!white; + LOG_DEBUG("gleich Compi ziehen lassen, Zug war OK, weiss %1d",white); + + state = GO_STATE; // gleichen Verhaltensstatus aufrufen + + } + else { + if (res_go==2) { + white=!white; + if (white) { + LOG_DEBUG("Weiss-keine Botbewegung"); + } + else {// nur wenn Schwarz an der Reihe ist bot bewegen + LOG_DEBUG("Bot fahren nach Autozug"); + LOG_DEBUG("Zug aus D() von %c %c nach %c %c",'a'+(K&7), '8'-(K>>4), 'a'+(L&7), '8'-(L>>4&7)); + chess2worldkoords('a'+(K&7),'8'-(K>>4&7), &wx,&wy); + LOG_DEBUG("gehe zu Zug-Startpos %1d,%1d, weiss %1d",wy,wx,white); + bot_goto_pos(data,wy,wx,999); + + state=GO_STATE_NEXT; + break; + } + } + + } + + break; + + + + + + case GO_STATE_NEXT: + /* Bot wird zu den Zug-Zielkoordinaten gefahren */ + chess2worldkoords('a'+(L&7),'8'-(L>>4&7),&wx,&wy); + LOG_DEBUG("gehe zu Zug-Zielpos %1d,%1d, weiss %1d",wy,wx,white); + bot_goto_pos(data,wy,wx,999); + + state = CO_END; // nach Abfahren Verhaltensende + + break; + + + default: + exit_behaviour(data, SUBFAIL); + return; + } +} + + + +/*! + * Neustart des eigentlichen Schach-Fahrverhalten + * Fuer den Bot-Spieler Schwarz wird nach dessen Zugberechnung der Zug vom Bot nachgefahren, fährt also von der Zug-Startposition + * zur Zug-Endposition. Das Verhalten ist dann damit abgeschlossen + * @param *caller Der Verhaltensdatensatz + */ +void bot_drive_chess(Behaviour_t * caller) { + switch_to_behaviour(caller, bot_drive_chess_behaviour, OVERRIDE); + state = NEWGAME_STATE; +} + + +/*! + * Start des Schach-Fahrverhalten nach GO-Betaetigung, d.h. nach Eingabe des Zuges wurde GO betaetigt + * @param *caller Der Verhaltensdatensatz + */ +void bot_drive_chess_go(Behaviour_t * caller) { + switch_to_behaviour(caller, bot_drive_chess_behaviour, OVERRIDE); + state = GO_STATE; +} + + +/*! + * Routine fuer manuelle Zugeingabe (Tastaturauswertung) + */ +void after_input(void) { + if (!(W&1)) //Umwandlung Zahl->Zeichen an je 1. Stelle, also an je ungerader Position + c[W] += 'a' - '1'; //W ist hierbei der Digit-Positionszaehler des Digits fuer den Zug + + switch (W) { + default: + print_move_digit(W, c[W]); + ++W; + break; + case 4: // getkey() anzeigen + clean_move_digits(); + c[0]=c[4]; + print_move_digit(0, c[0]); + W=1; + break; + case 5: // getkey() nicht anzeigen + clean_move_digits(); + W=0; + break; + } + +} + +/*! + * Keyhandler fuer das Chess-Verhalten + */ +#ifdef DISPLAY_DRIVE_CHESS_AVAILABLE +static void drivechess_disp_key_handler(void) { + switch (RC5_Code) { + case RC5_CODE_STOP: + /* Newgame */ + RC5_Code = 0; + c[W] = F_NEWGAME; + // Verhaltensstart Newgame + bot_drive_chess(NULL); + break; + + case RC5_CH_PLUS: + /* Level veraendern */ + RC5_Code = 0; + c[W] = F_LEVEL; + st++; + LOG_DEBUG("Level erhoeht auf %1d",st); + break; + + case RC5_CH_MINUS: + /* Level veraendern */ + RC5_Code = 0; + c[W] = F_LEVEL; + st--; + LOG_DEBUG("Level verringert auf %1d",st); + + break; + + + case RC5_CODE_BLUE: + /* Zugzeile loeschen */ + RC5_Code = 0; + c[W] = CL; + LOG_DEBUG("CLEAR %c",c[W]); + after_input(); + clean_move_digits(); + W=0; + break; + + + +case RC5_CODE_PLAY: + /* GO */ + RC5_Code = 0; + if (W==99) { + LOG_DEBUG("vor GO erstmaliges INIT"); + //new_game_init(); + bot_drive_chess(NULL); + } + else { + // Verhaltensstart im Status GO + bot_drive_chess_go(NULL); + } + c[W] = GO; + break; + +default: + /* wird immer durchlaufen fuer alle anderen Tasten als oben angegeben */ + /* hier nur noch die Tasten fuer man. Zugeingabe rauspicken */ + switch (RC5_Code) { + case RC5_CODE_1:c[W]='1';after_input();RC5_Code = 0;break; + case RC5_CODE_2:c[W]='2';after_input();RC5_Code = 0;break; + case RC5_CODE_3:c[W]='3';after_input();RC5_Code = 0;break; + case RC5_CODE_4:c[W]='4';after_input();RC5_Code = 0;break; + case RC5_CODE_5:c[W]='5';after_input();RC5_Code = 0;break; + case RC5_CODE_6:c[W]='6';after_input();RC5_Code = 0;break; + case RC5_CODE_7:c[W]='7';after_input();RC5_Code = 0;break; + case RC5_CODE_8:c[W]='8';after_input();RC5_Code = 0;break; + case RC5_CODE_9:c[W]='9';after_input();RC5_Code = 0;break; + }//switch + + break; + + } // switch +} // Ende Keyhandler + + +/*! + * Display zum Steuern des Schachverhaltens + */ +void drive_chess_display(void) { + display_cursor(1, 1); + display_printf("Chess Level %1d",st); + display_cursor(2, 1); + display_printf("Zug : %c%c %c%c",d_0,d_1,d_2,d_3); + display_cursor(3, 1); + display_printf("CL BLUE/Lv CH+-"); + display_cursor(4, 1); + display_printf("Go PLAY/New STOP"); + + drivechess_disp_key_handler(); // aufrufen des Key-Handlers +} +#endif // DISPLAY_DRIVE_CHESS_AVAILABLE + +#endif // BEHAVIOUR_DRIVE_CHESS_AVAILABLE Index: .cproject =================================================================== --- .cproject (revision 1618) +++ .cproject (working copy) @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?xml version="1.0" encoding="UTF-8"?> <?fileVersion 4.0.0?> <cproject> @@ -15,7 +15,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> -<configuration artifactExtension="exe" artifactName="ct-Bot" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="Windows mit Debug-Code" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.debug.1077176217" name="Debug-W32" parent="cdt.managedbuild.config.gnu.exe.debug" postbuildStep="objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary ct-Bot.exe ct-Bot.eep; objdump -t ct-bot.exe | grep "(sec 5)" | grep "(nx 0)" > eeprom_pc.map"> +<configuration artifactExtension="exe" artifactName="ct-Bot" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="Windows mit Debug-Code" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.debug.1077176217" name="Debug-W32" parent="cdt.managedbuild.config.gnu.exe.debug" postbuildStep="objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary ct-Bot.exe ct-Bot.eep; objdump -t ct-bot.exe | grep "(sec 5)" | grep "(nx 0)" > eeprom_pc.map"> <folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1077176217.380212843" name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.1011694867" name="GCC Tool Chain" superClass="cdt.managedbuild.toolchain.gnu.exe.debug"> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.1735484471" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/> Index: ui/available_screens.h =================================================================== --- ui/available_screens.h (revision 1618) +++ ui/available_screens.h (working copy) @@ -48,6 +48,7 @@ #define DISPLAY_DRIVE_STACK_AVAILABLE /*!< Steuerung Stack-Verhalten auf diesem Screen */ #define PATHPLANING_DISPLAY /*!< Display zur Pfadplanung */ #define DISPLAY_LINE_SHORTEST_WAY_AVAILABLE /*!< Steuerung des Verhaltens auf diesem Screen */ +#define DISPLAY_DRIVE_CHESS_AVAILABLE /*!< Steuerung des Schach-Verhaltens */ #ifndef SPEED_CONTROL_AVAILABLE #undef DISPLAY_REGELUNG_AVAILABLE Index: Changelog.txt =================================================================== --- Changelog.txt (revision 1618) +++ Changelog.txt (working copy) @@ -1,5 +1,7 @@ CHANGELOG fuer c't-Bot ====================== +2009-05-28 Frank Menzel [Menzelfr@xxxxxx]: Der Bot spielt Schach! Neues Schachverhalten behaviour_drive_chess + 2009-09-24 Timo Sandmann [mail@xxxxxxxxxxxxxxx]: BPS-Sensordaten des echten Bots werden zum Sim uebertragen 2009-09-23 Timo Sandmann [mail@xxxxxxxxxxxxxxx]: Bugfix im Command-Code, keine Uebertragung der Lichtsensordaten, falls keine Lichtsensoren aktiv sind Index: include/bot-logic/behaviour_drive_chess.h =================================================================== --- include/bot-logic/behaviour_drive_chess.h (revision 0) +++ include/bot-logic/behaviour_drive_chess.h (revision 0) @@ -0,0 +1,77 @@ +/* + * c't-Bot + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your + * option) any later version. + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307, USA. + * + */ + + +/*! + * @file behaviour_drive_chess.c + * @brief Der Bot spielt Schach! Das Schachverhalten ermoeglicht die manuelle Eingabe + * eines Schachzuges des Spielers 1 (weiss) ueber das Screeninterface. Nach Betaetigen + * der GO-Taste zieht der Bot-Spieler und der Bot fährt auf dem Schachbrett diesen + * Zug nach. Nun ist der menschliche Spieler wieder am Zug via Screeneingabe bzw. drückt sofort GO, + * um fuer sich den Zug machen zu lassen. Am besten ist es (weil ja die Schachfiguren nicht visualisiert werden), + * sich parallel dazu ein echtes Schachbrett aufzubauen und manuell die Zuege nachzuvollziehen. In meinem ersten Test + * musste ich eine Niederlage gegen den Bot einstecken:-) + * Fuer das Verhalten ist das Chess-Layout zu laden, damit wenigstens die Schachfelder visualisiert werden und damit die + * Botfahrten der gegnerischen Schachzuege. Die gruenen Felder stehen hierbei stellvertretend fuer die weissen Felder. + * Inspiriert zu diesem Verhalten wurde ich durch folgende Seiten: + * http://bralug.de/wiki/BLIT2008-Board_spielt_Schach + * Detailliertes zu dem Micro-Max Schach ist hier zu finden: + * http://home.hccnet.nl/h.g.muller/max-src2.html + * + * Brainstorming fuer moegliche Erweiterungen: + * Der Bot koennte gegen den anderen spielen ohne Mensch, d.h. Bot 1 ist Spieler 1 und der andere der Gegenspieler. + * Jeder bot macht jeweils einen Zug und fährt diesen ab. Danach ist der andere dran. Dies muesste/koennte dann ueber die + * bot_2_bot-Kommunikation laufen. Noch schoener waere es natuerlich, echte Spielfiguren auf dem Java3D-Schachbrett zu haben + * (oder zuerst auch einfache Objekte), wobei der bot sich jeweils die Figur greift (bot_catch_pillar) und an der Zielposition + * ablaedt (bot_unload_pillar)... + * + * @author Frank Menzel (Menzelfr@xxxxxx) + * @date 15.09.2009 + */ +#ifndef BEHAVIOUR_DRIVE_CHESS_H_ +#define BEHAVIOUR_DRIVE_CHESS_H_ + +#include "ct-Bot.h" +#include "bot-logic/bot-logik.h" + +#ifdef BEHAVIOUR_DRIVE_CHESS_AVAILABLE + +/*! + * Das eigentliche Schach-Fahrverhalten + * Fuer den Bot-Spieler Schwarz wird nach dessen Zugberechnung der Zug vom Bot nachgefahren, fährt also von der Zug-Startposition + * zur Zug-Endposition. Das Verhalten ist dann damit abgeschlossen + * @param *data Der Verhaltensdatensatz + */ +void bot_drive_chess_behaviour(Behaviour_t * data); + +/*! + * Neustart des eigentlichen Schach-Fahrverhalten + * Fuer den Bot-Spieler Schwarz wird nach dessen Zugberechnung der Zug vom Bot nachgefahren, fährt also von der Zug-Startposition + * zur Zug-Endposition. Das Verhalten ist dann damit abgeschlossen + * @param *caller Der Verhaltensdatensatz + */ +void bot_drive_chess(Behaviour_t * caller); + +/*! + * Display zum Steuern des Schachverhaltens + */ +void drive_chess_display(void); + +#endif // BEHAVIOUR_DRIVE_CHESS_AVAILABLE +#endif /*BEHAVIOUR_DRIVE_CHESS_H_*/ Index: include/bot-logic/available_behaviours.h =================================================================== --- include/bot-logic/available_behaviours.h (revision 1618) +++ include/bot-logic/available_behaviours.h (working copy) @@ -60,6 +60,8 @@ //#define BEHAVIOUR_DRIVE_AREA_AVAILABLE /*!< flaechendeckendes Fahren mit Map */ +#define BEHAVIOUR_DRIVE_CHESS_AVAILABLE /*!< Schach fuer den Bot */ + //#define BEHAVIOUR_LINE_SHORTEST_WAY_AVAILABLE /*!< Linienfolger ueber Kreuzungen zum Ziel */ //#define BEHAVIOUR_SCAN_BEACONS_AVAILABLE /*!< Suchen von Landmarken zur Lokalisierung */ @@ -88,6 +90,10 @@ #endif #endif +#ifdef BEHAVIOUR_DRIVE_CHESS_AVAILABLE + #define BEHAVIOUR_GOTO_POS_AVAILABLE +#endif + #ifdef BEHAVIOUR_DRIVE_AREA_AVAILABLE #define BEHAVIOUR_GOTO_POS_AVAILABLE #define BEHAVIOUR_GOTO_OBSTACLE_AVAILABLE @@ -276,6 +282,8 @@ #include "bot-logic/behaviour_drive_area.h" +#include "bot-logic/behaviour_drive_chess.h" + #include "bot-logic/behaviour_pathplaning.h" #include "bot-logic/behaviour_line_shortest_way.h" Index: ct-Bot.h =================================================================== --- ct-Bot.h (revision 1618) +++ ct-Bot.h (working copy) @@ -79,7 +79,7 @@ //#define MAP_AVAILABLE /*!< Aktiviert die Kartographie */ //#define MAP_2_SIM_AVAILABLE /*!< Sendet die Map zur Anzeige an den Sim */ -//#define SPEED_CONTROL_AVAILABLE /*!< Aktiviert die Motorregelung */ +#define SPEED_CONTROL_AVAILABLE /*!< Aktiviert die Motorregelung */ //#define ADJUST_PID_PARAMS /*!< macht PID-Paramter zur Laufzeit per FB einstellbar */ //#define SPEED_LOG_AVAILABLE /*!< Zeichnet Debug-Infos der Motorregelung auf MMC auf */ Index: ui/gui.c =================================================================== --- ui/gui.c (revision 1618) +++ ui/gui.c (working copy) @@ -299,7 +299,10 @@ #ifdef BEHAVIOUR_LINE_SHORTEST_WAY_AVAILABLE register_screen(&bot_line_shortest_way_display); #endif + #ifdef DISPLAY_DRIVE_CHESS_AVAILABLE + register_screen(&drive_chess_display); #endif + #endif } #endif // DISPLAY_AVAILABLE