Explosions on a chessboard
JavaScript (ES6) 305 310 321
As a function with 2 real parameters (and a lot more with default values, used as a quick and dirty way to define locals)
Test running the snippet below (being EcmaScript 6, Firefox only)
F=(g,m,b=[...g.replace(/\d/g,c=>'0'.repeat(c))],P=p=>p=='p'|p=='P',n=parseInt(m,32),
s=n>>5&31,u=n>>15,x=b[y=u+62-(n>>10&31)*9])=>(
b[b[y]=0,z=s+62-(n&31)*9]<1&!(s!=u&P(x))?b[z]=x:
[-1,1,8,9,10,-8,-9,-10].map(i=>b[i+=z]>'/'&&!P(b[i])?b[i]=0:0,b[b[z]<1?z>y?z-9:z+9:z]=0),
b.join('').replace(/0+/g,x=>x.length)
)
//TEST
out=x=>O.innerHTML+=x+'\n'
test=[
['rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR', 'g1f3'
,'rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R']
,['3kBb1r/pp5p/3p4/4pn2/P7/1P2P1pP/2rP1P2/R1B3RK', 'f2g3'
,'3kBb1r/pp5p/3p4/4pn2/P7/1P2P2P/2rP4/R1B3RK']
,['rnbqk1nr/1pp5/p2pp1pp/5p2/1bN5/2P1PQ1N/PP1P1PPP/R1B1KB1R', 'f3b7'
,'3qk1nr/2p5/p2pp1pp/5p2/1bN5/2P1P2N/PP1P1PPP/R1B1KB1R']
,['rnbqk2r/pp2p2p/2p3pb/3pP3/5P2/2N5/PPPP2P1/R1BQKB1R', 'e5d6'
,'rnbqk2r/pp2p2p/2p3pb/8/5P2/2N5/PPPP2P1/R1BQKB1R']
,['5r2/2k5/p1B5/1pP1p3/1P4P1/3P4/P7/1K3R1q', 'c6h1'
,'5r2/2k5/p7/1pP1p3/1P4P1/3P4/P7/1K3R2']
]
test.forEach(t=>(
r=F(t[0],t[1]),
out('Test '+(r==t[2]?'Ok':'Fail!')+' '+t[0]+' move '+t[1]
+'\nResult '+r+'\nExpected '+t[2]+'\n')))
<pre id=O></pre>
Ungolfed
B=(b,m)=>{
P=p=>p=='p'|p=='P'
m=parseInt(m,32)
r=m&31 // arrival row
s=(m/32&31)-10 // arrival column
z=s+(8-r)*9 // arrival position
t=m/32/32&31 // start row
u=(m/32/32/32&31)-10 // start column
y=u+(8-t)*9 // start position
b=[...b.replace(/\d/g,c=>'0'.repeat(c))] // board to array, empty squares as 0
x=b[y] // moving piece
b[y]=0
C=s!=u&P(x) // pawn capture
if (b[z]<1 && !C)
{ // no capture
b[z]=x
}
else
{
// capture and boom!
if (b[z]<1) // arrival empty: en passant
b[z>y?z-9:z+9]=0;
else
b[z]=0;
// zero to nearest 8 squares
[-1,1,8,9,10,-8,-9,-10].forEach(i=>b[i+=z]>'/'&&!P(b[i])?b[i]=0:0)
}
return b.join('').replace(/0+/g,x=>x.length)
}
APL (Dyalog Extended), 240 bytes
e←' '@(p/⍨~(x←∊∘'Pp')(b←↑⊃¨,/¨{⍵∊⎕D:' '/⍨⍎⍵⋄⍵}¨¨'/'(≠⊆⊢)⎕)[p←p/⍨{∧/⍵∊⍳8}¨p←(⊃⌽c←{(9-⍎⊃⌽⍵),⎕A⍳⊃⍵}¨↓2 2⍴1⎕C⎕)∘+¨,∘.,⍨2-⍳3])
1↓⊃,/{'/',⊃,/{' '∊⍵:⍕≢⍵⋄⍵}¨⍵⊂⍨1,2≠/⍵}¨↓{(x⊃n)∧(≠/⊃¨⌽¨c)∧' '=⊃⌽n←b[c]:e' '@((⊃c)+0,1↓⊃-⍨/c)⊢b⋄' '∊n:(⌽n)@c⊢b⋄e' '@c⊢b}0
Try it online!
A full program which takes the FEN first, and the move second.
Explanation
First Line: Explode. Function
e←' '@(p/⍨~(x←∊∘'Pp')(b←↑⊃¨,/¨{⍵∊⎕D:' '/⍨⍎⍵⋄⍵}¨¨'/'(≠⊆⊢)⎕)[p←p/⍨{∧/⍵∊⍳8}¨p←(⊃⌽c←{(9-⍎⊃⌽⍵),⎕A⍳⊃⍵}¨↓2 2⍴1⎕C⎕)∘+¨,∘.,⍨2-⍳3])
1⎕C⎕
capitalize the first input
↓2 2⍴
cut into halves
{(9-⍎⊃⌽⍵),⎕A⍳⊃⍵}¨
apply the following to each square name:
,⎕A⍳⊃⍵
get position of first char in the alphabet(column)
(9-⍎⊃⌽⍵)
get 9-int(second char) (row number)
c←
store that in c
⊃⌽
take the last element
∘+¨
and add that to:
,∘.,⍨2-⍳3
the cartesian product of (-1,0,1), getting the von neumann neighborhood
p←
assign the explosion indices to p
p←p/⍨{∧/⍵∊⍳8}¨
remove the ones outside the board, and reassign to p
(...)[...]
and index into the following:
'/'(≠⊆⊢)⎕
split the second input on slashes
⊃¨,/¨{⍵∊⎕D:' '/⍨⍎⍵⋄⍵}¨¨
convert each digit to the appropriate amount of spaces
b←↑
and convert it to a matrix, storing in b. This is the chess board.
x←∊∘'Pp'
store function to check for pawns in x
p/⍨~(x←∊∘'Pp')
now, remove the points which map to pawns
' '@
and insert a space at those indices in the right argument.
Second line: capture calculator
1↓⊃,/{'/',⊃,/{' '∊⍵:⍕≢⍵⋄⍵}¨⍵⊂⍨1,2≠/⍵}¨↓{(x⊃n)∧(≠/⊃¨⌽¨c)∧' '=⊃⌽n←b[c]:e' '@((⊃c)+0,1↓⊃-⍨/c)⊢b⋄' '∊n:(⌽n)@c⊢b⋄e' '@c⊢b}0
n←b[c]
assign the starting and ending characters to n
' '=⊃⌽n←b[c]
If ending square is empty,
(≠/⊃¨⌽¨c)∧
start column and end column are not equal,
(x⊃n)∧
and capturing piece is a pawn(en passant):
0,1↓⊃-⍨/c
get the direction of capture
(⊃c)+
add that to the start index
' '@((⊃c)+0,1↓⊃-⍨/c)⊢b
insert a space at that point
e
and explode.
' '∊n
else, if ending point is a space(no capture):
(⌽n)@c⊢b⋄
switch the places of the space and the piece
' '@c⊢b
Otherwise, insert a space at the start and end index(normal capture)
e
and explode.
¨↓
then, take each row,
⍵⊂⍨1,2≠/⍵
group it into equal runs
{' '∊⍵:⍕≢⍵⋄⍵}¨
replace runs of spaces with their length.
'/',⊃,/
join everything together and prepend a /
1↓⊃,/
join the rows together and drop the first /.
Java, (946 777 776 chars)
1 char thanks to @edc65
Note: Chars counted without test cases put in.
Code
class E{public static void main(String[]a){String i=a[0];char[]n=a[1].toCharArray();int j,k,z,w,y,u=56-n[3];char q,p,e ='e';char[][]b=new char[8][8];String[]r=i.split("/");for(j=0;j<8;j++){z=0;for(k=0;k<r[j].length();k++){p=r[j].charAt(k);if(Character.isDigit(p)){for(int l=k+z;l<k+z+p-48;l++)b[j][l]=e;z+=p-49;}else b[j][k+z]=p;}}z=n[0]-97;w=56-n[1];y=n[2]-97;p=b[w][z];q=b[u][y];b[w][z]=e;if(q!=e||((p|32)=='p'&&(w-u<0?u-w:w-u)==1&&(z-y<0?y-z:z-y)==1)){if(q!=e)b[u][y]=e;else b[w][y]=e;for(j=y-(y==0?0:1);j<y+(y==8?0:y==7?1:2);j++){for(k=u-(u==0?0:1);k<u+(u==8?0:u==7?1:2);k++)if((b[k][j]|32)!='p')b[k][j]=e;}}else b[u][y]=p;i="";for(j=0;j<8;j++){z=0;for(k=0;k<8;k++){if(b[j][k]==e)z++;else {if(z>0){i+=z;z=0;}i+=b[j][k];}}if(z>0)i+=z;i+=j!=7?"/":"";}System.out.print(i);}}
I'm not sure if this solution is optimal, but I'm working on golfing it more, any suggestions are welcome. I can comment all the code too if anyone would like, but I think it's mostly self explanatory, except for the confusing variable enumeration.
Explanation
- Unpack the board string into a char matrix
- Calculate the effect of the move
- Repack the board into a string
Expanded
class ExplosionChess{
public static void main(String[]a){
String i=a[0];
//"rnbqk1nr/1pp5/p2pp1pp/5p2/1bN5/2P1PQ1N/PP1P1PPP/R1B1KB1R";
//"f3b7";
char[]n=a[1].toCharArray();
int j,k,z,w,y,u=56-n[3];
char q,p,e ='e';
char[][]b=new char[8][8];
String[]r=i.split("/");
for(j=0;j<8;j++){
z=0;
for(k=0;k<r[j].length();k++){
p=r[j].charAt(k);
if(Character.isDigit(p)){
for(int l=k+z;l<k+z+p-48;l++)
b[j][l]=e;
z+=p-49;
}else
b[j][k+z]=p;
}
}
z=n[0]-97;
w=56-n[1];
y=n[2]-97;
p=b[w][z];
q=b[u][y];
b[w][z]=e;
if(q!=e||((p|32)=='p'&&(w-u<0?u-w:w-u)==1&&(z-y<0?y-z:z-y)==1)){
if(q!=e)
b[u][y]=e;
else
b[w][y]=e;
for(j=y-(y==0?0:1);j<y+(y==8?0:y==7?1:2);j++){
for(k=u-(u==0?0:1);k<u+(u==8?0:u==7?1:2);k++)
if((b[k][j]|32)!='p')
b[k][j]=e;
}
}else
b[u][y]=p;
i="";
for(j=0;j<8;j++){
z=0;
for(k=0;k<8;k++){
if(b[j][k]==e)
z++;
else {
if(z>0){
i+=z;
z=0;
}
i+=b[j][k];
}
}
if(z>0)
i+=z;
i+=j!=7?"/":"";
}
System.out.print(i);
}
}
Old
class E{public static void main(String[]a){String m,i="rnbqk1nr/1pp5/p2pp1pp/5p2/1bN5/2P1PQ1N/PP1P1PPP/R1B1KB1R";m="f3b7";char[]n=m.toCharArray();int z,w,y,u=56-n[3];z=n[0]-97;w=56-n[1];y=n[2]-97;char e='e';char[][]b=new char[8][8];String[]r=i.split("/");for(int j=0;j<8;j++){int o=0;for(int k=0;k<r[j].length();k++){char q=r[j].charAt(k);if(Character.isDigit(q)){for(int l=k+o;l<k+o+q-48;l++){b[j][l]=e;}o+=q-49;}else b[j][k+o]=q;}}char q,p=b[w][z];q=b[u][y];b[w][z]=e;if(q==e){if((p|32)=='p'&&(w-u<0?u-w:w-u)==1&&(z-y<0?y-z:z-y)==1){b[w][y]=e;for(int j=y-(y==0?0:1);j<y+(y==8?0:y==7?1:2);j++){for(int k=u-(u==0?0:1);k<u+(u==8?0:u==7?1:2);k++){if((b[k][j]|32)!='p')b[k][j]=e;}}}else{b[u][y]=p;}}else{b[u][y]=e;for(int j=y-(y==0?0:1);j<y+(y==8?0:y==7?1:2);j++){for(int k=u-(u==0?0:1);k<u+(u==8?0:u==7?1:2);k++){if((b[k][j]|32)!='p')b[k][j]=e;}}}i="";for(int j=0;j<8;j++){int x=0;for(int k=0;k<8;k++){if(b[j][k]==e)x++;else{if(x>0){i+=x;x=0;}i+=b[j][k];}}if(x>0)i+=x;i+=j!=7?"/":"";}System.out.println(i);}}