0 'Set Up Variables and Draw Screen
  'Every time a variable is used instead of a constant, it saves bytes.
  'Of course, the variable will need to be used a minimum number of
  'times to make up for the bytes used to define the variable
W=40:	'Screen Width - Every time 
E=W*6: 'Six Lines worth of characters
F$="  ": 'Used anywhere two spaces are needed
B$=F$+F$: 'The Missiles are four characters wide
          'By using F$+F$ instead of "    ", I saved one byte.
E$=CHR$(27): 'The Escape Character
R$=E$+"p":	'Reverse On
S$=E$+"q":	'Reverse Off
S=1E6:	'Beginning Score
		'Scientific Notation for 100000 saves 3 bytes
CLS:		'Clear the Screen, leaving cursor at position 0
PRINT		'Start Printing on first line///
"  Math Command   {Code-C}2010 Curtis F Kaylor"
,	'One comma skips to beginning of next line
,,	'The first comma goes to column 14
	'The scond to column 0 of the next line	
"  [A]dd [S]ubtract [M]ultiply [D]ivide"
,	'Skip to next line
,	'Skip to column 14
"Space=Sound O"  'the O is the beginning of On or Off
	'I wanted it to say "Press Space to Turn Sound O"
	'but hit the 255 characters per line limit
,	'Skip to next line
,,	'Blank line
,B$	'Column 14 + 4 spaces = column 18
"{GRPH-T}{GRPH-Q}{GRPH-Q}{GRPH-Y}"	'the top of the missile silo
,	'Next Line
R$	'Reverse on
" Press Q to quit   "
S$	'Reverse Off
F$	'This is where the typed numbers will appear
R$	'Reverse on again
B$" SCORE:"B$B$	'Using B$ here save a 12 bytes
S$	'Reverse Off
	'Printing to the end of the last line would have scrolled
	the screen, so I printed to the second to last line, then
CHR$(11)	'Cursor home, and
E$"L"		'Insert Line

1 'This is the Main Menu Code
D=PEEK(63017)AND1:	'D controls the sound, 1=On and 0=Off
	'The value is POKEd so that it will be preserved between RUNs,
	'including those used by Q=Quit
PRINT@187,MID$("n ff",D+D+1,2): 'If sound is currently off, print "On",
	'otherwise, print "Off". By preprinting the O, I saved a byte
FORK=0TO30:	'I am using the FOR loop to simulate a WHILE
K=RND(1):	'RND always starts with the same number after Boot up
		'so I'm calling it over and over again, to "churn" the		'pseudorandom number generator, since the amount of time it
		'takes the user to press a key is reasonably random
K=ASC(INKEY$+E$)-1: 'concatenate E$ because ASC("") causes an error
		'1 is subtracted because the NEXT will increment K 
NEXT:	'loop continues until SPACE or greater is pressed
K$=CHR$(K+32*(K>96)-29*(K=48)): 'If K is greater than 96, then a lower
	'case letter was pressed, so subtract 32 to make it upper case
	'if NUM lock is on, then pressing M will generate a 0, or K=48,
	;so add 29 to turn it into an M
IFK$="Q"THENMENU	'Q to quit at this point exits game
ELSEIFK$=" "THEN	'Space Bar
	D=1-D:	'Toggle Sound
	POKE63017,D: 'and save in RAM
	GOTO1		'then update screen and wait for next keypress
ELSEO=INSTR("ASMD",K$): 'Check for A, S, M, or D
IFO=0GOTO1	'If none of those then wait for next keypress
	'On/Off will get reprinted, but that won't hurt anything
ELSEO$=MID$("+-x/",O,1): 'Get the proper operator
M$="MJKLUIO"	'This is used to map the numeric keypad keys
	'if NUM is off

2 'Beginning of a Level
FORI=1TO4:	'play the Level Start Sound
SOUND6E3+1E3*(IAND1),D*20:	'frequency will be 6000, 3000, 6000, 3000
NEXT:		'Duration will be 20 is D=1 or 0 if D=0.
	'duration 0 causes no sound to be played, so D=0 turns off sound
PRINT@0,TAB(E);:	'TAB() clears all intervening characters, so this
	'clears the first six lines of the screen.
	'I originally used STRING$(E) but it builds a temporary string
	'and cause an OM error
M=25:	'This is the number of missiles in a level
D$=" {GRPH-h}{GRPH-h}  {GRPH-h}{GRPH-h} 	 'This is some sort of
     {GRPH-h}{GRPH-h}  {GRPH-h}{GRPH-h} ": 'typographical character
	'but it looks like houses to me, and two houses make a city
PRINTD$:	'print the left four cities
PRINT@263,D$;:	'then the right four
	'without obliterating the top of the missile silo
D$=D$+B$+B$+D$	'then build out the full 40 character strig
3 'Create a missile
Q=INT(RND(1)*4)*4-24*(RND(1)<.5): 'First RND picks  0, 4, 8, or 12
	'second RND adds either 0 or 24 to it,
	'so that missile exactly lines up with a city position 
P=Q:	'p is the @ position of the missile on the screen
A=INT(RND(1)*8)+1:  'A i the left operand
B=INT(RND(1)*8)+1:  'B is the left operand
	'both generate a number between 1 and 9 because 0 would
	'mess up the division calculation, and 0 is too easy anyway
