Wie Folge-FEN-String aus aktuellem Zug und FEN-String am einfachsten berechnen?

Habt ihr eine Idee, wie man das machen könnte?

Aktuell hapert es an Folgendem:

  • Rochade
  • en-passant
  • Figuren-Umwandlung
  • 50-Züge-Regelung

Beispiel kurze Rochade weiß, und anschließend kurze Rochade schwarz:

m = bestmove e2e4 ponder e7e5
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
[  8,  9, 10, 11, 12, 10,  9,  8]
[  7,  7,  7,  7,  7,  7,  7,  7]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  1,  1,  1,  1,  1,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  3,  2]

m = bestmove c7c5 ponder g1f3
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR
[  8,  9, 10, 11, 12, 10,  9,  8]
[  7,  7,  7,  7,  7,  7,  7,  7]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  1,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  1,  1,  1,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  3,  2]

m = bestmove g1f3 ponder e7e6
rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b
rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR
[  8,  9, 10, 11, 12, 10,  9,  8]
[  7,  7,  0,  7,  7,  7,  7,  7]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  7,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  1,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  1,  1,  1,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  3,  2]

m = bestmove e7e6 ponder b1c3
rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R w
rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  9,  8]
[  7,  7,  0,  7,  7,  7,  7,  7]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  7,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  1,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  1,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove c2c3 ponder d7d5
rnbqkbnr/pp1p1ppp/4p3/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b
rnbqkbnr/pp1p1ppp/4p3/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  9,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  0,  0,  0]
[  0,  0,  7,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  1,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  1,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove g8f6 ponder e4e5
rnbqkbnr/pp1p1ppp/4p3/2p5/4P3/2P2N2/PP1P1PPP/RNBQKB1R w
rnbqkbnr/pp1p1ppp/4p3/2p5/4P3/2P2N2/PP1P1PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  9,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  0,  0,  0]
[  0,  0,  7,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  1,  0,  0,  0]
[  0,  0,  1,  0,  0,  3,  0,  0]
[  1,  1,  0,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove e4e5 ponder f6d5
rnbqkb1r/pp1p1ppp/4pn2/2p5/4P3/2P2N2/PP1P1PPP/RNBQKB1R b
rnbqkb1r/pp1p1ppp/4pn2/2p5/4P3/2P2N2/PP1P1PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  9,  0,  0]
[  0,  0,  7,  0,  0,  0,  0,  0]
[  0,  0,  0,  0,  1,  0,  0,  0]
[  0,  0,  1,  0,  0,  3,  0,  0]
[  1,  1,  0,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove f6d5 ponder d2d4
rnbqkb1r/pp1p1ppp/4pn2/2p1P3/8/2P2N2/PP1P1PPP/RNBQKB1R w
rnbqkb1r/pp1p1ppp/4pn2/2p1P3/8/2P2N2/PP1P1PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  9,  0,  0]
[  0,  0,  7,  0,  1,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  1,  0,  0,  3,  0,  0]
[  1,  1,  0,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove d2d4 ponder c5d4
rnbqkb1r/pp1p1ppp/4p3/2pnP3/8/2P2N2/PP1P1PPP/RNBQKB1R b
rnbqkb1r/pp1p1ppp/4p3/2pnP3/8/2P2N2/PP1P1PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  0,  0,  0]
[  0,  0,  7,  9,  1,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0,  0]
[  0,  0,  1,  0,  0,  3,  0,  0]
[  1,  1,  0,  1,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove c5d4 ponder c3d4
rnbqkb1r/pp1p1ppp/4p3/2pnP3/3P4/2P2N2/PP3PPP/RNBQKB1R w
rnbqkb1r/pp1p1ppp/4p3/2pnP3/3P4/2P2N2/PP3PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  0,  0,  0]
[  0,  0,  7,  9,  1,  0,  0,  0]
[  0,  0,  0,  1,  0,  0,  0,  0]
[  0,  0,  1,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove c3d4 ponder d7d6
rnbqkb1r/pp1p1ppp/4p3/3nP3/3p4/2P2N2/PP3PPP/RNBQKB1R b
rnbqkb1r/pp1p1ppp/4p3/3nP3/3p4/2P2N2/PP3PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  0,  7,  0,  0,  0,  0]
[  0,  0,  1,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove d7d6 ponder f1c4
rnbqkb1r/pp1p1ppp/4p3/3nP3/3P4/5N2/PP3PPP/RNBQKB1R w
rnbqkb1r/pp1p1ppp/4p3/3nP3/3P4/5N2/PP3PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  7,  0,  7,  7,  7]
[  0,  0,  0,  0,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  0,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove f1c4 ponder f8e7
rnbqkb1r/pp3ppp/3pp3/3nP3/3P4/5N2/PP3PPP/RNBQKB1R b
rnbqkb1r/pp3ppp/3pp3/3nP3/3P4/5N2/PP3PPP/RNBQKB1R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  0,  0,  7,  7,  7]
[  0,  0,  0,  7,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  0,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  4,  0,  2]

