PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fehlermeldung bei goto Befehl



fredyxx
01.01.2018, 10:24
Hallo,
vorweg will ich sagen, dass ich weiß, dass man goto eigentlich nicht verwenden soll!

Trotzdem meine Frage:

Der folgende Code funktioniert:



if (M1_fertig == true) {
goto M3_Sprung; // M1u M2 werden übersprungen
}


Das Label "M3_Sprung" befindet sich weiter unten in einem größeren Programm

Während bei dem nächsten die Fehlermeldung "jump to label 'gummi' [-fpermissive]" erscheint.



if (Entf_int >= 99) {
digitalWrite (Pin_a, HIGH);
digitalWrite (Pin_b, LOW);

Ueberlauf();

goto gummi;

} // >>>>> ENDE if (Entf_int >= 99)

String Einer = Entf_String.substring(1, 2); // Selektion der Einerstelle
String Zehner = Entf_String.substring(0, 1); // Selektion der Zehnerstelle
gummi:
Zehnerstelle = Zehner.toInt();
Einerstelle = Einer.toInt();



Wenn ich "goto gummi;" und "gummi:" entferne, erhalte ich keine Fehlermeldung für dieses Programm.

Ich kann zwischen den beiden Beispielen keinen Unterschied erkennen.
Wie kommt es zu dieser Fehlermeldung beim Kompilieren?

Gruß
fredyxx

Rabenauge
01.01.2018, 10:59
Warum schreibt man sowas?
Es gibt durchaus sehr gute Gründe, wieso man goto eben _nicht_ verwenden sollte, und der geringste davon ist: weil man es niemals braucht.

https://www.arduino.cc/reference/en/language/structure/control-structure/goto/ dort im Beispiel sehe ich geschweifte Klammern- evtl. sind die das Problem bei dir?

Holomino
01.01.2018, 11:16
Gefunden in https://stackoverflow.com/questions/14274225/statement-goto-can-not-cross-variable-definition
Danach ist der Compiler über die übersprungene Definition der benutzten Variablen "Einer" und "Zehner" sehr, sehr unglücklich.

Workaround ist beschrieben, vielleicht hilft's.

HaWe
01.01.2018, 11:51
Warum schreibt man sowas?
Es gibt durchaus sehr gute Gründe, wieso man goto eben _nicht_ verwenden sollte, und der geringste davon ist: weil man es niemals braucht.

https://www.arduino.cc/reference/en/language/structure/control-structure/goto/ dort im Beispiel sehe ich geschweifte Klammern- evtl. sind die das Problem bei dir?

@Rabenauge: https://www.arduino.cc/reference/en/language/structure/control-structure/goto/

The reason that many programmers frown upon the use of goto is that with the unrestrained use of goto statements, it is easy to create a program with undefined program flow, which can never be debugged.
With that said, there are instances where a goto statement can come in handy, and simplify coding. One of these situations is to break out of deeply nested for loops, or if logic blocks, on a certain condition.

ich kenne - und habe selber - ein paar Programme, bei denen es nahezu unmöglich ist, ohne goto auszukommen - Beispiel gefällig? 8)


Gefunden in https://stackoverflow.com/questions/14274225/statement-goto-can-not-cross-variable-definition
Danach ist der Compiler über die übersprungene Definition der benutzten Variablen "Einer" und "Zehner" sehr, sehr unglücklich.
Workaround ist beschrieben, vielleicht hilft's.

schön formuliert ;)
Holomino hat völlig Recht, du musst deine Variablendeklarationen für die Strings ein paar Stufen höher machen, z.B. im Kopf der Funktion oder sogar global, damit sie nie von goto übersprungen werden können.

Holomino
01.01.2018, 12:00
Wobei mir hier die Feinheit "Deklaration" oder "Definition" auch nicht ganz klar ist.
C++ sollte eigentlich egal sein, ob die Variable oben oder in der Mitte deklariert ist, solange kein Block ({})explizit den Scope einschränkt. Einen Nullstring-Pointer in einen Int zu wandeln, erscheint mir hier kritischer, wobei das eher zur Laufzeit unangenehm auffallen sollte.

HaWe
01.01.2018, 12:03
eigentlich Definition eher als (nur) Deklaration, aber das soll hier sekundär sein.
Der Punkt ist:
zumindest ein paar Stufen höher machen, damit sie nie von goto übersprungen werden können.