C=A:	'C is the Correct Answer, preset to A for Subtract and Divide
T=A+B: 'Difficulty of the question, added to Score later
IFO=1THEN	'Addition
	C=T:	'Already calculated A+B so  use that to save 2 bytes
ELSEIFO=2THEN 'subtraction
	A=A+B: 'Set the left operand to the total, C was already set to A
ELSEIFO=3THEN 'Multiplication
	C=A*B:
ELSE		 'Must be Division
	A=A*B  'Set left operand to product, C already set to A
4 'now the missile falls and program checks for keypresses
PRINT@P,MID$(STR$(A),2)O$MID$(STR$(B),2);: 'Display the missile
	'I originally preset this to A$ for speed, but that required an
	'extra line and it turns out the code was already plenty fast
FORI=1TOW-V:  'Delay Loop 40 - Current Level
	'by level 39 the missile falls impossibly fast
K=ASC(INKEY$+E$): 'get a keypress
IFK>31THENK=K+32*(K>96): 'convert lowercase to uppercase
IFK=81THENRUN  'Q=Quit, which goes back to the main menu
ELSE
IFK=32THENN$="" 'a spacebar clears the entry (N$)
ELSE
Z=INSTR(M$,CHR$(K)) 'check for the letters in the numeri keypad
:K=Z+47*SGN(Z)-K*(Z=0):	'if Z<>0, set K to equivalent number
	'if Z=0, set K to K 
IFK>47ANDK<58THEN	'if a digit was pressed
	N$=N$+CHR$(K): 'add to entry
	Z=VAL(N$):	'get value of entry
	IFZ=CTHENI=E 'if entry is correct, set I to 240
		'this will force the delay loop to exit and
		'also flag that the correct answer was enterd
	ELSEIFZ>9THENN$="" 'if the answer is two digits, then it
		'must be wrong so it is cleared
5 PRINT@299,RIGHT$(F$+N$,2);: 'Print N$ right justified
NEXT: 'end of delay loop
PRINT@P,B$;: 'blank the missile on the current line
IFI<EANDP<ETHEN 'not the correct answer and missile not at bottom
	P=P+W:    'place missile on next line
	GOTO4	    'and redraw
ELSE
	PRINT@P,R$USING" ## ";C;: 'print correct answer at missile 
	IFP<ETHEN	'if missile not at bottom, then correct answer
		X=Q*6+9:  'horizontal center of missile
		Y=INT(P/W)*8+4:  'vertical center of missle
		LINE(119,47)-(X,Y),1: 'draw the laser
		FORI=3E3TO4E3STEP50: 'from freq 3000 to 4000
		SOUNDI,D:	'the laser sound (if D=1)
		NEXT:	
		LINE(119,47)-(X,Y),0: 'erase the laser
	ELSE	'missile at bottom, that's a miss
		FORI=1TO20:  'this is the closest I could get 
		SOUND16383-RND(1)*5E3,D:  'to white noise
		NEXT
6 PRINT@P,S$B$;:  'clear the missile area again
	'if at the bottom, then the city is automatically erased
	N$="": 'clear the answer
	PRINT@299,F$;:  'and the answer display
	IFP<ETHEN	'correct answer so update/display score
		GOSUB9
	ELSE	'miss
	MID$(D$,Q+1)=B$:  'clear city from D$
	IFINSTR(D$,"{GRPH-h}")=0THEN8 'if no cities left, game over
		'the THEN should really be a GOTO to be consistent
		'with the rest of the code, but it works
7 'Missile is now complete
M=M-1: 'decrement missile counter
IFMGOTO3 'if missiles left in level, then drop another one
ELSE	'otherwise the level is complete
V=V+1: 'during the level V is one less than the level
PRINT@92,"Level"V"Complete": 'this will get erased in line 2
T=0: 'This is left over and no longer necessary
FORI=2TOWSTEP4: 'step through the city positions
T=-(MID$(D$,I,2)="{GRPH-h}{GRPH-h}"): 'if position contains city
SOUND16383,9*T*D:	'make a noise if there was a city
PRINT@E+I*T-2,B$;:  'clear the city from the screen
T=T*10:	'cities are worth 10 bonus points 
		'actually they should be 20
GOSUB9	'update and display score
:NEXT:      'next city position
IFCGOTO2    'do the next level
		'this should be unconditional, but since C is never
		'0 it just happens to work
8 'game over
PRINT@96,R$"Game Over"S$;: 'display in reverse text
FORI=1E4TO16E3STEP3E3: 'game over sound effect
SOUNDI,D*W:
NEXT:
K$=INPUT$(1): 'wait for a keypress (displays blinking cursor)
RUN
9 'update and display score
S=S+T*(V+1): 'update score, adjusting for level
PRINT@313,R$RIGHT$(STR$(S),6)S$; 'right justify score so that it 
	'prints left filled with zeroes, this works because S is
	'initalized to 100000 and the leading 1 is cut off. This will
	'also cause the score to roll over if the user somehow exceeds
	'999999 points.
:RETURN
_