New-PSConftris.ps1
<#
.SYNOPSIS A game for the Powershell console based on a classic .DESCRIPTION This module demonstrates what is possible with the PowerShell console. Fixed positions for screen output etc. Everything is programmed very rudimentarily and certainly not in a good style. But it was in about 12 hours so far that it worked :-) .PARAMETER width minimum 9 chars - width of the playfields .PARAMETER height minimum 19 chars - height of the playfields .PARAMETER PsconfRegion Countdown for "Asis", "Europe" od "all" .EXAMPLE New-PSConfTris New-PSConfTris -width 11 -height 21 New-PSConfTris -width 9 -height 19 -PsconfRegion Asia New-PSConfTris -PsconfRegion All .NOTES Place additional notes here. .LINK URLs to related sites The first link is opened by Get-Help -Online New-PSConfTris .INPUTS List of input types that are accepted by this function. .OUTPUTS List of output types produced by this function. #> #> #Global #https://en.wikipedia.org/wiki/Block_Elements $UnicodeBlocks = @{FULLBLOCK=9608;LIGHTSHADE=9617;MEDIUMSHADE=9618;DARKSHADE=9619} $BlockColors = @("green", "White", "Blue", "Yellow" ) function New-PSConfTris{ param( [ValidateRange(9,400)] [int] $width = 9, [ValidateRange(19,400)] [int] $height = 19, [ValidateSet("Europe","Asia","all")] [string] $PsconfRegion = "all" ) $Script:Width = $width $Script:Height = $height [int[]] $Script:Lines=@(0..($Height-1)) [boolean[]] $Script:Field = @(0..($Width * $Height-1)) [int] $Script:Stone = Get-Random -Minimum 0 -Maximum 7 [int] $Script:Angle = Get-Random -Minimum 0 -Maximum 4 [int] $Script:XPos = 1 [int] $Script:YPos = 1 [int] $Script:Wait = 0 [bool] $Script:DoWas = $false [int] $Script:DoneLines = 0; [bool] $Script:AllDone = $false [int] $Script:OffestX = 1 [int] $Script:OffestY = 1 [bool] $Script:Debug = $false $Script:Stones = @( @( @{left=1;right=2;up=0;down=0; data=@(-1;0;1;2)} @{left=0;right=0;up=1;down=2; data=@(-$Width,0,$Width,(2 * $Width ))} @{left=1;right=2;up=0;down=0; data=@(-1,0,1,2)} @{left=0;right=0;up=1;down=2; data=@(-$Width,0,$Width,(2 * $Width))} ), @( @{left=0;right=1;up=0;down=1; data=@(0;1;$Width;$Width+1)} @{left=0;right=1;up=0;down=1; data=@(0;1;$Width;$Width+1)} @{left=0;right=1;up=0;down=1; data=@(0;1;$Width;$Width+1)} @{left=0;right=1;up=0;down=1; data=@(0;1;$Width;$Width+1)} ), @( @{left=1;right=1;up=0;down=1; data=@(-1;0;1;$Width)} @{left=1;right=0;up=1;down=1; data=@(-$Width;-1;0;$Width)} @{left=1;right=1;up=1;down=0; data=@(-$Width;-1;0;1)} @{left=0;right=1;up=1;down=1; data=@(-$Width;0;1;$Width)} ), @( @{left=1;right=1;up=0;down=1; data=@(-1;0;1;$Width-1)}; @{left=1;right=0;up=1;down=1; data=@(-$Width-1;-$Width;0;$Width)}; @{left=1;right=1;up=1;down=0; data=@(-$Width+1;-1;0;1)}; @{left=0;right=1;up=1;down=1; data=@(-$Width;0;$Width;$Width+1)}; ), @( @{left=1;right=1;up=0;down=1; data=@(-1;0;1;$Width + 1)} @{left=1;right=0;up=1;down=1; data=@(-$Width;0;$Width - 1;$Width)} @{left=1;right=1;up=1;down=0; data=@(-$Width -1;-1;0;1)} @{left=0;right=1;up=1;down=1; data=@(-$Width;-$Width+1;0;$Width)} ), @( @{left=1;right=1;up=1;down=0; data=@(-$Width-1;-$Width;0;1)} @{left=0;right=1;up=1;down=1; data=@(-$Width+1;0;1;$Width)} @{left=1;right=1;up=1;down=0; data=@(-$Width-1;-$Width;0;1)} @{left=0;right=1;up=1;down=1; data=@(-$Width+1;0;1;$Width)} ), @( @{left=1;right=1;up=1;down=0; data=@(-$Width;-$Width+1;-1;0)} @{left=0;right=1;up=1;down=1; data=@(-$Width;0;1;$Width+1)} @{left=1;right=1;up=1;down=0; data=@(-$Width;-$Width+1;-1;0)} @{left=0;right=1;up=1;down=1; data=@(-$Width;0;1;$Width+1)} )) #43 chars [int]$artWidth = 50 $Art = @' ( ( _ _ )\ ) )\ ) ( ( _| | |_ (()/((()/( )\ )\ ) |_ . _| /(_))/(_))(((_) ( ( (()/( |_ _|(_)) (_)) )\___ )\ )\ ) /(_)) |_|_| | _ \/ __|((/ __| ((_) _(_/((_) _| | _/\__ \ | (__ / _ \| ' \))| _| |_| |___/ \___|\___/|_||_| |_| I can't wait - so i want to play PSConfTris until the next psconf '@ #$psconfdate = [System.DateTime]::new(2019,06,04) #$today = [System.DateTime]::Today #$Text = "… days until psconf.eu 2019' if((-not ($Debug)) -and $host.name -ne "ConsoleHost") { #$Script:args = "-noexit -file " + "$PSScriptRoot\" + $MyInvocation.MyCommand.Name "New-PSConfTris -width $width -height $height -PsconfRegion $PsconfRegion " | Out-File "$env:temp\New-PSConfTris.ps1" $Script:args = '-noexit -file "' + "$env:temp\New-PSConfTris.ps1" + '"' Write-host $Script:args start-process powershell -ArgumentList $Script:args #Write-Host "please start only in the console" } else { Clear-Host Set-Tables if(! $Debug) { #$host.ui.rawui.CursorSize #$Script:BackgroundColor = $host.ui.rawui.BackgroundColor #$Script:ForgroundColor = $host.ui.rawui.ForegroundColor $Script:WinWidth = $host.ui.rawui.WindowSize.Width $Script:WinHeight = $host.ui.rawui.WindowSize.Height Set-ConsoleWindow -width ($Script:Width + $artWidth) -height ($Script:Height + 2) -titel 'PSConfTris 2018 - @nickinformation' Add-ConsoleBox -x 0 -y 0 -width ($Script:Width +2) -height ($Script:Height +2) Set-ASCIIArt -x ($Script:Width + 3) -y 4 -art $Art $mid = [math]::Floor($Script:Width / 2) -2 set-ConsolePosition -x $mid -y 3 Write-Host " Press" set-ConsolePosition -x $mid -y 4 Write-Host "Key to" set-ConsolePosition -x $mid -y 5 Write-Host " Start" set-ConsolePosition -x $mid -y 7 Write-Host "Esc =" set-ConsolePosition -x $mid -y 8 Write-Host " Exit" [console]::ReadKey() } Clear-Host Set-ASCIIArt -x ($Script:Width + 3) -y 4 -art $Art $Script:Exit = $false while(!$Script:Exit){ Start-Game $csize = $host.ui.rawui.CursorSize $host.ui.rawui.CursorSize = 0 Set-Fall Add-ConsoleBox -x 0 -y 0 -width ($Script:Width +2) -height ($Script:Height +2) set-ConsolePosition -x ($Script:Width + 4) -y 1 Write-Host $("Score: " + $Script:DoneLines + " ") set-ConsolePosition -x ($Script:Width + 7) -y 16 $today = [System.DateTime]::Now $psconfeudate = [System.DateTime]::new(2019,06,04,9,0,0) $psconfasisdate = [System.DateTime]::new(2018,10,19,9,0,0) switch ($PsconfRegion) { 'Europe' { $psct = ($psconfeudate - $today) Write-Host $("PSConf.eu: {0} d, {1} h {2} m and {3} " -f $psct.Days, $psct.Hours, $psct.Minutes, $psct.Seconds ) } 'Asia' { $psct = ($psconfasisdate - $today) Write-Host $("PSConf.asia: {0} d, {1} h {2} m and {3} " -f $psct.Days, $psct.Hours, $psct.Minutes, $psct.Seconds ) } 'all' { $psct = ($psconfeudate - $today) Write-Host $("PSConf.eu: {0} d, {1} h {2} m and {3} " -f $psct.Days, $psct.Hours, $psct.Minutes, $psct.Seconds ) set-ConsolePosition -x ($Script:Width + 7) -y 18 $psct = ($psconfasisdate - $today) Write-Host $("PSConf.asia: {0} d, {1} h {2} m and {3} " -f $psct.Days, $psct.Hours, $psct.Minutes, $psct.Seconds ) } } $host.ui.rawui.CursorSize = $csize } Clear-Host Write-host "Thanks for playing: You will meet me at the next PSConf.eu ;-)" Write-Host "@nickinformation" Write-Host "www.andreasnick.com" Write-Host break if(!$Debug) { #Set-ConsoleWindow -width $Script:WinWidth -heigh $Script:WinHeight -titel "Windows PowerShell" #` #-backgroundColor $Script:BackgroundColor -forgroundColor $Script:ForgroundColor #Clear-Host } } } function Set-ConsoleWindow { Param( [int] $width = 10, [int] $height = 20, [string] $titel = "PSWin" #[ConsoleColor] $backgroundColor = $Null, #[ConsoleColor] $forgroundColor = $Null ) If ($host.ui.rawui.BufferSize.Width -gt $Width ) { $host.ui.rawui.WindowSize.Width = $Width $host.ui.rawui.WindowSize = $host.ui.rawui.WindowSize } $Size = $host.ui.rawui.BufferSize $Size.Width = $Width +10 $Size.Height = $height +10 $host.ui.rawui.BufferSize = $Size $Size = $host.ui.rawui.WindowSize $Size.Width = $Width $Size.Height = $height $host.ui.rawui.WindowSize = $Size $host.ui.rawui.WindowTitle = $titel <# if($backgroundColor){ $host.ui.rawui.BackgroundColor = $backgroundColor } if($forgroundColor){ $host.ui.rawui.ForegroundColor = $forgroundColor } #> Clear-Host } function set-ConsolePosition { Param( [Parameter(Mandatory)] [int]$x, [Parameter(Mandatory)] [int]$y ) $position=$host.ui.rawui.cursorposition $position.x=$x $position.y=$y $host.ui.rawui.cursorposition = $position } function Add-Pixel { Param( [Parameter(Mandatory)] [int]$x, [Parameter(Mandatory)] [int]$y, [char] $Character = [char] $UnicodeBlocks.LIGHTSHADE ) $position=$host.ui.rawui.cursorposition $position.x=$x $position.y=$y $host.ui.rawui.cursorposition=$position write-host $Character -NoNewline #-ForegroundColor ($BlockColors[(Get-Random -Minimum 0 -Maximum 4)]) } function Add-ConsoleLine{ param( [Parameter(Mandatory)][ValidateRange(0,400)][int]$x, [Parameter(Mandatory)][ValidateRange(0,400)][int]$y, [ValidateRange(1,400)] [int]$lineLength = 1, [bool]$vertical = $false, [char] $lineCharacter = [char] $UnicodeBlocks.LIGHTSHADE ) for($c = 0;$c -lt $lineLength;$c++){ if($vertical){ set-ConsolePosition -x $x -y ($y +$c) } else { set-ConsolePosition -x ($x+$c) -y $y } write-host $lineCharacter -NoNewline } } function Add-ConsoleBox{ param( [Parameter(Mandatory)][ValidateRange(0,400)] [int]$x, [Parameter(Mandatory)][ValidateRange(0,400)] [int]$y, [ValidateRange(1,400)] [int]$width = 1, [ValidateRange(1,400)] [int]$height = 1, [char] $lineCharacter = [char] $UnicodeBlocks.LIGHTSHADE ) Add-ConsoleLine -x $x -y $y -lineLength $width Add-ConsoleLine -x $x -y ($y+$height-1) -lineLength $width Add-ConsoleLine -x $x -y $y -lineLength $height -vertical $true Add-ConsoleLine -x ($x +$width-1) -y $y -lineLength $height -vertical $true } function ClearPix{ param( [int] $field = 1 ) $winwidth = $host.ui.rawui.WindowSize.Width $y = [Math]::Floor($field / $Width) + $Script:OffestY $x = [int]($field % $Width) + $Script:OffestX if(!$Debug) { Add-Pixel -x $x -y $y -Character ' ' } } function DrawPix{ param( [int] $field = 1 ) $winwidth = $host.ui.rawui.WindowSize.Width $y = [Math]::Floor($field / $Width) + $Script:OffestY $x = [int]($field % $Width) + $Script:OffestX if(!$Debug) { Add-Pixel -x $x -y $y -Character $UnicodeBlocks.FULLBLOCK } } function RedrawField{ for($i=0; $i -le ($Width*$Height-1); $i++){ if( $Field[$i] ){ DrawPix $i } else { ClearPix $i } } } function Clear-Stone{ param ( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang, [Parameter(Mandatory)] [int] $f ) #$host.ui.rawui.ForegroundColor = $Script:forgroundColor $Field[$Stones[$index][$ang].data[0]+$f]=$false ClearPix -field ($Stones[$index][$ang].data[0]+$f) $Field[$Stones[$index][$ang].data[1]+$f]=$false ClearPix -field ($Stones[$index][$ang].data[1]+$f) $Field[$Stones[$index][$ang].data[2]+$f]=$false ClearPix -field ($Stones[$index][$ang].data[2]+$f) $Field[$Stones[$index][$ang].data[3]+$f]=$false ClearPix -field ($Stones[$index][$ang].data[3]+$f) #$host.ui.rawui.ForegroundColor = $Script:backgroundColor } function Set-Stone{ param ( [Parameter(Mandatory)] [int] $index , [Parameter(Mandatory)] [int] $ang , [Parameter(Mandatory)] [int] $f ) #$host.ui.rawui.ForegroundColor = $Script:forgroundColor $Field[$Stones[$index][$ang].data[0]+$f]=$true DrawPix -field ($Stones[$index][$ang].data[0]+$f) $Field[$Stones[$index][$ang].data[1]+$f]=$true DrawPix -field ($Stones[$index][$ang].data[1]+$f) $Field[$Stones[$index][$ang].data[2]+$f]=$true DrawPix -field ($Stones[$index][$ang].data[2]+$f) $Field[$Stones[$index][$ang].data[3]+$f]=$true DrawPix -field ($Stones[$index][$ang].data[3]+$f) # $host.ui.rawui.CursorSize = $csize #$host.ui.rawui.ForegroundColor = $Script:backgroundColor } function test-Stone{ Param ( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang , [Parameter(Mandatory)] [int] $f ) return ( -not ( $Field[$Stones[$index][$ang].data[0]+$f] -or $Field[$Stones[$index][$ang].data[1]+$f] -or $Field[$Stones[$index][$ang].data[2]+$f] -or $Field[$Stones[$index][$ang].data[3]+$f] ) ) } function Set-MoveStoneDown{ Param( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang, [Parameter(Mandatory)] [int] $x, [Parameter(Mandatory)] [int] $y #VAR ) [int] $pos = 0 if (($y+$Stones[$index][$ang].down) -lt ($Height-1)) { $pos=$x+$Lines[$y]; Clear-Stone -index $index -ang $ang -f $pos if (Test-Stone -index $index -ang $ang -f ($pos+$Width)) { Set-Stone -index $index -ang $ang -f ($pos+$Width) $y++ #VAR $Script:YPos = $y return $true } else { Set-Stone -index $index -ang $ang -f $pos } } return $FALSE } function Set-MoveStoneLeft{ Param( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang, [Parameter(Mandatory)] [int] $x, #VAR [Parameter(Mandatory)] [int] $y ) [int] $pos = 0 if (($x - $Stones[$index][$ang].left) -gt 0){ $pos =$x + $Lines[$y]; Clear-Stone -index $index -ang $ang -f $pos if(Test-Stone -index $index -ang $ang -f ($pos-1)){ Set-Stone -index $index -ang $ang -f ($pos-1) $x-- $Script:XPos=$x } else { Set-Stone -index $index -ang $ang -f $pos } } } function Set-MoveStoneRight{ Param( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang, [Parameter(Mandatory)] [int] $x, #VAR [Parameter(Mandatory)] [int] $y ) [int] $pos = 0 if(($x+ $Stones[$index][$ang].right) -lt ($Width-1)) { $pos =$x+$Lines[$y] Clear-Stone -index $index -ang $ang -f $pos if(Test-Stone -index $index -ang $ang -f ($pos+1) ) { Set-Stone -index $index -ang $ang -f ($pos+1) $x++ $Script:Xpos=$x } else { Set-Stone -index $index -ang $ang -f $pos } } } function Set-StoneRotateLeft{ param ( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang, [Parameter(Mandatory)][int] [int] $x, [Parameter(Mandatory)][int] [int] $y ) [int] $pos =0 $pos =$x+$Lines[$y] Clear-Stone -index $index -ang $ang -f $pos $a1 = ($ang-1) % 4 if(($x+ $Stones[$index][$a1].right -le $Width) -and ($x-$Stones[$index][$a1].left -ge 0) -and ($y+$Stones[$index][$a1].down -le $Height) -and ($y-$Stones[$index][$a1].up -ge 0) -and (test-Stone -index $index -ang $a1 -f $pos)){ $ang = ($ang-1) % 4 $Script:Angle = $ang Set-Stone -index $index -ang $a1 -f $pos } else { Set-Stone -index $index -ang $ang -f $pos } } function Set-StoneRotateRight{ param ( [Parameter(Mandatory)] [int] $index, [Parameter(Mandatory)] [int] $ang,#VAR [Parameter(Mandatory)][int] [int] $x, [Parameter(Mandatory)][int] [int] $y ) [int] $pos =0 $a1 = ($ang-1) % 4 $pos =$x+$Lines[$y] Clear-Stone -index $index -ang $ang -f $pos if(($x+ $Stones[$index,($ang+1) % 4].right -le $Width) -and ($x-$Stones[$index,($ang+1) % 4].left -ge 0) -and ($y+$Stones[$index,($ang+1) % 4].down -le $Height) -and ($y-$Stones[$index,($ang+1) % 4].up -ge 0) -and (test-Stone -index $index -ang $a1 -f $pos)){ $ang = ($ang+1) % 4 $Script:Angle = ang Set-Stone -index $index -ang $a1 -f $pos } else { Set-Stone -index $index -ang $ang -f $pos } } Function Set-Tables{ for($i =0; $i -le ($Height-1);$i++){ $Lines[$i] = $i*$Width } for($i =0; $i -le ($Height*$Width-1);$i++){ $Field[$i] =$false } } function Test-Line{ param( [Parameter(Mandatory=$true)] [int] $line ) [int] $i = 0 for($i = $line; $i -le ($line+$Width-1);$i++){ if( -not($Field[$i])){ return $false } } Return $true } function Clear-Line{ param( [int] $line ) for($line = $line-1; $line -ge 0 ;$line--){ $Field[$line+$Width]=$Field[$line] } for($line = $Width-1; $line -ge 0 ;$line--){ $Field[$line] = $false } } #$Debug=$true function Set-Fall{ if(! $AllDone){ if( $Wait -le 0){ if(! (set-MoveStoneDown -index $Stone -ang $Angle -x $XPos -y $YPos)){ $Dowas = $true if (($YPos -gt 0) -AND (Test-Line -line ($Lines[$YPos-1]))) { Clear-Line -line ($Lines[$yPos-1]) $Dowas = $FALSE $Script:DoneLines++ } if (Test-Line -line ($Lines[$yPos])) { Clear-Line -line ($Lines[$yPos]) $Dowas = $FALSE $Script:DoneLines++ } if (($YPos -lt ($Height-1)) -AND (Test-Line -line ($Lines[$yPos+1]))) { Clear-Line -line ($Lines[$yPos+1]) $Dowas = $FALSE $Script:DoneLines++ } if (($YPos -lt ($Height-2)) -AND (Test-Line -line ($Lines[$yPos+2]))) { Clear-Line -line ($Lines[$yPos+2]) $Dowas = $FALSE $Script:DoneLines++ } if(!($Dowas)){ RedrawField #WriteLines END; } $Script:Stone = Get-Random -Minimum 0 -Maximum 7 $Script:Angle = Get-Random -Minimum 0 -Maximum 4 $Script:XPos =1 $Script:yPos=1 if(!(test-Stone -index $Stone -ang $Angle -f ($Lines[$yPos]+$XPos))){ $AllDone = $true $Dowas = $TRUE; } else { $Dowas = $false } $Wait = -1 } else { $Wait-- $Dowas = $false } } } } function Start-Game{ if(!($AllDone)){ if(!$Debug){ start-sleep -Milliseconds 80 if( ([Console]::KeyAvailable -and ([ConsoleKeyInfo] $key = [Console]::ReadKey())) ) { switch ($key.key) { 'LeftArrow' { Set-MoveStoneLeft -index $Stone -ang $Angle -x $XPos -y $YPos } 'RightArrow'{ Set-MoveStoneRight -index $Stone -ang $Angle -x $XPos -y $YPos } 'UpArrow' { Set-StoneRotateLeft -index $Stone -ang $Angle -x $XPos -y $YPos } 'DownArrow' { Set-Fall } 'Escape' { $Script:Exit = $true } } } #Clear Buffer while ([Console]::KeyAvailable){ $key = [Console]::ReadKey() } } else { #Debug Set-Fall Set-StoneRotateLeft -index $Stone -ang $Angle -x $XPos -y $YPos start-sleep -Milliseconds 200 } if($Wait -eq -1){ $Wait = 2 } else{ $Wait=1 } } } function Set-ASCIIArt{ param( [int] $x, [int] $y, [string[]] $art ) $art = $art -split '\n' for($i=0;$i -lt $art.Count;$i++){ set-ConsolePosition -x $x -y ($y+$i) Write-Host $art[$i] -NoNewline } } #New-PSConftris -width 11 -height 19 |