fredyxx
02.01.2018, 09:24
Gefunden in https://stackoverflow.com/questions/14274225/statement-goto-can-not-cross-variable-definition
Danach ist der Compiler über die übersprungene Definition der benutzten Variablen "Einer" und "Zehner" sehr, sehr unglücklich.

Workaround ist beschrieben, vielleicht hilft's.

Herzlichen Dank.
Das ist die Lösung nun klappt es.

Gruß
fredyxx

Rabenauge
02.01.2018, 10:25
@Hawe: ich fürchte, ich komme mit deinem Programmierstil (soll keinerlei Kritik sein!) nicht klar- aber ja, würde mich interessieren.
Goto's hab ich das letzte Mal vor, hm, sagen wir, 25 Jahren benutzt, als ich mich noch mit BASIC beschäftigt hab.

Zwischendurch hatte ich einige Male durchaus den Gedanken "man, ein >Goto< würde das jetzt ganz fix lösen"- aber ich konnt es ausnahmslos vermeiden.
Von daher: nein, man braucht es definitiv nicht in Arduino-Slang, würd ich sagen.
Zugegeben: es ergibt ohne manchmal ein paar Zeilen Code mehr, aber das ist egal, wichtig ist nur, was am Ende (compiliert) dabei raus kommt, und die Compiler sind inzwischen ziemlich clevere Kerlchen geworden.
Ich erinnere mich noch dunkel an den uralten BASCOM (lief damals auf meinem Robotron A5110 unter SCP)- das war ne ganz andere, eigene Welt....:cool:

HaWe
02.01.2018, 12:11
@Hawe: ich fürchte, ich komme mit deinem Programmierstil (soll keinerlei Kritik sein!) nicht klar- aber ja, würde mich interessieren.
Goto's hab ich das letzte Mal vor, hm, sagen wir, 25 Jahren benutzt, als ich mich noch mit BASIC beschäftigt hab.

Zwischendurch hatte ich einige Male durchaus den Gedanken "man, ein >Goto< würde das jetzt ganz fix lösen"- aber ich konnt es ausnahmslos vermeiden.
Von daher: nein, man braucht es definitiv nicht in Arduino-Slang, würd ich sagen.
Zugegeben: es ergibt ohne manchmal ein paar Zeilen Code mehr, aber das ist egal, wichtig ist nur, was am Ende (compiliert) dabei raus kommt, und die Compiler sind inzwischen ziemlich clevere Kerlchen geworden.
Ich erinnere mich noch dunkel an den uralten BASCOM (lief damals auf meinem Robotron A5110 unter SCP)- das war ne ganz andere, eigene Welt....:cool:

schau mal, ob du die gotos zu den beiden Sprungmarken A: und C: in der rekursiven Funktion hier rauskriegst (ich finde es zumindest klarer, eindeutiger und übersichtlicher damit)...
(dies erste hier ist die Original-Ideen-Vorlage zu meiner Chess-Engine)


// http://home.hccnet.nl/h.g.muller/max-src2.html
#define F(I,S,N) for(I=S;I<N;I++)
#define W(A) while(A)
#define K(A,B) *(int*)(T+A+(B&8)+S*(B&7))
#define J(A) K(y+A,b[y])-K(x+A,u)-K(H+A,t)

#define U 16777224
struct _ {int K,V;char X,Y,D;} A[U]; /* hash table, 16M+8 entries*/

int V=112,M=136,S=128,I=8e4,C=799,Q,N,i; /* V=0x70=rank mask, M=0x88 */

char O,K,L,
w[]={0,1,1,3,-1,3,5,9}, /* 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[129], /* board: half of 16x8+dummy*/
T[1035], /* hash translation table */

n[]=".?+nkbrq?*?NKBRQ"; /* piece symbols on printout*/

D(k,q,l,e,J,Z,E,z,n) /* recursive minimax search, k=moving side, n=depth*/
int k,q,l,e,J,Z,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/
{ /* e=score, z=prev.dest; J,Z=hashkeys; return score*/
int j,r,m,v,d,h,i=9,F,G;
char t,p,u,x,y,X,Y,H,B;
struct _*a=A;
/* lookup pos. in hash table*/
j=(k*E^J)&U-9; /* try 8 consec. locations */
W((h=A[++j].K)&&h-Z&&--i); /* first empty or match */
a+=i?j:0; /* dummy A[0] if miss & full*/
if(a->K) /* hit: pos. is in hash tab */
{d=a->D;v=a->V;X=a->X; /* examine stored data */
if(d>=n) /* if depth sufficient: */
{if(v>=l|X&S&&v<=q|X&8)return v; /* use if window compatible */
d=n-1; /* or use as iter. start */
}X&=~M;Y=a->Y; /* with best-move hint */
Y=d?Y:0; /* don't try best at d=0 */
}else d=X=Y=0; /* start iter., no best yet */
N++; /* node count (for timing) */
W(d++<n|z==8&N<1e7&d<98) /* iterative deepening loop */
{x=B=X; /* start scan at prev. best */
Y|=8&Y>>4; /* request try noncastl. 1st*/
m=d>1?-I:e; /* unconsidered:static eval */
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{H=y+=r; /* y traverses ray */
if(Y&8)H=y=Y&~M; /* sneak in prev. best move */
if(y&M)break; /* board edge hit */
if(p<3&y==E)H=y^16; /* shift capt.sqr. H if e.p.*/
t=b[H];if(t&k|p<3&!(r&7)!=!t)break; /* capt. own, bad pawn mode */
i=99*w[t&7]; /* value of capt. piece t */
if(i<0||E-S&&b[E]&&y-E<2&E-y<2)m=I; /* K capt. or bad castling */
if(m>=l)goto C; /* abort on fail high */

if(h=d-(y!=z)) /* remaining depth(-recapt.)*/
{v=p<6?b[x+8]-b[y+8]:0; /* center positional pts. */
b[G]=b[H]=b[x]=0;b[y]=u&31; /* do move, strip virgin-bit*/
if(!(G&M)){b[F]=k+6;v+=30;} /* castling: put R & score */
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 */
if(y+r+1&S){b[y]|=7;i+=C;} /* promote p to Q, add score*/
}
v=-D(24-k,-l-(l>e),m>q?-m:-q,-e-v-i, /* recursive eval. of reply */
J+J(0),Z+J(8)+G-S,F,y,h); /* J,Z: hash keys */
v-=v>e; /* delayed-gain penalty */
if(z==9) /* called as move-legality */
{if(v!=-I&x==K&y==L) /* checker: if move found */
{Q=-e-i;O=F;return l;} /* & not in check, signal */
v=m; /* (prevent fail-lows on */
} /* K-capt. replies) */
b[G]=k+38;b[F]=b[y]=0;b[x]=u;b[H]=t; /* undo move,G can be dummy */
if(Y&8){m=v;Y&=~8;goto A;} /* best=1st done,redo normal*/
if(v>m){m=v;X=x;Y=y|S&G;} /* update max, mark with S */
} /* if non castling */
t+=p<5; /* fake capt. for nonsliding*/
if(p<3&6*k+(y&V)==S /* pawn on 3rd/6th, or */
||(u&~24)==36&j==7&& /* virgin K moving sideways,*/
G&M&&b[G=(x|7)-(r>>1&7)]&32 /* 1st, virgin R in corner G*/
&&!(b[G^1]|b[G^2]) /* 2 empty sqrs. next to R */
){F=y;t--;} /* unfake capt., 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/4|m<-I/4)d=99; /* mate is indep. of depth */
m=m+I?m:-D(24-k,-I,I,0,J,Z,S,S,1)/2; /* best loses K: (stale)mate*/
if(!a->K|(a->X&M)!=M|a->D<=d) /* if new/better type/depth:*/
{a->K=Z;a->V=m;a->D=d;A->K=0; /* store in hash,dummy stays*/
a->X=X|8*(m>q)|S*(m<l);a->Y=Y; /* empty, type (limit/exact)*/
} /* encoded in X S,8 bits */
/*if(z==8)printf("%2d ply, %9d searched, %6d by (%2x,%2x)\n",d-1,N,m,X,Y&0x77);*/
}
if(z&8){K=X;L=Y&~M;}
return m;
}

