Created
April 22, 2021 22:16
-
-
Save ToJans/50c160690d206dfb42d143e6132e7cd2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
/** | |
Chess: potential moves etc by @ToJans | |
Spiked in a couple of hours of late-night code for a tweet by @gregyoung | |
https://twitter.com/gregyoung/status/1385285718113722374 | |
** unfinished & untested, most likely contains bugs ** | |
**/ | |
public class Vector { | |
public int X, Y; | |
public Vector(int x=0, int y=0) { | |
this.X = x; | |
this.Y = y; | |
} | |
public Vector Clone() { | |
return new Vector{ X = this.X , Y = this.Y}; | |
} | |
public Vector[] In4Quadrants() { | |
return new Vector[]{this,new Vector(this.X,-this.Y), new Vector(-this.X,-this.Y), new Vector(-this.X,this.Y)}; | |
} | |
public static Vector operator +(Vector left, Vector right) { return Apply(left,right,(l,r)=> l+r);} | |
public static Vector operator -(Vector left, Vector right) { return Apply(left,right,(l,r)=> l-r);} | |
private static Vector Apply(Vector left, Vector right, Func<int,int,int> fn) { | |
return new Vector(fn(left.X,right.X), fn(left.Y, right.Y)); | |
} | |
public static Vector Up = new Vector(-1,0); | |
public static Vector Down = new Vector(1,0); | |
public static Vector Left = new Vector(0,-1); | |
public static Vector Right = new Vector(1,0); | |
public static Vector UpLeft = Up+Left; | |
public static Vector UpRight = Up+Right; | |
public static Vector DownLeft = Up+Left; | |
public static Vector DownRight = Up+Right; | |
public static Vector[] Cartesian = Up.In4Quadrants(); | |
public static Vector[] Diagonal = UpLeft.In4Quadrants(); | |
public static Vector[] AllDirections = Cartesian.Concat(Diagonal).ToArray(); | |
} | |
public class ChessPosition:Vector { | |
public ChessPosition(int row = -1, int column = -1):base(row,column) {} | |
public bool IsOutOfBounds { get { return this.X<0 || this.X> 7 || this.Y < 0 | this.Y > 7; } } | |
public static ChessPosition operator +(ChessPosition left, Vector right) { return Apply(left,right,(l,r)=> l+r);} | |
public static ChessPosition operator -(ChessPosition left, Vector right) { return Apply(left,right,(l,r)=> l-r);} | |
private static ChessPosition Apply(ChessPosition left, Vector right, Func<int,int,int> fn) { | |
if (left.IsOutOfBounds) return left; | |
return new ChessPosition(fn(left.X,right.X), fn(left.Y, right.Y)); | |
} | |
public IEnumerable<ChessPosition> ValidMovesInDirection(Vector direction) { | |
var current = this+direction; | |
while (!current.IsOutOfBounds) { | |
yield return current; | |
current+=direction; | |
} | |
} | |
public IEnumerable<IEnumerable<ChessPosition>> ValidMovesInMultipleDirections(IEnumerable<Vector> directions) { | |
return directions.Select(dir=>this.ValidMovesInDirection(dir)); | |
} | |
} | |
enum Piece : byte { | |
Empty=0, | |
Pawn=1, | |
Tower=2, | |
Knight=3, | |
Bishop=4, | |
King=5, | |
Queen=6, | |
Black=8 | |
} | |
class Move { | |
public ChessPosition From, To; | |
} | |
static class IEnumerableExtensions { | |
public static IEnumerable<T> TakeWhileInclusive<T>(this IEnumerable<T> items, Predicate<T> predicate) { | |
foreach(T item in items) | |
{ | |
if(predicate(item)) | |
{ | |
yield return item; | |
} | |
else | |
{ | |
yield return item; | |
yield break; | |
} | |
} | |
} | |
} | |
class Board { | |
Piece[,] board; | |
Board(Piece[,] board) { | |
this.board = board; | |
} | |
static Board Setup() { | |
var board = new Piece[8,8]; | |
for (int y=0;y<8;y++) { | |
for (int x=0;x<8;x++) { | |
board[x,y] = y>5?Piece.Black:Piece.Empty; | |
switch (y) { | |
case 1: case 6: board[x,y] |= Piece.Pawn; break; | |
case 0: case 7: | |
switch (x) { | |
case 0: case 7: board[x,y] |= Piece.Tower; break; | |
case 1: case 6: board[x,y] |= Piece.Knight; break; | |
case 2: case 5: board[x,y] |= Piece.Bishop; break; | |
case 3: board[x,y] |= Piece.King; break; | |
case 4: board[x,y] |= Piece.Queen; break; | |
} | |
break; | |
default: | |
board[x,y] = Piece.Empty; | |
break; | |
} | |
} | |
} | |
return new Board(board); | |
} | |
public Piece this[ChessPosition position] { | |
get { | |
return position.IsOutOfBounds ? Piece.Empty:this.board[position.X,position.Y]; | |
} | |
set { | |
if (!position.IsOutOfBounds) { | |
this.board[position.X,position.Y] = value; | |
} | |
} | |
} | |
IEnumerable<ChessPosition> PotentialMoves(ChessPosition position) { | |
var piece = this[position]; | |
var positions = new List<ChessPosition>(); | |
switch(piece) { | |
case Piece.Tower: | |
positions.AddRange(position | |
.ValidMovesInMultipleDirections(Vector.Cartesian) | |
.SelectMany(x=>x.TakeWhileInclusive(p=>this[p] == Piece.Empty))); | |
break; | |
case Piece.Bishop: | |
positions.AddRange(position | |
.ValidMovesInMultipleDirections(Vector.Diagonal) | |
.SelectMany(x=>x.TakeWhileInclusive(p=>this[p] == Piece.Empty))); | |
break; | |
case Piece.Queen: | |
positions.AddRange(position | |
.ValidMovesInMultipleDirections(Vector.AllDirections) | |
.SelectMany(x=>x.TakeWhileInclusive(p=>this[p] == Piece.Empty))); | |
break; | |
case Piece.Knight: | |
positions.AddRange(new Vector(3,2).In4Quadrants().Concat(new Vector(2,3).In4Quadrants()) | |
.Select(v=>position + v).Where(p=>!p.IsOutOfBounds)); | |
break; | |
case Piece.King: | |
positions.AddRange(Vector.AllDirections.Select(v=>position + v).Where(p=>!p.IsOutOfBounds)); | |
// TODO: rochade? | |
break; | |
case Piece.Pawn: | |
case Piece.Pawn|Piece.Black: | |
var forward = (piece & Piece.Black) == Piece.Black ? Vector.Up:Vector.Down; | |
// TODO: pawn movement: opening, striking pieces etc | |
break; | |
} | |
// TODO: filter out moves that result in check | |
return positions; | |
} | |
} | |
public class Program | |
{ | |
public static void Main() | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment