Category Archive: PowerShell
Recently, whilst messing with sprites and the Grrr framework, I got thinking about better graphics for games.
As PowerShell is very slow at doing console atomic write operations, a game should really have fewer, larger sprites. I then thought about ASCII art, and wouldn’t it be great if PowerShell could convert existing images (jpg, png) and produce lines of text for use with Grrr’s create-image function.
So my morning’s work is a PowerShell script that does just that.
You can download it here: convert-image2text.ps1 (as a text file)
(If you’re reading this from the RSS feed, the link may be broken – open the blog page if so)
Unfortunately, it’s only monochrome. I had a lot of trouble getting a reasonable conversion of RGB or HSV to the console’s limited colour palette and character range, so in the end, I removed it.
The script uses System.Drawing and demonstrates one (a good?) way of adding an assembly to PowerShell.
Usage:
./convert-image2text.ps1 imagefile
[ -maxwidth nchars ] [-palette ascii | shade | bw ]
Here’s an example using the default -palette ascii option:

Here’s the same with the -palette shade option:

Both are from this source image (click to see full size):

[Updated 25 Jan 2007, well rewritten
]
Something I find myself doing a lot is getting a screen shot of a PowerShell console window and posting it some place. Unfortunately, its always a bitmap, and occasionally, I want it as formatted text.
Now, the console is readable via $host.ui.rawui.GetBufferContents, so I wrote a small(ish) script to do just that, outputting lines of html.
You can download the script here get-bufferhtml.ps1.
Put the script somewhere so you can run it by name.
By default, the script will grab lines from the top of the buffer up to, but not including the current line, so if you type in this sequence:
PS> get-bufferhtml > out.html
PS> get-date
PS> asdasda
PS> get-bufferhtml > out.html
You end up with this:
PS> get-bufferhtml > out.html
WARNING: There must be one or more lines to get
PS> get-date
25 January 2007 14:17:42
PS> asdasda
The term 'asdasda' is not recognized as a cmdlet, function, operable pr
ogram, or script file. Verify the term and try again.
At line:1 char:7
+ asdasda < < < <
Note that the first line produced a warning, the second showed the date, the third produced an error and the last command (not shown) produce the above.
That output was then just pasted into this blog entry.
Read on »
Some time ago, I wrote a Sudoku solver in Java, along with an editor, interactive hint mode, puzzle generator etc, but the project never got finished because of feature creep and I generally got a bit bored of it all.
This morning, I resurrected the project and implemented the solver in PowerShell.
It’s not the shortest solver in history as it has gone through some performance improvements, but it does work and unless you’ve got a really hard puzzle, it’s quite quick too.
Download the script from here: sudoku.ps1
There are sample puzzles here (simple) and here (very hard). They are simple text files with numbers separated by white space. A zero indicates a blank in the puzzle.
You run the script like this:
PS > ./sudoku.ps1 sample-puzzle.txt
Going to to try to solve this puzzle:
7 . 5 . 3 . 8 . 2
. . 2 8 . 1 4 . .
8 1 . . . . . 5 6
. 3 . 1 . 8 . 2 .
. . 1 . 7 . 9 . .
. 9 . 3 . 2 . 4 .
9 8 . . . . . 3 7
. . 3 9 . 4 5 . .
2 . 6 . 8 . 1 . 4
Solved!
Guesses 53 (9 were wrong)
Elapsed time 00:00:00.4850316
Result:
7 4 5 6 3 9 8 1 2
3 6 2 8 5 1 4 7 9
8 1 9 2 4 7 3 5 6
4 3 7 1 9 8 6 2 5
6 2 1 4 7 5 9 8 3
5 9 8 3 6 2 7 4 1
9 8 4 5 1 6 2 3 7
1 7 3 9 2 4 5 6 8
2 5 6 7 8 3 1 9 4
I welcome any hints on performance or algorithmic improvements. No C# inlining please, it’s a PowerShell project
The very hard puzzle above takes a very long time to solve. So long, in fact, that I gave up waiting for it. If there is anyone out there with space time and cpu cycles, please run it and let me know how long it takes
Update: I’ve heard from one person that it takes approx 1.2 days to solve. My original Java app, in contrast takes 4.1 seconds.
Update 2: It looks like I inspired Mark Sheppard to do a better job (ie, not brute force). His PowerShell script solves the hard puzzle in 12 seconds (9.3 seconds on my Mac). Well done!
Despite the title, this is not a rant
Grrr is a pet project of mine that came after the exploratory work with psinvaders. I was somewhat dissatisfied with myself for doing so much without seeing how else it could be done, especially with respect to drawing of images, animation, etc.
So what is Grrr? Grrr is a set of functions written in pure PowerShell that let you create playfields with scrolling viewports, draw lines and images, animate and move sprites, and generally be an inappropriate use of the technology.
The version of Grrr discussed in this article can be downloaded from here. Updated versions will appear on the downloads page.
To use, you write a script of your own and source it with a dot/period, like this:
. ./grrr.ps1
I suppose you could do this in your $profile, but I prefer to keep things self contained as PowerShell’s global scope can get very cluttered very fast.
Testing
In the Grrr distribution, there is a very mini unit test framework called psunit.ps1.
The script grrr-test.ps1 uses this to unit test grrr.ps1. Hurrah for test-driven development! The picture shows it in action. Click on it to see the full thing.
To run the test your self, type ./grrr-test.ps1 in the directory where this is unzipped.
Example scripts
There are three example scripts. Run them like he unit test script.
They are:
⁃ grrr-test-clock.ps1 – a simple script that shows back buffering and drawing lines
⁃ grrr-test-sprite.ps1 – shows animation of sprites… some controlled semi-manually, and one by a motion path
⁃ grrr-test-scramble.ps1 – show the use of tilemaps to produce the effect of paralax scrolling.
The latter is very slow and really shows up how poor PowerShell by itself performs.
Have a look at the code, play around with it, tell me it’s rubbish if you like
The next steps for this project are adding a proper game loop controller, with key event handling, fps throttling and a few more motion handlers and behaviours – I’d like for sprites to be able to look after themselves, eg respond to proximity of others, shoot things, detect walls, etc.
I also want to make it faster. Maybe with C# inlining, maybe by making these things cmdlets, maybe by doing it all in C# in a custom host application. Who knows.
In a previous post I said that I always like to try to write space invaders in every language that I learn. Well, PowerShell in the standard Windows console window looked like a great candidate so I set about the task in my spare time. My colleagues Richy King, Nik Crabtree and Brian Long joined in the efforts and between us, after 37 revisions, we came up with something that was:
a) Silly
b) Inappropriate use of PowerShell
c) Quite a bit of fun.
Download it here: psinvaders r94 Update: this version now includes sound.
Unpack the zip file, then from the directory where psinvaders.ps1 is, type ./psinvaders.ps1. Enjoy!
Any future updates may appear on the downloads page.
Here are screen shots of the play screen and the score advance table.
How it works
All the drawing is based on drawing ‘sprites’ on the console screen. No back buffering takes place, so when a sprite is drawn, it erases itself from its most recent position, updates the x,y value, the draws itself in the new position.
The drawing itself is done using [Console]::Write. Since writing this we discovered the joys of BufferCells, and one of the reasons for taking this project no further.
Reading the key events proved to be quite simple: we just check if a key event is available, then consume all the event types, maintaining the down/up state for movement keys and just observing down events for firing and putting in new credits.
The game is quite playable, speed-wise, because very few sprites are moved in the inner loop: the base, one space invader, and any bombs and missiles. This means that:
a) The game moves at a reasonable pace.
b) The alien block gets quicker as more are killed
c) An alien bomb will overdraw an lower alien until next time.
The rest of it is fairly basic game loop logic.
What’s next?
I’m done with psinvaders now. I’ve started working on a better framework for doing back-buffered drawing of sprites, images, tiled backgrounds and lines/points.
Currently, it’s pure PowerShell and unusably slow, but I may start doing some C# or JScript inlining to speed it up. Thanks for Lee Holmes for that inspiration.
Or maybe I’ll just wait for the anticipated performance inprovements in PowerShell 1.1
Oh dear, it seems that even though this is 2007, the most popular web browser on the planet (IE
Will change it over to olde worlde JPEGs later, but in the mean time, if you’re using Windows, do yourself a favour and install Firefox or IE7.
Update: I’m not entirely sure what the problem is here… this site looks fine with IE6 on Win2k, but not on IE6 on my Wife’s XP. IE7 looks fine. There appear to be known problems with IE and PNG alpha, and overlapping PNGs, but I don’t know.
I was going to start the new year with a positive note, but then I thought, lets get a PS1 pet hate out of the way first.
PowerShell is slow.
There are many ways to demonstrate this, but for this case I’m going to use a small snippet of code I found to render the mandelbrot set to the console window. It’s not my code and don’t know where it came from, but algorithm is fairly well known.
The code to demonstrate this is in a zip file here.
If you run ./mandel2.ps1 you get this pretty picture.
There is a Windows Scripting Host version. Run this with cscript mandel2.wsf.
There is a JScript.NET version. Compile it with JSC and or run the supplied one with ./mandel2.js.exe.
There is even a javascript-embedded-in-a-HTML-page version, just click on mandel2.html.
Now on my machine (a 2.66ghz quad core MacPro running XP in Parallels Desktop), I get these results:
| PowerShell |
1510 ms |
| Windows Scripting Host |
90 ms |
| JScript.NET |
160 ms |
| HTML (IE7) |
110 ms |
| HTML (Firefox 2) |
140 ms |
| HTML (Safari on OSX) |
103 ms |
OK, so the existing javascript engine in Windows (used by IE and WSF) are pretty good at this. Safari’s is pretty good (using KJS). So why is this brand spanking new language, PowerShell, so very poor?
It’s more than an order of magnitude slower than Microsoft’s previous attempt at a scripting environment!
This tardiness really shows itself in other inappropriate projects I’m working on in PS1. I really hope the PowerShell team at Microsoft address this for version 1.1 – maybe they should go speak to the jscript team.