main()
{
int j,k=8,*p,c[9];

F(i,0,8)
{b[i]=(b[i+V]=o[i+24]+40)+8;b[i+16]=18;b[i+96]=9; /* initial board setup*/
F(j,0,8)b[16*j+i+8]=(i-4)*(i-4)+(j-3.5)*(j-3.5); /* center-pts table */
} /*(in unused half b[])*/
F(i,M,1035)T[i]=random()>>9;

W(1) /* play loop */
{F(i,0,121)printf(" %c",i&8&&(i+=7)?10:n[b[i]&15]); /* print board */
p=c;W((*p++=getchar())>10); /* read input line */
N=0;
if(*c-10){K=c[0]-16*c[1]+C;L=c[2]-16*c[3]+C;}else /* parse entered move */
D(k,-I,I,Q,1,1,O,8,0); /* or think up one */
F(i,0,U)A[i].K=0; /* clear hash table */
if(D(k,-I,I,Q,1,1,O,9,2)==I)k^=24; /* check legality & do*/
}
}


und hier meine 1. Portierung zu Arduino-C++ (auch ein klein wenig leserlicher, und die Sprungmarken heissen hier ausgeschrieben labelA und labelC):



// Code für Arduino Due


#define K(A,B) *(int*)(T+A+(B&8)+S*(B&7))

#define HTsize (1<<12) // wegen RAM, für PC: (1<<24) // <<<<<< für Arduino Mega verkleinern auf 1<<8 !

struct HTab {
int K,
V;
int X,
Y,
D;
} HTarray[HTsize]; /* hash table, HTsize entries*/


#define MAXNODES 80000 // wegen Zugdauer; für PC: x10 = 800000 = 8e5 // <<<<<< für Mega verkleinern auf 10000!

int K,
Q,
R,
J,
Z;

int32_t N,
I=80000; /* I=80000: "infinity score" */ ;

int
M=136, /* M=0x88 board system */
S=128, /* dummy square 0x80, highest valid square =127 */
turn=16; // 16=Weiss, 8=Schwarz; turn^=24 wechselt hin unnd her

