PowerShell Quick Script: Would You Like to Play a Game?

I teach a three-day course for System Administrators. I call it "Pragmatic PowerShell" - and that's exactly what it is about. Teaching administrators what they need to know about using PowerShell.

Of course, discoverability is a large part of the process. So we cover the standard stuff: Active Directory, DNS, DHCP, Exchange, and Lync. But what I find is that while most SysAdmins are comfortable with executing "one command, one result", most of them don't understand the concepts behind looping, functions, and conditional statements. And that's fine - if they weren't mainframe SysAdmins, they probably never had to write scripts before.

Note: Mainframe SysAdmins have been writing scripts for many decades; Job Control Language (JCL) on IBM mainframes, Work Flow Language (WFL) on Burroughs mainframes, Symbolic Stream Generator (SSG) on Univac mainframes, etc. etc.

So, it is important to cover these things to the students in ways that they can understand, and hopefully, to have a little fun with it at the same time.

Therefore, I went back and found a few of the simple computer games I used to play. In the 1970's and 1980's, many BASIC-based computer games were available, and these were commonly published in books and magazines and on BBSs (Bulletin Board Systems). People would buy the books or the magazines and then type the games into their computer. YES, actually type them!

I was six years-old when Neil Armstrong landed on the moon. I remember watching the TV transmission, sitting at my grandmother's house. Like most boys of my age, I wanted to grow up and become an astronaut! Alas, it was not to be.

But playing computer games, I never lost that desire. And it took me, a decade later, to study Physics in college.

"Lunar Lander", or "Lunar Exploration Module", or "Rocket" were common versions of programs that simulated a landing on the moon. Usually with some ASCII graphics.

Here is a PowerShell version (with some minor enhancements) of "Rocket".

Would you like to play a game?

 


###
### Rocket.ps1
###
### Algorithm is from the original Jim Storer "Lunar Lander" Basic 
### program from 1969
###
### Adapted from
### 	http://www.vintage-basic.net/bcg/rocket.bas
###	Retrieved on 2014-09-15
###
###	with a couple of minor bugfixes.
###
### Original program source came from "Basic Computer Games",
### first published in 1978. ISBN-10: 0894800523.
###
### This was one of the very first computer games that I ever
### played, a version in the late 1970's. Until graphics became
### more common (early 1980's), text games were the prevalent
### versions of all games. I can remember playing this game on DEC
### PDP computers (loaded from paper tape) and from original Apple
### computers (loaded from cassette tape).
###
### Michael B. Smith
### michael at TheEssentialExchange dot com
### September, 2014
###

###
### Newtonian one-dimensional physics says:
###
###	x' = x + vt + (1/2) * a * t * t
###
### Deriving this equation is trivial and left as an
### exercise for the reader. (Hint: use induction.)
###
### This program implements that algorithm, adjusted for
### the gravitational attraction of the moon.
###
### On the Earth, the gross value of gravitational
### acceleration is 32 feet/second/second.  The value of
### the gravitational acceleration on the moon is about
### one-sixth of that amount ( 16.6% ). This program
### uses a value of 5 feet/second/second. (Which is 
### close - the calculated value is 5.31 ft/sec/sec,
### which is only a 6.2% difference).)
###
### When originally written, floating point math was
### much more expensive than integer math. So most of
### the calculations will provide integer results.
### Newer versions of this program (based on lunar.bas
### and on lem.bas) use floating point math and will
### provide slightly more accurate results.
###
### However - you may find that this game is more
### challenging than you expect. :)
###

function GetYorN( [string] $prompt )
{
	while( 1 )
	{
		$answer = Read-Host $prompt
		if( $answer -eq "n" -or $answer -eq "no" )
		{

			return "n"
		}
		if( $answer -eq "y" -or $answer -eq "yes" )
		{
			return "y"
		}
	}	
}

function print-header
{
	" " * 30 + "Rocket"
	" " * 15 + "Creative Computing  Morristown, New Jersey"
	" "
	" "
	" "
	"Apollo Lunar Landing Simulation"
	"------ ----- ------- ----------"
	" "
}

function print-instructions
{
	$a = GetYorN "Do You Want Instructions (Yes or No)?"
	if( $a -eq "n" )
	{
		return
	}

	"You are landing on the moon and have taken over manual"
	"control 1,000 feet above a good landing spot. You have"
	"a downward velocity of 50 feet/sec. 150 units of fuel"
	"remain."
	" "
	"Here are the rules that govern your Apollo space-craft:"
	" "
	"[1] After each second, the height, velocity, and remaining"
	"    fuel will be reported via Digby, your on-board computer."
	"[2] After the report, a '?' will appear. Enter the number"
	"    of units of fuel you wish to burn during the next"
	"    second. Each unit of fuel will slow your descent by"
	"    1 foot/sec."
	"[3] The maximum thrust of your engine is 30 feet/sec/sec"
	"    or 30 units of fuel per second. If you enter a value"
	"    which exceeds 30, your value will be set to 30. If"
	"    you enter a value less than zero, your value will be"
	"    set to zero."
	"[4] When you contact the lunar surface, your descent engine"
	"    will automatically shut down and you will be given a"
	"    report of your landing speed and remaining fuel."
	"[5] If you run out of fuel, the '?' will no longer appear"
	"    but your second-by-second report will continue until"
	"    you contact the lunar surface."
	" "
}