m = bestmove b8c6 ponder e1g1
rnbqkb1r/pp3ppp/3pp3/3nP3/2BP4/5N2/PP3PPP/RNBQK2R w
rnbqkb1r/pp3ppp/3pp3/3nP3/2BP4/5N2/PP3PPP/RNBQK2R
[  8,  9, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  0,  0,  7,  7,  7]
[  0,  0,  0,  7,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  4,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  0,  0,  2]

m = bestmove d1e2 ponder d6e5
r1bqkb1r/pp3ppp/2npp3/3nP3/2BP4/5N2/PP3PPP/RNBQK2R b
r1bqkb1r/pp3ppp/2npp3/3nP3/2BP4/5N2/PP3PPP/RNBQK2R
[  8,  0, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  0,  0,  7,  7,  7]
[  0,  0,  9,  7,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  4,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  0,  1,  1,  1]
[  2,  3,  4,  5,  6,  0,  0,  2]

m = bestmove f8e7 ponder e1g1
r1bqkb1r/pp3ppp/2npp3/3nP3/2BP4/5N2/PP2QPPP/RNB1K2R w
r1bqkb1r/pp3ppp/2npp3/3nP3/2BP4/5N2/PP2QPPP/RNB1K2R
[  8,  0, 10, 11, 12, 10,  0,  8]
[  7,  7,  0,  0,  0,  7,  7,  7]
[  0,  0,  9,  7,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  4,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  5,  1,  1,  1]
[  2,  3,  4,  0,  6,  0,  0,  2]

m = bestmove e1g1 ponder d6e5
r1bqk2r/pp2bppp/2npp3/3nP3/2BP4/5N2/PP2QPPP/RNB1K2R b
r1bqk2r/pp2bppp/2npp3/3nP3/2BP4/5N2/PP2QPPP/RNB1K2R
[  8,  0, 10, 11, 12,  0,  0,  8]
[  7,  7,  0,  0, 10,  7,  7,  7]
[  0,  0,  9,  7,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  4,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  5,  1,  1,  1]
[  2,  3,  4,  0,  6,  0,  0,  2]

m = bestmove e8g8 ponder f1d1
r1bqk2r/pp2bppp/2npp3/3nP3/2BP4/5N2/PP2QPPP/RNB3KR w
r1bqk2r/pp2bppp/2npp3/3nP3/2BP4/5N2/PP2QPPP/RNB2RK1
[  8,  0, 10, 11, 12,  0,  0,  8]
[  7,  7,  0,  0, 10,  7,  7,  7]
[  0,  0,  9,  7,  7,  0,  0,  0]
[  0,  0,  0,  9,  1,  0,  0,  0]
[  0,  0,  4,  1,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  3,  0,  0]
[  1,  1,  0,  0,  5,  1,  1,  1]
[  2,  3,  4,  0,  0,  0,  6,  2]
  1. berechneter bester Zug
  2. berechneter FEN-String
  3. richtiger FEN-String
  4. berechnete interne Darstellung

Was sind denn deine konkreten Fragen?

Die Regeln für die vier genannten Züge sollten doch klar sein (ansonsten mal irgendeine Schacheinführung konsultieren, Wikipedia dürfte dafür auch reichen).

Für Rochade, en-passant und 50-Züge-Regelung muss man die vollständige FEN nutzen, deine verkürzte Form lässt das dafür notwendige (mögliche Rochaden, mögliches en-Passant und Anzahl Züge) leider weg. Umwandlung ist trivial, wenn ein Bauer am Ende angekommen ist, wird der gegen das gewünschte getauscht.

Es geht speziell um die Funktion move():

public static int[][] fenToIntA(String fen) {
	int[][] d = new int[8][8];

	String[] a = fen.split("/");
	for (int i = 0; i < 8; i++) {
		char[] b = a[i].toCharArray();
		int index = 0;
		for (int j = 0; index < 8; j++) {
			char c = b[j];
			if (Character.isDigit(c)) {
				index += c - '0';
			} else {
				if (Character.isUpperCase(c)) {
					c = Character.toLowerCase(c);
					switch (c) {
					case 'p':
						d[i][index++] = 1;
						break;
					case 'r':
						d[i][index++] = 2;
						break;
					case 'n':
						d[i][index++] = 3;
						break;
					case 'b':
						d[i][index++] = 4;
						break;
					case 'q':
						d[i][index++] = 5;
						break;
					case 'k':
						d[i][index++] = 6;
						break;

					default:
						break;
					}
				} else {
					switch (c) {
					case 'p':
						d[i][index++] = 7;
						break;
					case 'r':
						d[i][index++] = 8;
						break;
					case 'n':
						d[i][index++] = 9;
						break;
					case 'b':
						d[i][index++] = 10;
						break;
					case 'q':
						d[i][index++] = 11;
						break;
					case 'k':
						d[i][index++] = 12;
						break;

					default:
						break;
					}
				}
			}
		}
	}

	return d;
}

public static void move(int[][] inta, String move) {
	inta[8 - move.charAt(3) + '0'][move.charAt(2) - 'a'] = inta[8 - move.charAt(1) + '0'][move.charAt(0) - 'a'];
	inta[8 - move.charAt(1) + '0'][move.charAt(0) - 'a'] = 0;
}

public static String intAToFen(int[][] inta, char color) {
	StringBuilder b = new StringBuilder();

	for (int i = 0; i < inta.length; i++) {
		int index = 0;
		for (int j = 0; j < inta[i].length; j++) {
			if (inta[i][j] == 0) {
				index++;
			} else {
				if (index != 0) {
					b.append(index);
					index = 0;
				}
				switch (inta[i][j]) {
				case 1:
					b.append('P');
					break;
				case 2:
					b.append('R');
					break;
				case 3:
					b.append('N');
					break;
				case 4:
					b.append('B');
					break;
				case 5:
					b.append('Q');
					break;
				case 6:
					b.append('K');
					break;
				case 7:
					b.append('p');
					break;
				case 8:
					b.append('r');
					break;
				case 9:
					b.append('n');
					break;
				case 10:
					b.append('b');
					break;
				case 11:
					b.append('q');
					break;
				case 12:
					b.append('k');
					break;

				default:
					break;
				}
			}
		}
		if (index != 0) {
			b.append(index);
		}
		b.append("/");
	}
	b.replace(b.length() - 1, b.length(), " ");
	b.append(color);

	return b.toString();
}

Sorry für die verrückten Einrückungen…

Falls euch ein Refactoring einfällt, her damit! (Sonst würd ich die Frage auch noch mal auf codereview stackexchange stellen…)

Die Funktion, die quasi noch gar nicht existiert? Du wirst doch wohl irgendeinen Ansatz dafür haben?

