mirror of
https://github.com/fleschutz/PowerShell.git
synced 2024-11-21 15:33:15 +01:00
1233 lines
47 KiB
PowerShell
1233 lines
47 KiB
PowerShell
|
<#
|
|||
|
.SYNOPSIS
|
|||
|
Local multiplayer chess game in PowerShell.
|
|||
|
|
|||
|
.DESCRIPTION
|
|||
|
Started off of code from https://github.com/bhassen99/POSH-Chess, which was very
|
|||
|
much incomplete. I kept the board shape, but have changed everything else.
|
|||
|
The unicode chess pieces unfortunately do not render in the base PowerShell console,
|
|||
|
they only appear when run in PowerShell ISE.
|
|||
|
|
|||
|
.NOTES
|
|||
|
Name: Chess.ps1
|
|||
|
Version: 0.3.1
|
|||
|
Author: Michael Shen
|
|||
|
Date: 10-19-2017
|
|||
|
#>
|
|||
|
|
|||
|
#Update-Board must be run before Publish-Board
|
|||
|
#Draws the board to the screen and displays all the icons
|
|||
|
Function Publish-Board {
|
|||
|
Clear
|
|||
|
Write-Host "`n`n"
|
|||
|
Write-Host ' A B C D E F G H'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 8 |'$board[0,7].Icon'|'$board[1,7].Icon'|'$board[2,7].Icon'|'$board[3,7].Icon'|'$board[4,7].Icon'|'$board[5,7].Icon'|'$board[6,7].Icon'|'$board[7,7].Icon'| 8'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 7 |'$board[0,6].Icon'|'$board[1,6].Icon'|'$board[2,6].Icon'|'$board[3,6].Icon'|'$board[4,6].Icon'|'$board[5,6].Icon'|'$board[6,6].Icon'|'$board[7,6].Icon'| 7'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 6 |'$board[0,5].Icon'|'$board[1,5].Icon'|'$board[2,5].Icon'|'$board[3,5].Icon'|'$board[4,5].Icon'|'$board[5,5].Icon'|'$board[6,5].Icon'|'$board[7,5].Icon'| 6'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 5 |'$board[0,4].Icon'|'$board[1,4].Icon'|'$board[2,4].Icon'|'$board[3,4].Icon'|'$board[4,4].Icon'|'$board[5,4].Icon'|'$board[6,4].Icon'|'$board[7,4].Icon'| 5'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 4 |'$board[0,3].Icon'|'$board[1,3].Icon'|'$board[2,3].Icon'|'$board[3,3].Icon'|'$board[4,3].Icon'|'$board[5,3].Icon'|'$board[6,3].Icon'|'$board[7,3].Icon'| 4'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 3 |'$board[0,2].Icon'|'$board[1,2].Icon'|'$board[2,2].Icon'|'$board[3,2].Icon'|'$board[4,2].Icon'|'$board[5,2].Icon'|'$board[6,2].Icon'|'$board[7,2].Icon'| 3'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 2 |'$board[0,1].Icon'|'$board[1,1].Icon'|'$board[2,1].Icon'|'$board[3,1].Icon'|'$board[4,1].Icon'|'$board[5,1].Icon'|'$board[6,1].Icon'|'$board[7,1].Icon'| 2'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' 1 |'$board[0,0].Icon'|'$board[1,0].Icon'|'$board[2,0].Icon'|'$board[3,0].Icon'|'$board[4,0].Icon'|'$board[5,0].Icon'|'$board[6,0].Icon'|'$board[7,0].Icon'| 1'
|
|||
|
Write-Host ' --------------------------------- '
|
|||
|
Write-Host ' A B C D E F G H'
|
|||
|
}
|
|||
|
|
|||
|
#Read and clean text input before calling New-Move
|
|||
|
Function Read-Input {
|
|||
|
Write-Host ""
|
|||
|
if($Script:whiteTurn) {
|
|||
|
try {
|
|||
|
[ValidateScript({$_.Length -eq 2 -or $_ -like '*resign*'})]$src = Read-Host 'White piece source'
|
|||
|
if ($src -eq 'resign') {
|
|||
|
$Script:gameStatus = [gamestatus]::blackWin
|
|||
|
Update-Log -resign $true
|
|||
|
} else {
|
|||
|
[Int]$cc = Get-Column $src[0]
|
|||
|
[Int]$cr = Get-Row $src[1]
|
|||
|
[ValidateScript({$_.Color -eq 'White'})]$pc = $board[$cc, $cr]
|
|||
|
[ValidateScript({$_.Length -eq 2})]$dst = Read-Host 'White piece destination'
|
|||
|
New-Move $src $dst
|
|||
|
}
|
|||
|
} catch {
|
|||
|
Write-Error "Illegal input: Not a white piece or valid location"
|
|||
|
Write-Error $src
|
|||
|
Read-Input
|
|||
|
}
|
|||
|
} else {
|
|||
|
try {
|
|||
|
[ValidateScript({$_.Length -eq 2 -or $_.Value -eq 'resign'})]$src = Read-Host 'Black piece source'
|
|||
|
if ($src -like '*resign*') {
|
|||
|
$Script:gameStatus = [gamestatus]::whiteWin
|
|||
|
Update-Log -resign $true
|
|||
|
}
|
|||
|
[Int]$cc = Get-Column $src[0]
|
|||
|
[Int]$cr = Get-Row $src[1]
|
|||
|
[ValidateScript({$_.Color -eq 'Black'})]$pc = $board[$cc, $cr]
|
|||
|
[ValidateScript({$_.Length -eq 2})]$dst = Read-Host 'Black piece destination'
|
|||
|
New-Move $src $dst
|
|||
|
} catch {
|
|||
|
Write-Error "Illegal input: Not a black piece or valid location"
|
|||
|
Read-Input
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#Update the status of all the pieces and place them
|
|||
|
Function Update-Board {
|
|||
|
#Get arrays of all piece that are still alive
|
|||
|
[Array]$CurrentWhite = $Script:WhitePieces | Where-Object {$_.Alive -eq $true}
|
|||
|
[Array]$CurrentBlack = $Script:BlackPieces | Where-Object {$_.Alive -eq $true}
|
|||
|
|
|||
|
#Place all the white pieces
|
|||
|
foreach ($pc in $CurrentWhite) {
|
|||
|
$board[($pc.CurrentColumn),($pc.CurrentRow)] = $pc
|
|||
|
}
|
|||
|
#Place all the black pieces
|
|||
|
foreach ($pc in $CurrentBlack) {
|
|||
|
$board[($pc.CurrentColumn),($pc.CurrentRow)] = $pc
|
|||
|
}
|
|||
|
|
|||
|
#Check for spaces without a piece in them, then fill it with the empty placeholder.
|
|||
|
for ($i = 0; $i -le 7; $i++) {
|
|||
|
for ($j = 0; $j -le 7; $j++) {
|
|||
|
if ($board[$i, $j] -eq $null) {
|
|||
|
$board[$i, $j] = $Empty
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#Used to move pieces on the board
|
|||
|
Function New-Move {
|
|||
|
param ([string]$src, [string]$dst)
|
|||
|
|
|||
|
enum castleOptions {
|
|||
|
none = 0
|
|||
|
kingside = 1
|
|||
|
queenside = 2
|
|||
|
}
|
|||
|
|
|||
|
[bool]$attack = $false
|
|||
|
[bool]$moveSuccess = $false
|
|||
|
[int]$castle = [castleOptions]::none
|
|||
|
[bool]$promote = $false
|
|||
|
[bool]$ep = $false
|
|||
|
[bool]$check = $false
|
|||
|
|
|||
|
try {
|
|||
|
[Int]$CurrentColumn = Get-Column $src[0]
|
|||
|
[Int]$CurrentRow = Get-Row $src[1]
|
|||
|
[Int]$DesiredColumn = Get-Column $dst[0]
|
|||
|
[Int]$DesiredRow = Get-Row $dst[1]
|
|||
|
|
|||
|
$pc = $board[$CurrentColumn, $CurrentRow]
|
|||
|
} catch {
|
|||
|
Write-Error "Out of bounds"
|
|||
|
Read-Input
|
|||
|
}
|
|||
|
|
|||
|
#Moving nothing, nowhere, or trying to capture your own piece
|
|||
|
if ($board[$CurrentColumn, $CurrentRow] -eq $Empty) {
|
|||
|
Write-Error "There is nothing there."
|
|||
|
Read-Input
|
|||
|
} elseif (($CurrentRow -eq $DesiredRow) -and ($CurrentColumn -eq $DesiredColumn)) {
|
|||
|
Write-Error "That wouldn't move anywhere."
|
|||
|
Read-Input
|
|||
|
} elseif ($board[$DesiredColumn, $DesiredRow] -ne $Empty -and `
|
|||
|
$pc.Color -eq $board[$DesiredColumn, $DesiredRow].Color) {
|
|||
|
Write-Error "Collision with own team"
|
|||
|
Read-Input
|
|||
|
} else {
|
|||
|
[int]$MoveX = $DesiredColumn - $CurrentColumn
|
|||
|
[int]$MoveY = $DesiredRow - $CurrentRow
|
|||
|
|
|||
|
#Move verification logic for each piece
|
|||
|
switch ($pc.GetType().Name) {
|
|||
|
'Pawn' {
|
|||
|
$MoveX = [math]::abs($MoveX)
|
|||
|
|
|||
|
#Pawns can max move one to the side when capturing, two forward when moving
|
|||
|
if (($MoveX -gt 1) -or ([math]::abs($MoveY) -gt 2)) {
|
|||
|
Write-Error "Illegal Pawn Move: Too many spaces"
|
|||
|
} else {
|
|||
|
#Force pawns to only move "forward"
|
|||
|
if ($pc.Color -eq 'Black') {
|
|||
|
$MoveY *= -1
|
|||
|
}
|
|||
|
|
|||
|
if ($MoveX -eq 0) {
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -eq $Empty) {
|
|||
|
if ($MoveY -eq 1) {
|
|||
|
$moveSuccess = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
} elseif ($MoveY -eq 2 -and $pc.firstmove -eq $true) {
|
|||
|
if ($board[$DesiredColumn, ($DesiredRow + 1)] -eq $Empty) {
|
|||
|
$moveSuccess = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
$pc.inpassing = $Script:turnCounter
|
|||
|
} else {
|
|||
|
Write-Error "Illegal Pawn Move: Blocked Path"
|
|||
|
}
|
|||
|
} else {
|
|||
|
Write-Error "Illegal Pawn Move: Cannot Move 2 Spaces"
|
|||
|
}
|
|||
|
} else {
|
|||
|
Write-Error "Illegal Pawn Move: Blocked Path"
|
|||
|
}
|
|||
|
} elseif (($MoveX -eq 1) -and ($MoveY -eq 1)) {
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -eq $Empty) {
|
|||
|
$enpassant = $board[$DesiredColumn, $CurrentRow]
|
|||
|
if (($enpassant.GetType().Name -eq 'Pawn') -and `
|
|||
|
($pc.Color -ne $enpassant.Color) -and `
|
|||
|
($enpassant.inpassing -eq ($Script:turnCounter - 1))) {
|
|||
|
|
|||
|
$moveSuccess = $true
|
|||
|
$attack = $true
|
|||
|
$ep = $true
|
|||
|
|
|||
|
$enpassant.Alive = $false
|
|||
|
$enpassant.CurrentPosition = $null
|
|||
|
$enpassant.CurrentRow = $null
|
|||
|
$enpassant.CurrentColumn = $null
|
|||
|
$board[$DesiredColumn, $CurrentRow] = $Empty
|
|||
|
} else {
|
|||
|
Write-Error 'Illegal Pawn Move: Cannot Capture en passant'
|
|||
|
}
|
|||
|
} else {
|
|||
|
$attack = $true
|
|||
|
$moveSuccess = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} else {
|
|||
|
#Catch-all, should never get here
|
|||
|
Write-Error "Illegal Pawn Move"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Knight' {
|
|||
|
$MoveX = [math]::abs($MoveX)
|
|||
|
$MoveY = [math]::abs($MoveY)
|
|||
|
|
|||
|
if ((($MoveX -eq 1) -and ($MoveY -eq 2)) -or (($MoveX -eq 2) -and ($MoveY -eq 1))) {
|
|||
|
$moveSuccess = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$attack = $true
|
|||
|
}
|
|||
|
} else {
|
|||
|
Write-Error "Illegal Knight Move"
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Bishop' {
|
|||
|
if ([math]::abs($MoveX) -ne [math]::abs($MoveY)) {
|
|||
|
Write-Error "Illegal Bishop Move: Not a Diagonal"
|
|||
|
} else {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Bishop Move: Blocked Path"
|
|||
|
Read-Input
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Bishop Move: Blocked Path"
|
|||
|
Read-Input
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[($CurrentColumn - $i) , ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Bishop Move: Blocked Path"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Bishop Move: Blocked Path"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$moveSuccess = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$attack = $true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Rook' {
|
|||
|
if (([math]::abs($MoveX) -gt 0) -and ([math]::abs($MoveY) -gt 0)) {
|
|||
|
Write-Error "Illegal Rook Move"
|
|||
|
} else {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i), $CurrentRow] -ne $Empty) {
|
|||
|
Write-Error "Illegal Rook Move: Blocked Path"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveX -lt 0) {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i), $CurrentRow] -ne $Empty) {
|
|||
|
Write-Error "Illegal Rook Move: Blocked Path"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Rook Move: Blocked Path"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveY); $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Rook Move: Blocked Path"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$moveSuccess = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$attack = $true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'King' {
|
|||
|
$MoveX = [math]::abs($MoveX)
|
|||
|
$MoveY = [math]::abs($MoveY)
|
|||
|
|
|||
|
if (($MoveX -eq 1) -or ($MoveY -eq 1)) {
|
|||
|
$moveSuccess = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$attack = $true
|
|||
|
}
|
|||
|
} elseif (($pc.firstmove -eq $true) -and `
|
|||
|
($pc.color -eq 'White')) {
|
|||
|
if (($dst -eq 'G1') -and `
|
|||
|
($wHR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[7, 0]
|
|||
|
$board[7, 0] = $Empty
|
|||
|
$Crk.CurrentPosition = 'F1'
|
|||
|
$Crk.CurrentRow = 0
|
|||
|
$Crk.CurrentColumn = 5
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$moveSuccess = $true
|
|||
|
$castle = [castleOptions]::kingside
|
|||
|
$pc.firstmove = $false
|
|||
|
} elseif (($dst -eq 'C1') -and `
|
|||
|
($wAR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[0, 0]
|
|||
|
$board[0, 0] = $Empty
|
|||
|
$Crk.CurrentPosition = 'D1'
|
|||
|
$Crk.CurrentRow = 0
|
|||
|
$Crk.CurrentColumn = 3
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$moveSuccess = $true
|
|||
|
$castle = [castleOptions]::queenside
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} elseif (($pc.firstmove -eq $true) -and `
|
|||
|
($pc.color -eq 'Black')) {
|
|||
|
if (($dst -eq 'G8') -and `
|
|||
|
($bHR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[7, 7]
|
|||
|
$board[7, 7] = $Empty
|
|||
|
$Crk.CurrentPosition = 'F8'
|
|||
|
$Crk.CurrentRow = 7
|
|||
|
$Crk.CurrentColumn = 5
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$moveSuccess = $true
|
|||
|
$castle = [castleOptions]::kingside
|
|||
|
$pc.firstmove = $false
|
|||
|
} elseif (($dst -eq 'C8') -and `
|
|||
|
($bAR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[0, 7]
|
|||
|
$board[0, 7] = $Empty
|
|||
|
$Crk.CurrentPosition = 'D8'
|
|||
|
$Crk.CurrentRow = 7
|
|||
|
$Crk.CurrentColumn = 3
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$moveSuccess = $true
|
|||
|
$castle = [castleOptions]::queenside
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} else {
|
|||
|
Write-Error "Illegal King Move"
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Queen' {
|
|||
|
if ([math]::abs($MoveX) -eq [math]::abs($MoveY)) {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[($CurrentColumn - $i), ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$moveSuccess = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$attack = $true
|
|||
|
}
|
|||
|
} elseif (($MoveX -ne 0 -and $MoveY -eq 0) -or `
|
|||
|
($MoveX -eq 0 -and $MoveY -ne 0)) {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i), $CurrentRow] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveX -lt 0) {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i), $CurrentRow] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveY); $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
Publish-Board
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$moveSuccess = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$attack = $true
|
|||
|
}
|
|||
|
} else {
|
|||
|
Write-Error "Illegal Queen Move"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ($moveSuccess -eq $true) {
|
|||
|
if ($attack -eq $true -and $ep -eq $false) {
|
|||
|
$board[$DesiredColumn, $DesiredRow].Alive = $false
|
|||
|
$board[$DesiredColumn, $DesiredRow].CurrentPosition = $null
|
|||
|
$board[$DesiredColumn, $DesiredRow].CurrentRow = $null
|
|||
|
$board[$DesiredColumn, $DesiredRow].CurrentColumn = $null
|
|||
|
}
|
|||
|
|
|||
|
#Pawn Promotion logic
|
|||
|
if (($pc.GetType().Name -eq 'Pawn') -and ($DesiredRow -eq 0)) {
|
|||
|
[ValidateSet('Knight', 'Bishop', 'Rook', 'Queen')]$ptype = Read-Host 'Promote black pawn to'
|
|||
|
|
|||
|
$promote = $true
|
|||
|
$pc.Type = $ptype
|
|||
|
|
|||
|
switch ($ptype) {
|
|||
|
'Knight' {
|
|||
|
$pc.Icon = '♞'
|
|||
|
$pc.Symbol = 'N'
|
|||
|
}
|
|||
|
'Bishop' {
|
|||
|
$pc.Icon = '♝'
|
|||
|
$pc.Symbol = 'B'
|
|||
|
}
|
|||
|
'Rook' {
|
|||
|
$pc.Icon = '♜'
|
|||
|
$pc.Symbol = 'R'
|
|||
|
}
|
|||
|
'Queen' {
|
|||
|
$pc.Icon = '♛'
|
|||
|
$pc.Symbol = 'Q'
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif (($pc.GetType().Name -eq 'Pawn') -and ($DesiredRow -eq 7)) {
|
|||
|
[ValidateSet('Knight', 'Bishop', 'Rook', 'Queen')]$ptype = Read-Host 'Promote white pawn to'
|
|||
|
|
|||
|
$promote = $true
|
|||
|
$pc.Type = $ptype
|
|||
|
|
|||
|
switch ($ptype) {
|
|||
|
'Knight' {
|
|||
|
$pc.Icon = '♘'
|
|||
|
$pc.Symbol = 'N'
|
|||
|
}
|
|||
|
'Bishop' {
|
|||
|
$pc.Icon = '♗'
|
|||
|
$pc.Symbol = 'B'
|
|||
|
}
|
|||
|
'Rook' {
|
|||
|
$pc.Icon = '♖'
|
|||
|
$pc.Symbol = 'R'
|
|||
|
}
|
|||
|
'Queen' {
|
|||
|
$pc.Icon = '♕'
|
|||
|
$pc.Symbol = 'Q'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$board[$CurrentColumn, $CurrentRow] = $Empty
|
|||
|
$pc.CurrentPosition = $dst.ToUpper()
|
|||
|
$pc.CurrentRow = $DesiredRow
|
|||
|
$pc.CurrentColumn = $DesiredColumn
|
|||
|
|
|||
|
Update-Board
|
|||
|
|
|||
|
#Check logic
|
|||
|
#TODO: Shouldn't check when king is captured Issue 25
|
|||
|
Test-Gamestatus
|
|||
|
if ($Script:gameStatus -eq [gamestatus]::ongoing) {
|
|||
|
[Array]$curWhite = $Script:WhitePieces | Where-Object {$_.Alive -eq $true}
|
|||
|
[Array]$curBlack = $Script:BlackPieces | Where-Object {$_.Alive -eq $true}
|
|||
|
|
|||
|
if ($Script:whiteTurn -eq $true) {
|
|||
|
foreach ($whitePiece in $curWhite) {
|
|||
|
if ($(Test-Move $whitePiece.CurrentPosition $Script:bK.CurrentPosition)[0] -eq $true) {
|
|||
|
$check = $true
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
foreach ($blackPiece in $curBlack) {
|
|||
|
if ($(Test-Move $blackPiece.CurrentPosition $Script:wK.CurrentPosition)[0] -eq $true) {
|
|||
|
$check = $true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#Update the log, advance turn
|
|||
|
Update-Log $src $dst $pc.Symbol $attack $castle $promote $ep $check
|
|||
|
$Script:turnCounter += 1
|
|||
|
$Script:whiteTurn = !($Script:whiteTurn)
|
|||
|
} else {
|
|||
|
Read-Input
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#Log logic will go here
|
|||
|
Function Update-Log {
|
|||
|
param([string]$src, [string]$dst, [string]$piece, [bool]$attack,
|
|||
|
[int]$castle, [bool]$promote, [bool]$ep, [bool]$check, [bool]$resign)
|
|||
|
|
|||
|
[string]$logentry = ''
|
|||
|
|
|||
|
enum castleOptions {
|
|||
|
none = 0
|
|||
|
kingside = 1
|
|||
|
queenside = 2
|
|||
|
}
|
|||
|
|
|||
|
if ($castle -eq [castleOptions]::kingside) {
|
|||
|
$logentry = '0-0'
|
|||
|
} elseif ($castle -eq [castleOptions]::queenside) {
|
|||
|
$logentry = '0-0-0'
|
|||
|
} elseif ($promote -eq $true) {
|
|||
|
if ($attack) {
|
|||
|
$logentry += 'x'
|
|||
|
}
|
|||
|
$logentry += $dst + '=' + $piece
|
|||
|
} else {
|
|||
|
$logentry = $piece
|
|||
|
if ($attack) {
|
|||
|
$logentry += 'x'
|
|||
|
}
|
|||
|
$logentry += $dst
|
|||
|
}
|
|||
|
|
|||
|
if ($ep -eq $true) {
|
|||
|
$logentry += ' ep'
|
|||
|
}
|
|||
|
|
|||
|
if ($check -eq $true) {
|
|||
|
$logentry += '+'
|
|||
|
}
|
|||
|
|
|||
|
if ($Script:gameStatus -ne 0) {
|
|||
|
$logentry += '#'
|
|||
|
}
|
|||
|
|
|||
|
if ($resign -eq $true) {
|
|||
|
$logentry = 'resigned'
|
|||
|
}
|
|||
|
|
|||
|
$Script:log += $logentry
|
|||
|
|
|||
|
#Equivalent of touch command to ensure a log exists
|
|||
|
Write-Output $null >> $Script:logpath
|
|||
|
|
|||
|
#Clear and rewrite the log each time
|
|||
|
Clear-Content $Script:logpath
|
|||
|
$line = "White`t`tBlack`r`n--------------------"
|
|||
|
|
|||
|
#Header
|
|||
|
Add-Content -Encoding Unicode $Script:logpath $line
|
|||
|
|
|||
|
if ($log.Length -eq 1) {
|
|||
|
Add-Content -Encoding Unicode $Script:logpath $log[0]
|
|||
|
} else {
|
|||
|
for ($i = 0; $i -lt $log.Length - 1; $i += 2) {
|
|||
|
$line = $Script:log[$i]
|
|||
|
$line += " `t`t"
|
|||
|
$line += $Script:log[$i + 1]
|
|||
|
Add-Content -Encoding Unicode $Script:logpath $line
|
|||
|
}
|
|||
|
|
|||
|
#If game ended in white move, print out the "half-line"
|
|||
|
if ($log.Length % 2 -eq 1) {
|
|||
|
Add-Content -Encoding Unicode $Script:logpath $Script:log[$Script:log.Length - 1]
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#Try a move, used for check and castling logic
|
|||
|
Function Test-Move {
|
|||
|
param ([string]$src, [string]$dst)
|
|||
|
|
|||
|
[bool]$attack = $false
|
|||
|
[bool]$moveSuccess = $false
|
|||
|
[bool[]]$status = @($moveSuccess, $attack)
|
|||
|
|
|||
|
try {
|
|||
|
[Int]$CurrentColumn = Get-Column $src[0]
|
|||
|
[Int]$CurrentRow = Get-Row $src[1]
|
|||
|
[Int]$DesiredColumn = Get-Column $dst[0]
|
|||
|
[Int]$DesiredRow = Get-Row $dst[1]
|
|||
|
|
|||
|
$pc = $board[$CurrentColumn, $CurrentRow]
|
|||
|
} catch {
|
|||
|
Write-Error "Out of bounds"
|
|||
|
return $status
|
|||
|
}
|
|||
|
|
|||
|
#Moving nothing, nowhere, or trying to capture your own piece
|
|||
|
if ($board[$CurrentColumn, $CurrentRow] -eq $Empty) {
|
|||
|
Write-Error "There is nothing there."
|
|||
|
return $status
|
|||
|
} elseif (($CurrentRow -eq $DesiredRow) -and ($CurrentColumn -eq $DesiredColumn)) {
|
|||
|
Write-Error "That wouldn't move anywhere."
|
|||
|
return $status
|
|||
|
} elseif ($board[$DesiredColumn, $DesiredRow] -ne $Empty -and `
|
|||
|
$pc.Color -eq $board[$DesiredColumn, $DesiredRow].Color) {
|
|||
|
Write-Error "Collision with own team"
|
|||
|
return $status
|
|||
|
} else {
|
|||
|
[int]$MoveX = $DesiredColumn - $CurrentColumn
|
|||
|
[int]$MoveY = $DesiredRow - $CurrentRow
|
|||
|
|
|||
|
#Pieces playable
|
|||
|
switch ($pc.Type) {
|
|||
|
'Pawn' {
|
|||
|
$MoveX = [math]::abs($MoveX)
|
|||
|
if (($MoveX -gt 1) -or ([math]::abs($MoveY) -gt 2)) {
|
|||
|
return $status
|
|||
|
} else {
|
|||
|
#Force pawns to only move "forward"
|
|||
|
if ($pc.Color -eq 'Black') {
|
|||
|
$MoveY *= -1
|
|||
|
}
|
|||
|
if (($MoveX -eq 0) -and ($MoveY -eq 1)) {
|
|||
|
if ($board[$DesiredColumn,$DesiredRow] -ne $Empty) {
|
|||
|
return $status
|
|||
|
} else {
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} elseif (($MoveX -eq 0) -and ($MoveY -eq 2)) {
|
|||
|
if (($pc.firstmove = $true) -and `
|
|||
|
(($board[$DesiredColumn, $DesiredRow] -eq $Empty) -and `
|
|||
|
($board[($DesiredColumn + 1), $DesiredRow] -eq $Empty))) {
|
|||
|
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
$pc.inpassing = $Script:turnCounter
|
|||
|
} else {
|
|||
|
return $status
|
|||
|
}
|
|||
|
} elseif (($MoveX -eq 1) -and ($MoveY -eq 1)) {
|
|||
|
if ($board[$DesiredColumn,$DesiredRow] -eq $Empty) {
|
|||
|
$enpassant = $board[$DesiredColumn, $CurrentRow]
|
|||
|
if (($enpassant.GetType().Name -eq 'Pawn') -and `
|
|||
|
($pc.Color -ne $enpassant.Color) -and `
|
|||
|
($enpassant.inpassing -eq ($Script:turnCounter - 1))) {
|
|||
|
|
|||
|
$status[0] = $true
|
|||
|
|
|||
|
$enpassant.Alive = $false
|
|||
|
$enpassant.CurrentPosition = $null
|
|||
|
$enpassant.CurrentRow = $null
|
|||
|
$enpassant.CurrentColumn = $null
|
|||
|
$board[$DesiredColumn, $CurrentRow] = $Empty
|
|||
|
} else {
|
|||
|
return $status
|
|||
|
}
|
|||
|
} else {
|
|||
|
$status[1] = $true
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} else {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Knight' {
|
|||
|
$MoveX = [math]::abs($MoveX)
|
|||
|
$MoveY = [math]::abs($MoveY)
|
|||
|
|
|||
|
if ((($MoveX -eq 1) -and ($MoveY -eq 2)) -or (($MoveX -eq 2) -and ($MoveY -eq 1))) {
|
|||
|
$status[0] = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$status[1] = $true
|
|||
|
}
|
|||
|
} else {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Bishop' {
|
|||
|
if ([math]::abs($MoveX) -ne [math]::abs($MoveY)) {
|
|||
|
return $status
|
|||
|
} else {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[($CurrentColumn - $i) , ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$status[0] = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$status[1] = $true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Rook' {
|
|||
|
if (([math]::abs($MoveX) -gt 0) -and ([math]::abs($MoveY) -gt 0)) {
|
|||
|
return $status
|
|||
|
} else {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i), $CurrentRow] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveX -lt 0) {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i), $CurrentRow] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveY); $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$status[1] = $true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'Queen' {
|
|||
|
if ([math]::abs($MoveX) -eq [math]::abs($MoveY)) {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
if ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[($CurrentColumn - $i), ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i) , ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$status[0] = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$status[1] = $true
|
|||
|
}
|
|||
|
} elseif (($MoveX -ne 0 -and $MoveY -eq 0) -or `
|
|||
|
($MoveX -eq 0 -and $MoveY -ne 0)) {
|
|||
|
if ($MoveX -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveX; $i++) {
|
|||
|
if ($board[($CurrentColumn + $i), $CurrentRow] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveX -lt 0) {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveX); $i++) {
|
|||
|
if ($board[($CurrentColumn - $i), $CurrentRow] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} elseif ($MoveY -gt 0) {
|
|||
|
for ($i = 1; $i -lt $MoveY; $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow + $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for ($i = 1; $i -lt [math]::abs($MoveY); $i++) {
|
|||
|
if ($board[$CurrentColumn, ($CurrentRow - $i)] -ne $Empty) {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$status[0] = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$status[1] = $true
|
|||
|
}
|
|||
|
} else {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'King' {
|
|||
|
$MoveX = [math]::abs($MoveX)
|
|||
|
$MoveY = [math]::abs($MoveY)
|
|||
|
|
|||
|
if (($MoveX -le 1) -and ($MoveY -le 1)) {
|
|||
|
$status[0] = $true
|
|||
|
if ($board[$DesiredColumn, $DesiredRow] -ne $Empty) {
|
|||
|
$status[1] = $true
|
|||
|
}
|
|||
|
} elseif (($pc.firstmove -eq $true) -and `
|
|||
|
($pc.color -eq 'White')) {
|
|||
|
if (($dst -eq 'G1') -and `
|
|||
|
($wHR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[7, 0]
|
|||
|
$board[7, 0] = $Empty
|
|||
|
$Crk.CurrentPosition = 'F1'
|
|||
|
$Crk.CurrentRow = 0
|
|||
|
$Crk.CurrentColumn = 5
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
} elseif (($dst -eq 'C1') -and `
|
|||
|
($wAR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[0, 0]
|
|||
|
$board[0, 0] = $Empty
|
|||
|
$Crk.CurrentPosition = 'D1'
|
|||
|
$Crk.CurrentRow = 0
|
|||
|
$Crk.CurrentColumn = 3
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} elseif (($pc.firstmove -eq $true) -and `
|
|||
|
($pc.color -eq 'Black')) {
|
|||
|
if (($dst -eq 'G8') -and `
|
|||
|
($bHR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[7, 7]
|
|||
|
$board[7, 7] = $Empty
|
|||
|
$Crk.CurrentPosition = 'F8'
|
|||
|
$Crk.CurrentRow = 7
|
|||
|
$Crk.CurrentColumn = 5
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
} elseif (($dst -eq 'C8') -and `
|
|||
|
($bAR.firstmove -eq $true)) {
|
|||
|
|
|||
|
$Crk = $board[0, 7]
|
|||
|
$board[0, 7] = $Empty
|
|||
|
$Crk.CurrentPosition = 'D8'
|
|||
|
$Crk.CurrentRow = 7
|
|||
|
$Crk.CurrentColumn = 3
|
|||
|
$Crk.firstmove = $false
|
|||
|
|
|||
|
$status[0] = $true
|
|||
|
$pc.firstmove = $false
|
|||
|
}
|
|||
|
} else {
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return $status
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#Figure out if the game is over or still ongoing
|
|||
|
Function Test-Gamestatus {
|
|||
|
if ($wK.Alive -eq $false) {
|
|||
|
$Script:gameStatus = [gamestatus]::blackWin
|
|||
|
} elseif ($bK.Alive -eq $false) {
|
|||
|
$Script:gameStatus = [gamestatus]::whiteWin
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Function Get-Column {
|
|||
|
param ([ValidatePattern('[A-H]')][string]$Col)
|
|||
|
switch ($Col) {
|
|||
|
"A" {Return "0"}
|
|||
|
"B" {Return "1"}
|
|||
|
"C" {Return "2"}
|
|||
|
"D" {Return "3"}
|
|||
|
"E" {Return "4"}
|
|||
|
"F" {Return "5"}
|
|||
|
"G" {Return "6"}
|
|||
|
"H" {Return "7"}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Function Get-Row {
|
|||
|
param ([ValidateRange(1,8)][string]$row)
|
|||
|
|
|||
|
return ($row - 1)
|
|||
|
}
|
|||
|
|
|||
|
###########################
|
|||
|
#endregion: Functions
|
|||
|
####################################################
|
|||
|
|
|||
|
|
|||
|
####################################################
|
|||
|
#region: Classes
|
|||
|
###########################
|
|||
|
|
|||
|
#Gives all classes that inherit(:) this class the base properties
|
|||
|
Class ChessPiece {
|
|||
|
[bool]$Alive=$true
|
|||
|
[string]$Type
|
|||
|
[string]$Icon
|
|||
|
[string]$Symbol
|
|||
|
[ValidateSet('White', 'Black')][String]$Color
|
|||
|
[String]$CurrentPosition
|
|||
|
[ValidateRange(0,7)][Int]$CurrentRow
|
|||
|
[ValidateRange(0,7)][Int]$CurrentColumn
|
|||
|
}
|
|||
|
|
|||
|
Class Pawn : ChessPiece {
|
|||
|
[bool]$firstmove = $true
|
|||
|
[int]$inpassing = 0
|
|||
|
[string]$Type = $this.GetType().Name
|
|||
|
[string]$Symbol = " "
|
|||
|
Pawn([string]$Position, [string]$color) {
|
|||
|
$this.Color = $color
|
|||
|
$this.CurrentPosition = $Position
|
|||
|
$this.CurrentRow = Get-Row $Position[1]
|
|||
|
$this.CurrentColumn = Get-Column $Position[0]
|
|||
|
|
|||
|
if ($color -eq 'White') {
|
|||
|
$this.Icon = '♙'
|
|||
|
} elseif ($color -eq 'Black') {
|
|||
|
$this.Icon = '♟'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Class Rook : ChessPiece {
|
|||
|
[bool]$firstmove = $true
|
|||
|
[string]$Type = $this.GetType().Name
|
|||
|
[string]$Symbol = "R"
|
|||
|
Rook([string]$Position, [string]$color) {
|
|||
|
$this.Color = $color
|
|||
|
$this.CurrentPosition = $Position
|
|||
|
$this.CurrentRow = Get-Row $Position[1]
|
|||
|
$this.CurrentColumn = Get-Column $Position[0]
|
|||
|
|
|||
|
if ($color -eq 'White') {
|
|||
|
$this.Icon = '♖'
|
|||
|
} elseif ($color -eq 'Black') {
|
|||
|
$this.Icon = '♜'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Class Knight : ChessPiece {
|
|||
|
[string]$Type = $this.GetType().Name
|
|||
|
[string]$Symbol = "N"
|
|||
|
Knight([string]$Position, [string]$color) {
|
|||
|
$this.Color = $color
|
|||
|
$this.CurrentPosition = $Position
|
|||
|
$this.CurrentRow = Get-Row $Position[1]
|
|||
|
$this.CurrentColumn = Get-Column $Position[0]
|
|||
|
|
|||
|
if ($color -eq 'White') {
|
|||
|
$this.Icon = '♘'
|
|||
|
} elseif ($color -eq 'Black') {
|
|||
|
$this.Icon = '♞'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Class Bishop : ChessPiece {
|
|||
|
[string]$Type = $this.GetType().Name
|
|||
|
[string]$Symbol = "B"
|
|||
|
Bishop([String]$Position, [string]$color) {
|
|||
|
$this.Color = $color
|
|||
|
$this.CurrentPosition = $Position
|
|||
|
$this.CurrentRow = Get-Row $Position[1]
|
|||
|
$this.CurrentColumn = Get-Column $Position[0]
|
|||
|
|
|||
|
if ($color -eq 'White') {
|
|||
|
$this.Icon = '♗'
|
|||
|
} elseif ($color -eq 'Black') {
|
|||
|
$this.Icon = '♝'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Class Queen : ChessPiece {
|
|||
|
[string]$Type = $this.GetType().Name
|
|||
|
[string]$Symbol = "Q"
|
|||
|
Queen([String]$Position, [string]$color) {
|
|||
|
$this.Color = $color
|
|||
|
$this.CurrentPosition = $Position
|
|||
|
$this.CurrentRow = Get-Row $Position[1]
|
|||
|
$this.CurrentColumn = Get-Column $Position[0]
|
|||
|
|
|||
|
if ($color -eq 'White') {
|
|||
|
$this.Icon = '♕'
|
|||
|
} elseif ($color -eq 'Black') {
|
|||
|
$this.Icon = '♛'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Class King : ChessPiece {
|
|||
|
[bool]$firstmove = $true
|
|||
|
[string]$Type = $this.GetType().Name
|
|||
|
[string]$Symbol = "K"
|
|||
|
King([String]$Position, [string]$color) {
|
|||
|
$this.Color = $color
|
|||
|
$this.CurrentPosition = $Position
|
|||
|
$this.CurrentRow = Get-Row $Position[1]
|
|||
|
$this.CurrentColumn = Get-Column $Position[0]
|
|||
|
|
|||
|
if ($color -eq 'White') {
|
|||
|
$this.Icon = '♔'
|
|||
|
} elseif ($color -eq 'Black') {
|
|||
|
$this.Icon = '♚'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Class Blank {
|
|||
|
[String]$Icon=' '
|
|||
|
}
|
|||
|
|
|||
|
###########################
|
|||
|
#endregion: Classes
|
|||
|
####################################################
|
|||
|
|
|||
|
#Creates the game board
|
|||
|
[Object]$Script:board = New-Object 'object[,]' 8,8
|
|||
|
|
|||
|
#Creates a turn status
|
|||
|
[bool]$Script:whiteTurn = $true
|
|||
|
|
|||
|
#SAN log.txt path, currently on desktop
|
|||
|
$DesktopPath = [Environment]::GetFolderPath("Desktop")
|
|||
|
[string]$Script:logpath = $DesktopPath + '\log.txt'
|
|||
|
[string[]]$Script:log = @()
|
|||
|
|
|||
|
$Script:wAP = [Pawn]::New('A2', 'White')
|
|||
|
$Script:wBP = [Pawn]::New('B2', 'White')
|
|||
|
$Script:wCP = [Pawn]::New('C2', 'White')
|
|||
|
$Script:wDP = [Pawn]::New('D2', 'White')
|
|||
|
$Script:wEP = [Pawn]::New('E2', 'White')
|
|||
|
$Script:wFP = [Pawn]::New('F2', 'White')
|
|||
|
$Script:wGP = [Pawn]::New('G2', 'White')
|
|||
|
$Script:wHP = [Pawn]::New('H2', 'White')
|
|||
|
$Script:wAR = [Rook]::New('A1', 'White')
|
|||
|
$Script:wBN = [Knight]::New('B1', 'White')
|
|||
|
$Script:wCB = [Bishop]::New('C1', 'White')
|
|||
|
$Script:wQ = [Queen]::New('D1', 'White')
|
|||
|
$Script:wK = [King]::New('E1', 'White')
|
|||
|
$Script:wFB = [Bishop]::New('F1', 'White')
|
|||
|
$Script:wGN = [Knight]::New('G1', 'White')
|
|||
|
$Script:wHR = [Rook]::New('H1', 'White')
|
|||
|
|
|||
|
$Script:bAP = [Pawn]::New('A7', 'Black')
|
|||
|
$Script:bBP = [Pawn]::New('B7', 'Black')
|
|||
|
$Script:bCP = [Pawn]::New('C7', 'Black')
|
|||
|
$Script:bDP = [Pawn]::New('D7', 'Black')
|
|||
|
$Script:bEP = [Pawn]::New('E7', 'Black')
|
|||
|
$Script:bFP = [Pawn]::New('F7', 'Black')
|
|||
|
$Script:bGP = [Pawn]::New('G7', 'Black')
|
|||
|
$Script:bHP = [Pawn]::New('H7', 'Black')
|
|||
|
$Script:bAR = [Rook]::New('A8', 'Black')
|
|||
|
$Script:bBN = [Knight]::New('B8', 'Black')
|
|||
|
$Script:bCB = [Bishop]::New('C8', 'Black')
|
|||
|
$Script:bQ = [Queen]::New('D8', 'Black')
|
|||
|
$Script:bK = [King]::New('E8', 'Black')
|
|||
|
$Script:bFB = [Bishop]::New('F8', 'Black')
|
|||
|
$Script:bGN = [Knight]::New('G8', 'Black')
|
|||
|
$Script:bHR = [Rook]::New('H8', 'Black')
|
|||
|
|
|||
|
$Script:Empty = [Blank]::New()
|
|||
|
|
|||
|
[Array] $Script:WhitePieces = @(
|
|||
|
$Script:wAP,$Script:wBP,$Script:wCP,$Script:wDP,
|
|||
|
$Script:wEP,$Script:wFP,$Script:wGP,$Script:wHP,
|
|||
|
$Script:wAR,$Script:wHR,$Script:wBN,$Script:wGN,
|
|||
|
$Script:wCB,$Script:wFB,$Script:wQ,$Script:wK
|
|||
|
)
|
|||
|
|
|||
|
[Array] $Script:BlackPieces = @(
|
|||
|
$Script:bAP,$Script:bBP,$Script:bCP,$Script:bDP,
|
|||
|
$Script:bEP,$Script:bFP,$Script:bGP,$Script:bHP,
|
|||
|
$Script:bAR,$Script:bHR,$Script:bBN,$Script:bGN,
|
|||
|
$Script:bCB,$Script:bFB,$Script:bQ,$Script:bK
|
|||
|
)
|
|||
|
|
|||
|
enum gamestatus {
|
|||
|
ongoing = 0
|
|||
|
whiteWin = 1
|
|||
|
blackWin = 2
|
|||
|
quit = 3
|
|||
|
}
|
|||
|
|
|||
|
#Set global variables to keep track of turn and game status
|
|||
|
[int]$Script:turnCounter = 0
|
|||
|
$Script:gameStatus = [gamestatus]::ongoing
|
|||
|
|
|||
|
while ($Script:gameStatus -eq [gamestatus]::ongoing) {
|
|||
|
Update-Board
|
|||
|
Publish-Board
|
|||
|
Read-Input
|
|||
|
|
|||
|
if ($Script:gameStatus -eq [gamestatus]::blackWin) {
|
|||
|
Write-Output "Black Wins!"
|
|||
|
} elseif ($Script:gameStatus -eq [gamestatus]::whiteWin) {
|
|||
|
Write-Output "White Wins!"
|
|||
|
} elseif ($Script:gameStatus -eq [gamestatus]::quit) {
|
|||
|
Write-Output "Game ended by request."
|
|||
|
}
|
|||
|
}
|