function print-introduction
{
	"Beginning landing procedure.........."
	" "
	"G o o d  L u c k ! ! !"
	" "
	" "
	"SEC  FEET      SPEED     FUEL     PLOT OF DISTANCE"
	" "
}

function process-contact
{
	"*** Moon Contact ***"       ## 670 580
	$h = $h + 0.5 * ( $v1 + $v ) ## 680
	if( $b -eq 5 )
	{
		## time delta = height / velocity
		$d = $h / $v         ## 720 690
	}
	else
	{
		## time delta = -v + ( Sqrt( v*v + ( h * ( 10 - 2 * b ) ) ) / ( 5 - b )
		$d = ( -$v + [Math]::Sqrt( ( $v * $v ) + $h * ( 10 - 2 * $b ) ) ) / ( 5 - $b ) ## 700
	}

	$v1 = $v + ( 5 - $b ) * $d   ## 730 710
	"Touchdown at " + ( $t + $d ).ToString( 'N1' ) + " seconds."  ## 760
	"Landing velocity " + $v1.ToString( 'N1' ) + " feet/second."  ## 770
	$f.ToString() + " units of fuel remaining."                   ## 780

	if( $v1 -eq 0 )
	{
		"Congratulations! A perfect landing!!"                      ## 800
		"Your license will be renewed........Later."                ## 805
	}

	if( [Math]::Abs( $v1 ) -ge 2 )
	{
		"***** Sorry, but you blew it!!!! *****"                    ## 820
		"Everyone on the Lunar Landing Module is dead."
		"Appropriate condolences will be sent to the next of kin."  ## 830
	}

	" "                                                                 ## 840 
	" "
	" "
}

function print-status
{
	$str = "{0,-4:N0} {1,-8:N0}  {2,-8:N0}  {3,-7:N0}  I" -f $t, $h, $v, $f
	$str += ( "*" * ( [int] ( $h / 15 / 2 ) ) ) + "*"
	$str
}

###
###	Main
###

	print-header
	print-instructions

	while( 1 )
	{
		print-introduction      ## 390   860

		$t = 0	   ## 455	## time in seconds, at beginning of simulation
		$h = 1000  ## 455	## height in feet, at beginning of simulation
		$v = 50    ## 455	## velocity in feet per second, at beginning of simulation
		$f = 150   ## 455	## available fuel in arbitrary units, at beginning of simulation

		[bool] $done = $false

		while( $f -gt 0 -or !$done )
		{
			if( $f -gt 0 )
			{
				print-status                 ## 490 610

				$b = [int] ( Read-Host '?' ) ## 500
				if( $b -lt 0 )  { $b = 0  }  ## 510
				if( $b -gt 30 ) { $b = 30 }  ## 520
				if( $b -gt $f ) { $b = $f }  ## 530
			}

			$v1 = $v - $b + 5               ## 540 660
			$f = $f - $b                    ## 560
			$h = $h - 0.5 * ( $v1 + $v )    ## 570

			if( $h -le 0 )                  ## 580
			{                               ## 580
				$done = $true           ## 580
				break                   ## 580
			}                               ## 580

			$t = $t + 1                     ## 590
			$v = $v1                        ## 600

			if( $f -gt 0 )                  ## 610
			{                               ## 610
				continue                ## 610
			}                               ## 610

			if( $b -ne 0 )                  ## 615
			{                               ## 620
				"*** Out of fuel. ***"  ## 620
			}                               ## 620

			print-status                    ## 640

			$b = 0	                        ## 650
		}

		process-contact                         ## 670 - 840

		$a = GetYorN "Another mission (Yes or No)?"
		if( $a -eq "n" -or $a -eq "no" )
		{
			" "
			"Apollo Launch Control, signing out."
			"------ ------ -------- ------- ----"
			" "

			break  ## exit while(1) loop
		}
	}

The line numbers are from rocket.bas available from the link shown in the script source.

Follow me on Twitter at @essentialexch 

"WOULD YOU LIKE TO PLAY A GAME?" is a quote from "WarGames", starring a very young Matthew Broderick and Ally Sheedy, released in 1983.

Published Monday, September 29, 2014 6:31 PM by michael
Filed under:

Comments

Monday, September 29, 2014 7:18 PM by michael

# re: PowerShell Quick Script: Would You Like to Play a Game?

By the way, the fuel is not actually in arbitrary units. It is in "foot-pounds/second" multiplied by the weight of the module. But we don't know how heavy the module is, and as we burn fuel, the module becomes lighter. THAT is why we use this particular simplification in this program.