signed char L,
pval[]={0,2,2,7,-1,8,12,23}, /* relative piece values */
vector[]={-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 vector[] per piece*/

bsetup[]={6,3,5,7,4,5,3,6}, /* initial piece setup */
board[129], /* board: half of 16x8+dummy*/
T[1035]; /* hash translation table */

signed char psymbol[]= ".?+nkbrq?*?NKBRQ";

int mfrom, mto; // current ply from - to
int EPSQ, // e.p. square
RemP; // remove piece




/* recursive minimax search, turn=moving side, n=depth*/

int Minimax(int32_t q, int32_t l, int32_t score, int EPC, int prev, int32_t n)
/* (q,l)=window, score, EnPass_sqr.*/
/* prev=prev.dest; J,Z=hashkeys; return score*/
{
int j,
r,
m,
v,
d,
h,
i,
F,
G,
V,
P,
f=J,
g=Z,
C,
s;
signed char t,
p,
upiece,
x,
y,
X,
Y,
H,
B;

struct HTab *a = HTarray + (J + turn * EPC & HTsize-1); /* lookup pos. in hash table*/

char sbuf[50];



q--; /* adj. window: delay bonus */
turn^=24; /* change sides */
d=a->D;
m=a->V;
X=a->X;
Y=a->Y; /* resume at stored depth */

if(a->K-Z|prev| /* miss: other pos. or empty*/
!(m<=q | X&8&&m>=l | X&S)) /* or window incompatible */
{ d=Y=0; } /* start iter. from scratch */

X&=~M; /* start at best-move hint */

while( d++ < n || d<3 /* iterative deepening loop */
|| prev&K == I
&& ( N<60000 & 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 : Minimax(-l,1-l,-score,S,0,d-3); /* Search null move */
m = (-P<l | R>35) ? ( d>2 ? -I : score ) : -P; /* Prune or stand-pat */
N++; /* node count (for timing) */
do
{
upiece=board[x]; /* scan board looking for */
if(upiece & turn) /* own piece (inefficient!)*/
{
r = p = upiece&7; /* p = piece type (set r>0) */
j = vector[p+16]; /* first step vector f.piece*/
while(r = p>2 & r<0 ? -r : -vector[++j] ) /* loop over directions vector[] */
{
labelA: /* resume normal after best */
y=x; /* (x,y)=move */
F=G=S; /* (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= EPC-S&board[EPC]&&y-EPC<2&EPC-y<2?I:m; /* bad castling */

if(p<3&y==EPC)H^=16; /* shift capt.sqr. H if e.p.*/

t=board[H];

if(t&turn|p<3&!(y-x&7)-!t)break; /* capt. own, bad pawn mode */
i=37*pval[t&7]+(t&192); /* value of capt. piece t */
m=i<0?I:m; /* K capture */

if(m>=l&d>1) goto labelC; /* abort on fail high */

v=d-1?score:i-p; /* MVV/LVA scoring */

if(d-!t>1) /* remaining depth */
{
v=p<6?board[x+8]-board[y+8]:0; /* center positional pts. */
board[G]=board[H]=board[x]=0;board[y]=upiece|32; /* do move, set non-virgin */
if(!(G&M))board[F]=turn+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||board[x-2]-upiece)+ /* structure, undefended */
(x+2&M||board[x+2]-upiece)-1 /* squares plus bias */
+(board[x^16]==turn+36)) /* kling to non-virgin King */
-(R>>2); /* end-game Pawn-push bonus */
V=y+r+1&S?647-p:2*(upiece&y+16&32); /* promotion or 6/7th bonus */
board[y]+=V;
i+=V; /* change piece, add score */
}

v+= score+i;
V=m>q ? m : q; /* new eval and alpha */
J+=K(y+0,board[y])-K(x+0,upiece)-K(H+0,t);
Z+=K(y+8,board[y])-K(x+8,upiece)-K(H+8,t)+G -S; /* update hash key */
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?-Minimax(-l,-V,-v, /* recursive eval. of reply */
F,0,C):v; /* or fail low if futile */
} while( s>q & ++C<d );

v=s;
if(prev&&K-I&&v+I&&x==K&y==L) /* move pending & in root: */
{
Q=-score-i; EPSQ=F; /* exit if legal & found */
a->D=99;a->V=0; /* lock game in hash as draw*/
R+=i>>7;
return l; /* captured non-P material */
}
J=f;
Z=g; /* restore hash key */
board[G]=turn+6;
board[F]=board[y]=0;
board[x]=upiece;
board[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 labelA; /* redo after doing old best*/
}
if (
x+r-y|upiece&32| /* not 1st step,moved before*/
p>2 & (
p-4|j-7|| /* no P & no lateral K move,*/
board[G=x+3^r>>1&7]-turn-6 /* no virgin R in corner G, */
|| board[G^1] | board[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*/

}
} // (upiece & turn)

} while((x=x+9&~M)-B); /* next sqr. of board, wrap */

labelC:
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(a->D<99) { /* protect game history */
a->K=Z;
a->V=m;
a->D=d; /* always store in hash tab */
a->X=X|8*(m>q)|S*(m<l);
a->Y=Y; /* move, type (bound/exact),*/
}
/* uncomment for Kibitz */
//if(prev) sprintf(sbuf, "%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));

if(prev && X!=Y) {
sprintf(sbuf, "\n%2d ply, searched: %9d ", d-1, N-S );
Serial.print(sbuf);
}
else
if( ((N-S)%10000)<1) Serial.print(".");


} // while (iterative deepening loop)

turn^=24; /* change sides back */
mfrom=K; mto=L;
return m+= m<score; /* delayed-loss bonus */
}





void chess()
{
int32_t score, i;
int16_t oldto, oldEPSQ;
char sbuf[50], sbuf2[50];
char cstring[20];
signed char oboard[129], spiece;


K=8;
while(K--)
{
board[K]=(board[K+112]=bsetup[K]+8)+8;
board[K+16]=18;
board[K+96]=9; /* initial board setup*/
L=8;
while(L--)board[16*L+K+8]=(K-4)*(K-4)+(L-3.5)*(L-3.5); /* center-pts table */
} /*(in unused half board[])*/
N=1035;
while(N-->M)T[N]=rand()>>9;

/* play loop */
while(1)
{
N=-1;

Serial.print("\n");

sprintf(sbuf," A B C D E F G H \n --------------- \n"); Serial.print(sbuf);
while(++N<121) { /* print board */
if(N&8 && (N+7!=0) ) {sprintf(sbuf,"%3d \n", 1+((120-N)>>4)); Serial.print(sbuf); N+=7; }
else {
if(N%8==0) {sprintf(sbuf, "%3d ", 1+((120-N)>>4)); Serial.print(sbuf); }
sprintf(sbuf," %c", psymbol[board[N]&15]); Serial.print(sbuf);
}
}
sprintf(sbuf," --------------- \n A B C D E F G H "); Serial.print(sbuf);

if(turn==16) sprintf(sbuf,"\n> WHITE: "); else sprintf(sbuf,"\n> BLACK: ");
Serial.print(sbuf);

i = 0;
strcpy(cstring,"");
do {
while (Serial.available()==0);
cstring[i] = Serial.read();
if(cstring[i]==13) {
cstring[i]=0;
break;
}
else i++;
} while(i < 10);

K=I;

if(cstring[0]!=0) { /* parse entered move */
K= cstring[0]-16*cstring[1]+799;
L= cstring[2]-16*cstring[3]+799;
}
/*
Serial.print("\n DEBUG cstring : "); Serial.print(cstring);
sprintf(sbuf,"\n DEBUG K: %d \n DEBUG L: %d \n", K, L);
Serial.print(sbuf);
*/
memcpy(oboard, board, sizeof(board));
oldto=mto;
oldEPSQ=EPSQ;

score=Minimax(-I, I, Q, EPSQ, 1, 3); /* think or check & do*/

if(score!=15) {
RemP=S;
if(oboard[mto]) RemP=mto;
if(mto==oldEPSQ) RemP=oldto;

spiece=psymbol[board[mto]&15];
if(spiece=='*' || spiece=='+') spiece=' ';
sprintf(sbuf,"\n\nmoved: >> %c %c%c", spiece,'a'+(mfrom&7),'8'-(mfrom>>4) );

if(oboard[mto]) strcat(sbuf," X ");
else strcat(sbuf,"-");

sprintf(sbuf2,"%c%c ", 'a'+(mto&7),'8'-(mto>>4&7));
strcat(sbuf, sbuf2);
Serial.print(sbuf);

sprintf(sbuf, " \nDEBUG: %d to %d \n", mfrom, mto);
Serial.print(sbuf);
sprintf(sbuf," EPsq: %c%c (%3d)\n",
'a'+(EPSQ&7), '8'-(EPSQ>>4&7), EPSQ); Serial.print(sbuf);
sprintf(sbuf," RemP: %c%c (%3d)\n\n",
'a'+(RemP&7), '8'-(RemP>>4&7), RemP); Serial.print(sbuf);
}
else printf("\n\nILLEGAL!\n");

}
}




void setup() {
Serial.begin(9600);
}



void loop() {
chess();

while(1);
}


------------------

PS:
aber ganz abgesehen von der Lösbarkeit:
goto ist und bleibt legaler C code, es gibt keinen Grund, ihn zu zu verteufeln oder grundsätzlich stattdessen if/else if oder case/switch oder verschachtelte for/while/break/continue vorzuziehen. Auch case/switch/break ist übrigens nichts anderes als ein verkapptes goto (denn die "case" Fälle sind in Wirklichkeit für den Compiler Konstanten, die als goto-Sprungmarken benutzt werden, nichts anderes).
Er ist "riskanter", ok, aber C ist grundsätzlich riskant, weil C nunmal - gottseidank - alles erlaubt, was riskant ist, schon angefangen mit Schreiben von Werten an Pointer Adressen und deren Referenzen, wodurch man schnell im Nirwana landen kann.
In C entscheidet aber eben einzig der Programmierer, was erlaubt ist oder sein soll, nicht die Programmiersprache oder der Compiler, notfalls kann man es sogar per Compiler Flags erzwingen (-fpermissive etc):
und das finde ich absolut gut so, und daher ziehe ich auch nicht grundsätzlich irgend was anderes dem goto generell vor, sondern entscheide nach Praktikabilität und notfalls Bequemlichkeit. Wer die Fallstricke kennt, kann sie auch vermeiden, wer nicht, muss halt aufpassen. Nachfragen in Foren helfen einem dann aber wiederum schnell bei der persönlichen Lernkurve 8)