Mindestens die Magic Numbers loswerden, ein paar Dinge in Methoden auslagern schadet auch nicht, generell mal über einen Objektorientierten Ansatz nachdenken kann auch sinnvoll sein…

Diesen habe ich geschrieben.

Das ist vielleicht nur meine Meinung, aber dieser Kommentar ist 0 zielführend.

Ist dir klar, dass dein „Code“ ausschaut wie welcher den man durch einen uglyfier durchrennen gelassen hat? Der einzige unterschied dazwischen sind nur noch die leerzeichen und das ab und an tatsächlich mal was Wortähnliches vorkommt.

Du hast jetzt also genau EINE CHANCE dein Thema vor mir zu retten. Um Hilfe erwarten zu dürfen, sollte man entsprechende vorarbeit geleistet haben. Und d.h. vernünftigen Code hier posten.

Sollte das nicht passieren - oder solltest du weiterhin so pampig:

sein, dann mach ich hier ohne weiteren Kommentar dicht!

Ganz spontan ist das erste was fehlt die richtige interne Darstellung, damit man mal vergleichen kann.

Naja, ein FEN-String beschreibt eine Ausgangssituation beim Schach eindeutig. fenToIntA() erhält einen FEN-String (zum Beispiel die Startposition) und gibt eine interne Darstellung zurück. intAToFen() geht dabei umgekehrt vor, und berechnet auch einer internen Darstellung einen FEN-String. move() soll eine interne Darstellung manipulieren können. Das Problem wäre, dass sich bei einer Rochade vier Felder ändern, bei en-passant drei und eine Figuren-Umwandlung anders als ein normaler Zug ist.

Genau, und eine richtige interne Darstellung weiß ich nicht genau…

Um auf dem Niveau deines Codes zu bleiben: ein riesiges switch-if-else-Konstrukt, in dem du alle möglichen Fälle einzeln behandelst.

Für die Darstellung eines Spiels, bei dem Figuren, die zu einer bestimmten Farbe gehören und einen bestimmten Typ haben, über ein Schachfeld bewegt werden, könnte man zB genau die irgendwie sinnvoll abbilden (und Nein, ein int ist nicht sinnvoll…)

1 „Gefällt mir“

Mmmm, hab einen Workaround dafür, und dieser lautet so: Ich muss den Folge-FEN gar nicht aus dem aktuellen Zug berechnen… Sorry für das Thema, aber falls ihr dennoch eine Idee habt, gerne her damit.

@mrBrown : Eine interne Darstellung mit so vielen Objekten wäre hierbei zu langsam.

Workaround für was?

FEN ist einfach nur eine Darstellung des Zustands, und aktueller Zustand+Zug ergibt den Folge-Zustand, genauso wie der Folge-Zustand nur aus aktuellem Zustand und Zug herleitbar ist. Schach, ohne Zug oder Folge-Zustand, hat nicht mehr viel mit Schach zu tun…

Naja, lieber langsam als nicht funktionierend :slight_smile:

Iwie müßig mit mrBrown zu diskutieren.

… besser weder noch.

@mrBrown nett das du es versuchst aber mein Rat: Gib es auf. CB ist lernresistent. Sein „Code“ war schon immer fern ab jeglicher Qualität und wird es auch immer sein. Und hier hat er es Mal wieder im Paradebeispiel gezeigt. Fadenscheinige Ausreden warum er kein OOP verwenden möchte.

Da anscheinend ein „workaround“ gefunden wurde ist das Thema ja eigentlich gelöst. Normerweise würde ich nochmal darauf bestehen, dass auch zu Posten. Aber bei dem Code wäre es anderen eh keine Hilfe und darum können wir auf die „Lösung“ hier auch ausnahmsweise Mal verzichten.

Zum anderen mach ich hier dicht, weil ich nicht will das CB weiterhin die Hilfsbereitschaft ausnutzt.

2 „Gefällt mir“