Microsoft Small Basic

Program Listing:
Embed this in your website
'***************************************************
' Small Basic Chomper (SBC) v 1.0
' Pacman-style game (BETA)
'Version 1.3.7.13 (online version)
'
' Software designed & written in BASIC by Anthony Yarrell (QBasicLover in the SB forums)
' Designed for Microsoft Small Basic 1.0
' March 2013
'
'Sprites created using Microsoft Paint
'Maze designed using Microsoft Excel
'
'My Research Sources:
'===============
'Sprite Management & Animation: "Visual Basic Game Programming for Teens", Jonathan S. Harbour;
'"Video Game Programming for Teens", Jonathan S. Harbour; Microsoft Small Basic Forums.
'Pacman Sprite Behavior: "The Pacman Dossier" http://home.comcast.net/~jpittman2/pacman/pacmandossier.html;
'Creating a Pacman Maze: http://stackoverflow.com/questions/622471/pacman-maze-in-java;
'
'***************************************************

'These variables control game play:
BRAND_NEW_GAME  = 0
PLAY_LEVEL      = 1
ADVANCE_LEVEL   = 2
REPLAY_LEVEL    = 3
GAME_OVER       = 4
gameState       = BRAND_NEW_GAME

'Initialization:
mazeScale       = 8 'Size of maze and distance between tiles. The game runs better when
                    'the mazeScale is 2 x the number of animation frames. I set the total animation frames
                    'to 4 because it gave the best performance while making the math easier.
gameScreenHeight = 375
gamescreenWidth = 225
monsterEatenCtr = 0      'Counts the number of monsters eaten in succession per energizer (4= bonus)
monsterBonusPts = 1000   'Pts given to player for eating 4 monsters in succession.
monsterPts      = 200    'Points player gets when he/she eats a monster.
monsterPtsMuliplier = 2  'Causes player to get bonus points when monsters are eaten in succession.
monstersEatenPerLevel = 0'Counts the number of mosters eaten per level. SBC gets a life if he eats 16 monsters per level.
gameSpeed      = 20'<-- Decrease if game runs too slowly
gameScore      = 0
gameLevel      = 0
pelletScore    = 25
energizerScore = 100
hasReached50K = "False"   'Flag to track if score reaches 50,000. Player gets extra life.
initialCountDownTime = 80 'Amount of time (cycles) the monsters stay "frightened"
globalCycleCtr = 0        'Used for syncronization and scheduling.

'**********************************
'Game loop
'***********************************
While (gameState <> GAME_OVER)
keyPressed = GraphicsWindow.LastKey

start = Clock.ElapsedMilliseconds
globalCycleCtr = globalCycleCtr + 1

If (gameState = BRAND_NEW_GAME) Then

 InitializeLookupTables()
 SetupGraphicsWindow()
 LoadBitmaps()
 InitializeSprites()
 SpriteArray[SBC][Lives] = 3
 gameState = ADVANCE_LEVEL

ElseIf (gameState = ADVANCE_LEVEL) Then
 globalCycleCtr = 0
 monstersEatenPerLevel = 0
 selectedRotation = 0 ' SBC goes through 4 max rotations.
 sbcDirection = Dir_R ' SBC moves to the right when level starts.
 SmallDelay()
 UpdateLevelState()
 ConstructGameElements()
 splashText = "L E V E L : "+ gameLevel
 DisplayLevelSplash()
 gameState = PLAY_LEVEL

ElseIf (gameState = PLAY_LEVEL) Then
 LeaveMonsterPenOneByOne()

  'Each sprite has a counter that it uses to track when it reaches a tile when moving though the maze.
  'When this counter reaches mazeScale, the sprite updates it info and draws.
  'Each sprite also has a spritespeed variable that it uses to set its movement speed. For example,
  'if spritespeed = 1 then updates will be done on each tick of the global counter. If spritespeed = 2 then
  'updates will be done on every 2nd tick, which will slow down that sprite, etc.

 For Sprites = firstSprite to lastSprite
   IF Math.Remainder(globalCycleCtr,SpriteArray[Sprites][spriteSpeed])=0 Then
     Update()
     Draw()
  EndIf
 Endfor

ElseIf (gameState = REPLAY_LEVEL) Then
 sbcDirection = Dir_R
 Sprites=1
 SpriteArray[SBC][Lives] = SpriteArray[sbc][Lives] - 1
 SpriteArray[SBC][State] = NORMAL
 globalCycleCtr = 0
 SmallDelay()
 ClearSpritesFromaze()
 InitializeSprites()
 PositionSpritesInMaze()
 DrawSprites() '<---BUG FIX. A call to DrawSprites( ) fixes an issue where SBC dissapears when level restarts.
 SmallDelay()
 gameState = PLAY_LEVEL


 If (SpriteArray[SBC][Lives] = 0) Then
  gameState = GAME_OVER
  splashText = "Game Over"
  DisplayLevelSplash()
 Endif

Endif

 delay = gameSpeed - (Clock.ElapsedMilliseconds-start)
 If (delay > 0) Then
  Program.Delay(delay)
 EndIf

KeyboardHandler()
EndWhile 'End of main state machine
'***********************************************************************************
Sub SmallDelay
 Program.Delay(500)
EndSub
'*******************************************************************************************
'Updates various games elements (eg maze color, game speed, etc) as the player advances to a new level:
'- gameSpeed: Overall speed of game. Game gets faster on each level.
'- initialCountDownTime: amount of time that monsters stay afraid. Decreases on each level.

Sub UpdateLevelState
  If math.Remainder(gameLevel,4) = 1 Then
    mazeBorderColor = "Cyan"
  ElseIf math.Remainder(gameLevel,4) = 2 then
    mazeBorderColor = "Red"
  Elseif math.Remainder(gameLevel,4) = 3 then
   mazeBorderColor  = "midnightblue"
  Elseif math.Remainder(gameLevel,4) = 0 then
    mazeBorderColor = "magenta"
  EndIf

  gameLevel = gameLevel + 1
  gameSpeed = gameSpeed - 2

  If (gameSpeed <= 0) Then
     gameSpeed = 0
  EndIf

  'Give the player a new life on levels 4 and 8:
  If (gameLevel = 4 Or gameLevel = 8) Then
     SpriteArray[sbc][Lives]=SpriteArray[sbc][Lives] + 1
  EndIf

  'Reduce the amount of time that the monsters stay "Frightened" as game progresses.
  'At much higher levels, the monsters won't stay frighened at all:
  initialCountDownTime = initialCountDownTime - 2
  If initialCountDownTime <= 0 Then
    initialCountDownTime = 0
  EndIf
EndSub
'*******************************************************************************************
'Dsplays a splash screen at the start of each level:

Sub DisplayLevelSplash
  GraphicsWindow.FontSize=14
  GraphicsWindow.BrushColor="white"
  l=Shapes.AddText(splashText)
  Shapes.Move(l,-200,205)
  Shapes.Animate(l,80,205,1000)
  SmallDelay()
  SmallDelay()
  SmallDelay()
  Shapes.Animate(l,-200,205,1000)
EndSub
'*******************************************************************************************
'The variables Dir_L, Dir_U, Dir_R, Dir_D are used as indexes into the xModifier and yModifier lookup tables.
'For example, xModifier[L] & yModifier[L] produces -1 and 0 respectively. When added to XY or RC values this will cause
'the sprite to go left, etc:

Sub KeyboardHandler

  Dir_L = 1
  Dir_U = 2
  Dir_R = 3
  Dir_D = 4

  If (keyPressed = "Left") Then
    sbcDirection = Dir_L
  Elseif (keyPressed = "Right") Then
    sbcDirection = Dir_R
  Elseif (keyPressed = "Up") Then
    sbcDirection = Dir_U
  Elseif (keyPressed = "Down") Then
    sbcDirection = Dir_D
  Elseif (keyPressed = "Escape") Then
    gameState = GAME_OVER
   Endif

EndSub
'*******************************************************************************************
Sub MoveSBC
'This routine moves SBC around the screen and causes SBC to stop at borders.It checks the maze
'locations adjacent to SBC's current location aganist the direction chosen by an arrow key press.
'If the new direction is possible (eg no borders in the way) SBC will go in the new direction. If
'the new direction is not possible, but the previous direction is, SBC will continue traveling in the
'direction it was moving in prior to the arrow key press. If neither direction is possible, SBC
'will stop moving:

If Sprites=SBC Then
canMoveInOldDirection = "False"
canMoveInNewDirection = "False"

'Get maze data ahead of SBC:
aheadDirX = SpriteArray[SBC][mazeCol] + SpriteArray[SBC][DX]
aheadDirY = SpriteArray[SBC][mazeRow] + SpriteArray[SBC][DY]
aheadDirData = Maze[aheadDirY][aheadDirX]

'Get maze data at location based on arrow key press:
newDirX = SpriteArray[SBC][mazeCol] + xModifier[SbcDirection]
newDirY = SpriteArray[SBC][mazeRow] + yModifier[SbcDirection]
newDirData = Maze[newDirY][newDirX]

'The mazeTokens array holds data that represent ares that are NOT blocked by borders.

For a = firstToken To lastToken
 If (mazeTokens[a] = newDirData) Then
   canMoveInNewDirection = "True"
   Goto _XIT_4Loop_Early
 EndIf
 If (mazeTokens[a] =  aheadDirData) Then
   canMoveInOldDirection = "True"
 EndIf
EndFor
_XIT_4Loop_Early:

'If the new direction is possible, go in new direction:
If (canMoveInNewDirection = "True") Then
  SpriteArray[SBC][DX] = xModifier[sbcDirection]
  SpriteArray[SBC][DY] = yModifier[sbcDirection]
  selectedRotation = rotationLookupTable[sbcDirection]
EndIf

'If neither old nor new directions are possible, come to a stop:
If (canMoveInNewDirection = "False" And canMoveInOldDirection = "False") Then
   SpriteArray[SBC][DX] = 0
   SpriteArray[SBC][DY] = 0
EndIf

SpriteArray[SBC][mazeCol] = SpriteArray[SBC][mazeCol] +  SpriteArray[SBC][DX]
SpriteArray[SBC][mazeRow] = SpriteArray[SBC][mazeRow] +  SpriteArray[SBC][DY]

EatPellet()
EndIf

EndSub
'*******************************************************************************************
Sub MoveMonstersTowardTarget
'This routine moves the monsters toward a target while allowing them to navigate around the maze
'borders. LL is a temporary array:

INVALID = 9999 '9999 is used as an invalid flag because the total distance across the maze is
'much lower than 9999 pixels. Later, when the code calculates the distance
'between source to target, anything marked 9999 won't be considered.

If (Sprites <> SBC) Then '<--SBC has his own movement routine (see MoveSBC)

 For a = 1 To 4 'step through XY/RC modifier table:
  SourceX = SpriteArray[Sprites][mazeCol] + xModifier[a]
  SourceY = SpriteArray[Sprites][mazeRow] + yModifier[a]
  targetX = SpriteArray[Sprites][targetCol]
  targetY = SpriteArray[Sprites][targetRow]

  For b = firstToken To lastToken

   'If the maze area being examined is not a border then calculate the distance from that maze area
   ' to the target using the Manhattan Distance formula (SourceX-targetCol)+(SourceY-targetRow)...
   If mazeTokens[b]=Maze[SpriteArray[Sprites][mazeRow] + yModifier[a]][SpriteArray[Sprites][mazeCol]+ xModifier[a]] Then
    LL[a] = 1+(math.Abs(Sourcex-targetx) + math.Abs(Sourcey-targety))
    Goto _XIT4

   '...otherwise mark it as invalid because it's a border :
   Else
    LL[a] = INVALID
   EndIf

  EndFor
  _XIT4:
 EndFor

  'For each maze area stored in the LL array, check to see if that was visited by the monster during previous
  'game loop cycle. If so mark it INVALID, then save the monster's current maze location
  'in VX, VY. These two steps will force the monster to travel in forward directions only (no reversing direction):
  For c = 1 To 4
    If SpriteArray[Sprites][mazeCol] + xModifier[c] = SpriteArray[Sprites][VX] Then
      If SpriteArray[Sprites][mazeRow] + yModifier[c] = SpriteArray[Sprites][VY] Then
        LL[c] = INVALID
      EndIf
    EndIf
  EndFor

  SpriteArray[Sprites][VX] = SpriteArray[Sprites][mazeCol]
  SpriteArray[Sprites][VY] = SpriteArray[Sprites][mazeRow]

  'Get the smallest number in temporary LL array, which will represent the direction to move in
  '1 = go left, 2 = go up, 3 = to right, 4 = go down:
  initialValue = LL[1]
  For ictr = 1 TO 4
   If initialValue >= LL[ictr] THEN
    initialValue = LL[ictr]
    elementfound = ictr
   EndIf
 EndFor
  'Set the movement direction. The xModifier/yModifier lookup tables eliminate the need for If/Then tests here:
  SpriteArray[Sprites][DX] = xModifier[elementfound]
  SpriteArray[Sprites][DY] = yModifier[elementfound]

  '** There is at least one circumstance where the monster finds a dead end - when the monster is in the
  'monster pen at level start. In this instance, the monster's L, D, & R adjacent areas will be invalid
  'due to being blocked by visible and invisible borders, and U is blocked because it will be added to the
  'VX/VY variables after the first game cycle. When this happens the VX/VY variables must be deleted
  'and on the next game cycle the monster will move out of dead end.
  '
 if LL[elementfound] = INVALID Then
  SpriteArray[Sprites][DX] = 0
  SpriteArray[Sprites][DY] = 0
  SpriteArray[Sprites][VX] = 0
  SpriteArray[Sprites][VY] = 0
 EndIf

  'Finally, move toward target:
  SpriteArray[Sprites][mazeCol] = (SpriteArray[Sprites][mazeCol] + SpriteArray[Sprites][dx])
  SpriteArray[Sprites][mazeRow] = (SpriteArray[Sprites][mazeRow] + SpriteArray[Sprites][dy])

EndIf

Endsub
'*******************************************************************************************
'Detects when sprites touch each other and when sprites enter special areas of the maze:
Sub CollisionDetect

If Sprites <> SBC Then
CheckRectangles()

 If isTouching = "True" Then
  isTouching = "False"
  'Monster dies if touching SBC while fightened and then monster returns to the monster pen:
  If SpriteArray[Sprites][State] = FRIGHT then
    ShowEatSplash()
    SpriteArray[Sprites][State] = DIE
    hasEatenMonster = "True"
    ScoreAndBonusManager()

  'SBC dies if touching monster when energizer is not active:
  ElseIf SpriteArray[Sprites][State] = CHASE then
    SpriteArray[SBC][State] = DIE
    gameState = REPLAY_LEVEL
  EndIf

  hasEatenMonster = "False"
 EndIf

 'When monster reaches monster pen, get body back and leave:
 If SpriteArray[Sprites][mazeCol] = MonsterPenX and SpriteArray[Sprites][mazeRow]= MonsterPenY Then
  If SpriteArray[Sprites][State] = DIE then
    SpriteArray[Sprites][State]  = EMERGE
   EndIf
  EndIf
  'When monster has left monster pen, go back to chasing SBC:
  If SpriteArray[Sprites][mazeCol] = emergeX and SpriteArray[Sprites][mazeRow] = emergeY Then
   If SpriteArray[Sprites][State] = EMERGE then
    SpriteArray[Sprites][State]  = CHASE
   EndIf
  EndIf
EndIf

'***BUG FIX: If a monster is in the monster pen when an energizer is eaten it will switch from whatever mode its in to
'FRIGHT mode. However, FRIGHT mode closes to doors when causes the monster to get trapped. This is a side effect -
'my intention was to keep the monsters from re-entering the pen prematurely. The fix below checks to see if a monster
'is in the pen and is the wrong mode. If so, it is switched to EMERGE mode so that it can properly emerge from the pen:
If (SpriteArray[Sprites][mazeCol] = MonsterPenX) and (SpriteArray[Sprites][mazeRow] = MonsterPenY) Then
   If (SpriteArray[Sprites][State] <> DIE) Or (SpriteArray[Sprites][State] <> EMERGE)  then
    SpriteArray[Sprites][State]  = EMERGE
   EndIf
  EndIf
EndSub
'*******************************************************************************************
'Sets the targets that the monsters will move towards:
Sub SetupMonsterTargets

IF (Sprites <>SBC) then

 'Sets ghosts to meander around the screen after SBC eats a power pellet:
 If SpriteArray[Sprites][State]  = FRIGHT Then
    SpriteArray[Sprites][targetRow] = math.GetRandomNumber(maxMazeRows)
    SpriteArray[Sprites][targetCol] = math.GetRandomNumber(maxMazeCols)

 'Sends the monsters back to monster pen after being eaten by SBC:
 ElseIf SpriteArray[Sprites][State] = DIE Then
    SpriteArray[Sprites][targetCol] = MonsterPenX
    SpriteArray[Sprites][targetRow] = MonsterPenY

 'Makes the monsters leave home base:
 ElseIf SpriteArray[Sprites][State] = EMERGE Then
    SpriteArray[Sprites][targetCol] = emergeX
    SpriteArray[Sprites][targetRow] = emergeY

 Elseif SpriteArray[Sprites][State] = CHASE Then

    If Sprites       =  RedMonster Then
      'Red monster pursues directly:
      SpriteArray[RedMonster][targetCol] = SpriteArray[SBC][mazeCol]
      SpriteArray[RedMonster][targetRow] = SpriteArray[SBC][mazeRow]

    ElseIf Sprites   =  PinkMonster Then
      'Pink monster tries to ambush (***TO DO: needs to be fixed***):
      SpriteArray[PinkMonster][targetCol] = SpriteArray[SBC][mazeCol] + (SpriteArray[SBC][DX]-1)
      SpriteArray[PinkMonster][targetRow] = SpriteArray[SBC][mazeRow] + (SpriteArray[SBC][DY]-1)

    ElseIf Sprites   =  OrangeMonster Then
      'Orange monster wanders around
      SpriteArray[OrangeMonster][targetCol] = math.GetRandomNumber(maxMazeCols)
      SpriteArray[OrangeMonster][targetRow] = math.GetRandomNumber(maxMazeRows)

    ElseIf Sprites   =  BlueMonster Then
      'Blue monster considers red monster's coordinates and SBC's coordinates wheb determining how to move:
      SpriteArray[BlueMonster][targetCol] = math.abs(SpriteArray[SBC][mazeCol] + SpriteArray[RedMonster][mazeCol])
      SpriteArray[BlueMonster][targetRow] = math.abs(SpriteArray[SBC][mazeRow] + SpriteArray[RedMonster][mazeRow])
    EndIf

EndIf

ENDIF

EndSub
'*******************************************************************************************
'Animation manager. The animation frames are stored in the ImageArray 2D array. This routine
'sets the indexes into that array. FrameCtr + Offset is used as the index into ImageArray.
'When Offset = zero all sprites go through the normal 4-cycle animation sequence. When
'offset = 5, the monsters turn purple (Fright Mode), and when the offset = 6 the monsters turn dark gray
'(Die Mode).

Sub SetupAnimationSequence

SpriteArray[SBC][LastFrame]   = 4
SpriteArray[SBC][FirstFrame]  = 1
SpriteArray[SBC][offset]      = 0

If (Sprites <> SBC) Then
  If SpriteArray[Sprites][State]      = CHASE Then
     SpriteArray[Sprites][offset]     = 0
     SpriteArray[Sprites][LastFrame]  = 4
     SpriteArray[Sprites][FirstFrame] = 1

  ElseIf SpriteArray[Sprites][State]  = FRIGHT Then
     SpriteArray[Sprites][offset]      = 5
     SpriteArray[Sprites][LastFrame]   = 5
     SpriteArray[Sprites][FirstFrame]  = 5

   ElseIf SpriteArray[Sprites][State] = DIE Then
    SpriteArray[Sprites][offset]      = 6
    SpriteArray[Sprites][LastFrame]   = 6
    SpriteArray[Sprites][FirstFrame]  = 6

   ElseIf SpriteArray[Sprites][State] = EMERGE Then
    SpriteArray[Sprites][offset]      = 0
    SpriteArray[Sprites][LastFrame]   = 4
    SpriteArray[Sprites][FirstFrame]  = 1
   Endif
 EndIf
 FlashMonsters()
EndSub
'*******************************************************************************************
Sub EatPellet

erasePelletFromScreen = "FALSE"
mazeData = Maze[(SpriteArray[SBC][mazeRow])][(SpriteArray[SBC][mazeCol])]

'Pellet = mazeToken[1]. Energizer = mazeToken[2]:
If (mazeData = mazeTokens[1] Or mazeData = mazeTokens[2]) Then
  Maze[(SpriteArray[SBC][mazeRow])][(SpriteArray[SBC][mazeCol])]=mazeTokens[0] 'empty this maze location
  pelletCount = pelletCount - 1
  erasePelletFromScreen = "True"
  gameScore = gameScore + pelletScore

  If (mazeData = mazeTokens[1]) Then
    gameScore = gameScore + pelletScore
  ElseIf (mazeData = mazeTokens[2]) then
    monsterEatenCtr=0
    SetMonstersToFrightState()
    gameScore = gameScore + energizerScore
    energizerTimer = ACTIVE
    energizerTime = initialCountDownTime
  EndIf

  If pelletCount <= 0 Then
    gameState = ADVANCE_LEVEL
  EndIf

EndIf

DoEnergizerTimer()
EndSub
'*******************************************************************************************
'Sets all monsters to FRIGHT state. VY & VX are zeroed out so that the monsters can switch
'directions. (MoveMonstersTowardTarget( ) normally restricts the monsters to forward-only movements):
Sub SetMonstersToFrightState
For ee = firstMonster to lastMonster
 if SpriteArray[ee][State] <> DIE then
  SpriteArray[ee][State] = FRIGHT
  shapes.SetOpacity(ImageArray[ee][5],100)
  SpriteArray[ee][VY] = 0
  SpriteArray[ee][VX] = 0
 EndIf
Endfor
EndSub
'*******************************************************************************************
'Sets all monsters to CHASE state. This is a bug fix to keep the monsters from switching out of DIE
'mode prematurely:
Sub MakeMonstersChase
 For mc = firstMonster to lastMonster
  If SpriteArray[mc][State] <> DIE then
   SpriteArray[mc][State] = CHASE
  EndIf
 Endfor
EndSub
'*******************************************************************************************
'Manages the count down timer that determines how long an energizer lasts.
Sub DoEnergizerTimer
If (energizerTimer = ACTIVE) Then
 If (energizerTime <> 0) Then
   energizerTime = energizerTime -1
 Else
  energizerTimer = INACTIVE
  monsterEatenCtr=0
  MakeMonstersChase()
 Endif
Endif

EndSub
'*******************************************************************************************
'Dispatch routine for erasing pellets/energizers from the screen:
Sub ErasePellet
  pelletColor = "black"
  pelletX = SpriteArray[SBC][screenX] + sWidth - mazeScale
  pelletY = SpriteArray[SBC][screenY] + sHeight - mazeScale
  DrawEnergizer()
EndSub
'*******************************************************************************************
'Draws/erases an energizer
Sub DrawEnergizer
  pelletSize = 6
  xOffset    = -6
  yOffset    = -6
  DP()
Endsub
'*******************************************************************************************
'Draws/erases a pellet
Sub DrawPellet
  pelletSize = 3
  xOffset    = -3
  yOffset    = -3
  DP()
EndSub
'*******************************************************************************************
Sub DP
  GraphicsWindow.BrushColor = pelletColor
  GraphicsWindow.FillEllipse(pelletX+xOffset, pelletY+yOffset, pelletSize, pelletSize)
EndSub
'*******************************************************************************************
'Removes sprites from the maze
Sub ClearSpritesFromaze
For r=firstSprite To lastSprite
  For t = 1 To 6
    Shapes.move(ImageArray[r][t],-100,-100)
  EndFor
EndFor

EndSub
'*******************************************************************************************
'Draws sprites on screen while advancing through the animation sequence setup by SetupAnimationSequence().

Sub DrawSprites

'To reduce flicker only draw sprites that are moving (SBC sometimes stops)
If SpriteArray[Sprites][dx]<>0 Or SpriteArray[Sprites][dy]<>0 Then

  'Get a reference to the current animation frame. We will hide it later:
  oldFrameCtr=SpriteArray[Sprites][FrameCtr]
  SpriteArray[Sprites][frameCtr]=SpriteArray[Sprites][frameCtr]+1+SpriteArray[Sprites][offset]

  'Advance to next frame and check to see if all frames have been displayed:
  If SpriteArray[Sprites][frameCtr]>SpriteArray[Sprites][lastFrame] then
    SpriteArray[Sprites][frameCtr]=SpriteArray[Sprites][firstFrame]
  Endif

  'Update screen coordinates:
  SpriteArray[Sprites][screenX]= SpriteArray[Sprites][screenX]+ SpriteArray[Sprites][DX] * 1
  SpriteArray[Sprites][screenY]= SpriteArray[Sprites][screenY]+ SpriteArray[Sprites][DY] * 1.5

  'Get reference to new animation frame and apply rotation (for SBC):
  newFrameCtr=SpriteArray[Sprites][frameCtr]
  if Sprites = SBC Then
    Shapes.Rotate(ImageArray[Sprites][newFrameCtr], selectedRotation)
  EndIf

  'Finally, hide previous frame and show new animation frame:
  shapes.Move(ImageArray[Sprites][oldFrameCtr],-20,-20)
  Shapes.Move(ImageArray[Sprites][newFrameCtr], SpriteArray[Sprites][screenX], SpriteArray[Sprites][screenY])

  EndIf

If erasePelletFromScreen = "True" Then
 ErasePellet()
EndIf

EndSub
'*******************************************************************************************
'This routine intializes general purpose global lookup tables.

Sub InitializeLookupTables

'The xModifier & yModifier arrays are used to modify the XY screen coordinates and RC maze coordinates:
xModifier[0] = 0 'Stop moving
xModifier[1] =-1 'Move Left (when added to X)
xModifier[2] = 0  '
xModifier[3] = 1 'Move Right (when added to X)
xModifier[4] = 0

yModifier[0] = 0 'Stop moving
yModifier[1] = 0  '
yModifier[2] =-1 'Move Up (when added to Y)
yModifier[3] = 0  '
yModifier[4] = 1  'Move Down (when added to Y)

'rotationLookupTable holds the rotation angles for SBC. SbcDirection is used as an index:
rotationLookupTable[1] = 180
rotationLookupTable[2] = 270
rotationLookupTable[3] = 0
rotationLookupTable[4] = 90

EndSub
'*******************************************************************************************
'Sets up sprite data structure and establishes related variables:

Sub InitializeSprites

'State variables for sprites:
DIE     = 0
NORMAL  = 1
CHASE   = 2
SCATTER = 3 '<--not implemented yet
FRIGHT  = 4
EMERGE  = 5

'State variables for energizer timer:
ACTIVE       = 1
INACTIVE     = 0

'The sprite data structure is a 2D array. These variables are indexes into the 2nd dimension of that array.
'(Dimension#1 slects the sprite, dimension #2 sets/gets properties of the particular sprite:

firstSprite  = SBC
lastSprite   = PinkMonster
firstMonster = RedMonster
lastMonster  = PinkMonster

'Variables for dimension #2:
screenX  = 1  'screen x coordinate
screenY  = 2  'screen y coordinate
mazeCol  = 3  'maze col
mazeRow  = 4  'maze row
DX       = 5  'x/col modifier
DY       = 6  'y/row modifier
targetCol= 7  'maze target col
targetRow= 8  'maze target row
VX       = 9  'visited maze col
VY       = 10 'visited maze row
State    = 11
Lives    = 12
FrameCtr = 13 'Index into ImageArray[ ][ ]
Offset   = 14
FirstFrame = 15
LastFrame  = 16
cycleCounter= 17
spriteSpeed= 18

'Initialize:
For spriteCtr = firstSprite To lastSprite
 SpriteArray[spriteCtr][FirstFrame] = 1
 SpriteArray[spriteCtr][LastFrame]  = 4
 SpriteArray[spriteCtr][FrameCtr]   = 4
 SpriteArray[spriteCtr][offset]     = 4
 SpriteArray[spriteCtr][DX]         = 0
 SpriteArray[spriteCtr][DY]         = 0
 SpriteArray[spriteCtr][VX]         = 0
 SpriteArray[spriteCtr][VY]         = 0
 SpriteArray[spriteCtr][targetCol]  = 0
 SpriteArray[spriteCtr][targetRow]  = 0
 SpriteArray[spriteCtr][State]      = CHASE
 SpriteArray[spriteCtr][spriteSpeed] = 1
 SpriteArray[spriteCtr][cycleCounter] = 1
Endfor
SpriteArray[SBC][State] = NORMAL
sbcDirection = Dir_R

EndSub
'*******************************************************************************************
Sub PositionSpritesInMaze

'Used for alignment hacks:
xxOffset= 0
yyOffset= 0

'Position SBC two tiles underneath Monster pen:
SpriteArray[SBC][mazeCol]             = 15
SpriteArray[SBC][mazeRow]             = 24

'Position Red Monster outside & above Monster pen:
SpriteArray[RedMonster][mazeCol]      = 12
SpriteArray[RedMonster][mazeRow]      = 12

'Blue, Orange and Pink Monsters inside Monster pen:
SpriteArray[BlueMonster][mazeCol]     = 12
SpriteArray[BlueMonster][mazeRow]     = 16
SpriteArray[OrangeMonster][mazeCol]   = 17
SpriteArray[OrangeMonster][mazeRow]   = 16
SpriteArray[PinkMonster][mazeCol]     = 14
SpriteArray[PinkMonster][mazeRow]     = 15

'Set correct screen positions:
For Sprites = firstSprite to lastSprite
  AdjustScreenCoords()
EndFor

EndSub
'*******************************************************************************************
'Using maze RC values, calculate screen XYs:
Sub AdjustScreenCoords
  SpriteArray[Sprites][screenX] = (SpriteArray[Sprites][mazeCol]) * mazeScale - mazeScale
  SpriteArray[Sprites][screenY] = (SpriteArray[Sprites][mazeRow]) * mazeScale * 1.5 - mazeScale
EndSub
'*******************************************************************************************
Sub LoadBitmaps
'The sprite data structure is a 2D array. These variables are indexes into the 2nd dimension of that array.
'(Dimension#1 slects the sprite, dimension #2 sets/gets properties of the particular sprite.

'Variables to select the sprites (dimension #1 of SpriteArray):
SBC           = 1
RedMonster    = 2
BlueMonster   = 3
OrangeMonster = 4
PinkMonster   = 5

sWidth  = mazeScale * 2
sHeight = mazeScale * 2

'ImageArray is a 2D array that holds references to the bitmaps used by the sprites. Dimension #1 is used
'to select the sprite, dimension #2 is used to select the bitmap.

'Load bitmaps for normal animation sequence:
filePath = Program.Directory +"\"
'SBC animation frames
ImageArray[SBC][1]=shapes.addimage("http://farm9.staticflickr.com/8240/8528887960_413fda8a5a_t.jpg")
ImageArray[SBC][2]=shapes.addimage("http://farm9.staticflickr.com/8379/8528887958_f8f6d3e534_t.jpg")
ImageArray[SBC][3]=shapes.addimage("http://farm9.staticflickr.com/8520/8527774169_b73baef828_t.jpg")
ImageArray[SBC][4]=shapes.addimage("http://farm9.staticflickr.com/8379/8528887958_f8f6d3e534_t.jpg")

'Red Monster animation frames
ImageArray[RedMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")
ImageArray[RedMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")
ImageArray[RedMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")
ImageArray[RedMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")

'Blue Monster animation frames
ImageArray[BlueMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")
ImageArray[BlueMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")
ImageArray[BlueMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")
ImageArray[BlueMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")

'Orange Monster animation frames
ImageArray[OrangeMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")
ImageArray[OrangeMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")
ImageArray[OrangeMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")
ImageArray[OrangeMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")

'Pink Monster animation frames
ImageArray[PinkMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")
ImageArray[PinkMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")
ImageArray[PinkMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")
ImageArray[PinkMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")

For s= 1 to 5

'Load bitmaps for FRIGHT Mode:
ImageArray[s][5]=shapes.addimage("http://farm9.staticflickr.com/8102/8528933134_d80645e3cc_t.jpg")

'Load bitmaps for DIE mode:
ImageArray[s][6]=shapes.addimage("http://farm9.staticflickr.com/8532/8528888036_85d4b2906d_t.jpg")
Shapes.SetOpacity(ImageArray[s][6],50)

Endfor

ClearSpritesFromaze()

EndSub

''*******************************************************************************************
'Loads maze pattern into maze array, counts the number of pellets added to maze, and gets the
'maze XY coordinates for special areas. Also creates and populates the mazeToken[ ] lookup table:
'
Sub LoadMaze

  M[1] =  "/------\/----------\/------\"
  M[2] =  "|......||..........||......|"
  M[3] =  "|*/--\.||./------\.||./--\*|"
  M[4] =  "|.(--).().(------).().(--).|"
  M[5] =  "|..........................|"
  M[6] =  "(-\./\./---\./\./---\./\./-)"
  M[7] =  "oo|.||.| |.||.| |.||.|oo"
  M[8] =  "oo|.||.(---).||.(---).||.|oo"
  M[9] =  "oo|.||.......||.......||.|oo"
  M[10] = "oo|.|(--\+/--)(--\+/--)|.|oo"
  M[11] = "--).(---)+(------)+(---).(--"
  M[12] = "LT+.+++++++E++++++++++++.+SR"
  M[13] = "--\./---\+/AAAAAAo+/---\./--"
  M[14] = "oo|.|/--)+|+Co+B+|+(--\|.|oo"
  M[15] = "oo|.||++++|+oo+o+|++++||.|oo"
  M[16] = "oo|.||+/\+|MCo+B+|+/\+||.|oo"
  M[17] = "oo|.()+||+(------)+||+().|oo"
  M[18] = "oo|.+++||++++++++++||+++.|oo"
  M[19] = "oo|./--)(--\+/\+/--)(--\.|oo"
  M[20] = "oo|.(------)+||+(------).|oo"
  M[21] = "oo|.......+++||+++.......|oo"
  M[22] = "oo|./---\./--)(--\./---\.|oo"
  M[23] = "/-).(---).(------).(---).(-\"
  M[24] = "|............++............|"
  M[25] = "|./--\./---\./\./---\./--\.|"
  M[26] = "|.|oo|.|/--).||.(--\|.|oo|.|"
  M[27] = "|.|oo|.||....||....||.|oo|.|"
  M[28] = "|*|oo|.||./--)(--\.||.|oo|*|"
  M[29] = "|.(--).().(------).().(--).|"
  M[30] = "|..........................|"
  M[31] = "(--------------------------)"
maxMazeRows = Array.GetItemCount(M)
maxMazeCols = Text.GetLength(M[1])

'mazeTokens[ ] hold tokens that represent walkable space in the maze:
firstToken = 0
lastToken = 2

mazeTokens[0]= "+"
mazeTokens[1]= "."
mazeTokens[2]= "*"

'Load the maze pattern into the maze[ ] [ ] array:
For rows = 1 To maxMazeRows
  For cols = 1 To maxMazeCols
    maze[rows][cols] = Text.GetSubText(M[rows], cols, 1)
    If maze[rows][cols] = mazeTokens[1] Or maze[rows][cols] = mazeTokens[2] Then
      pelletCount = pelletCount + 1
    EndIf

    'Special areas:
    If Maze[rows][cols] ="M" Then  'DIE mode target Monster Pen tile
       Maze[rows][cols] = mazeTokens[0]
       monsterpenX = cols
       MonsterPenY = rows
    ElseIf Maze[rows][cols] ="E" Then 'Emerge mode target tile
       Maze[rows][cols] = mazeTokens[0]
       emergeX = cols
       emergeY = rows
    ElseIf Maze[rows][cols] ="L" Then 'Left tunnel tile
       Maze[rows][cols] = mazeTokens[0]
       leftTunnelX = cols
       leftTunnelY = rows
    ElseIf Maze[rows][cols] ="R" Then 'Right tunnel tile
       Maze[rows][cols] = mazeTokens[0]
       rightTunnelX = cols
       rightTunnelY = rows
    ElseIf Maze[rows][cols] ="S" Then 'Right slow-down tunnel tile
       Maze[rows][cols] = mazeTokens[0]
       sld1X = cols
       sld1Y = rows
    ElseIf Maze[rows][cols] ="T" Then 'Right slow-down tunnel tile
       Maze[rows][cols] = mazeTokens[0]
       sld2X = cols
       sld2Y = rows
    EndIf

  EndFor
EndFor

'Delete the temporary array holding the maze structure:
M=""
EndSub
'*******************************************************************************************
'Steps through maze[ ] [ ] and draws the pattern on screen:
Sub DrawMaze

mazeBackgroundColor = "black"
GraphicsWindow.BackgroundColor= mazeBackgroundColor
x       = 0
y       = 0
mWidth  = mazeScale
mHeight = mazeScale
MMX     = (X + 1 * mWidth)
MMY     = (Y + 1.5 * mHeight)
MMH     = (1.5 * mHeight)
MMW     = (1 * mWidth)

For rows = 1 To maxMazeRows
  tempMMYrows = MMY*rows 'helps speed up draw operations a bit.
  For cols = 1 To maxMazeCols
    mazeData = Maze[rows][cols]

    GraphicsWindow.PenColor = mazeBorderColor
    GraphicsWindow.PenWidth = 2
    ' Upper Left corner:
    if mazeData     =     "/" then
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, mazeCol+MMW*cols, TempMMYrows)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, MMY+MMH*rows)

    'Upper Right corner:
    elseif mazeData =     "\" then
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows+MMH)

    'Lower Left corner:
    elseif mazeData =     "(" then
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows-MMH)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols+MMW, TempMMYrows)

    'Lower right corner:
    elseif mazeData =     ")" then
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows-MMH)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
      '
    'Vertical line:
    elseif mazeData =     "-" then
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols+MMW, TempMMYrows)
      '
     'Vertical line for top door
    elseif mazeData =     "A" then
      GraphicsWindow.PenColor="white"
      GraphicsWindow.PenWidth="1"
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols+MMW, TempMMYrows)
      '
    'Horizontal line:
    elseif mazeData =     "|" then
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows-MMH)
      GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows+MMH)

    'Pellet:
    elseif mazeData =     "." then
      pelletColor         = "white"
      pelletX=(cols * MMW)
      pelletY=(rows * MMY)
      DrawPellet()

    'Energizer:
    elseif mazeData =     "*" then
      pelletColor         = "white"
      pelletX=(cols * MMW)
      pelletY=(rows * MMY)
      DrawEnergizer()

    Endif
  EndFor
EndFor
EndSub
'*******************************************************************************************
'There are three invisible borders that keep the blue, pink and orange ghosts in the monster pen
'and also keeps the monsters from getting back in unless they are in EMERGE or DIE modes.
'The doors are "opened" by adding their tokens to the mazeToken[ ] array and extending the lastToken pointer.
'The doors are "closed" by resetting the lastToken pointer:
Sub CloseDoors
    lastToken = 2
EndSub
'*******************************************************************************************
Sub OpenLeftDoor
    mazeTokens[3] = "B"
    lastToken = lastToken + 1
EndSub
'*******************************************************************************************
Sub OpenRightDoor
    mazeTokens[3] = "C"
    lastToken = lastToken + 1
EndSub
'*******************************************************************************************
Sub OpenTopDoor
    mazeTokens[3] = "A"
    lastToken = lastToken + 1
EndSub
'*******************************************************************************************
'This routines causes the monsters to leave the monster pen one-by-one after a certain number of
'cycles have past. This done at game start, on each new level and when a level is replayed . The
'invisible "doors" open whenever the monsters are in EMERGE or DIE modes:
Sub LeaveMonsterPenOneByOne

If globalCycleCtr = 100 then
  SpriteArray[PinkMonster][state] = EMERGE
ElseIf globalCycleCtr = 200 Then
  SpriteArray[OrangeMonster][state] = EMERGE
Elseif globalCycleCtr = 400 Then
  SpriteArray[BlueMonster][state] = EMERGE
EndIf
EndSub
'*******************************************************************************************
'Dispatches update-related routines:
Sub Update
  SpriteArray[Sprites][cycleCounter]=SpriteArray[Sprites][cycleCounter]+1

  'Do updates when a sprite reaches a new tile. Distance between tiles is set by MazeScale:
  if (SpriteArray[Sprites][cycleCounter] > mazeScale) Then
     MoveSBC()
     SetupMonsterTargets()
     SetupSpriteSpeed()
     OpenCloseDoors()
     MoveMonstersTowardTarget()
     CheckGoThroughTunnels()
     SpriteArray[Sprites][cycleCounter]=1
     DisplayScore()
     DisplayLevel()
   EndIf

Endsub
'*******************************************************************************************
'Displaches draw-related routines:
Sub Draw
 SetupAnimationSequence()
 DrawSprites()
 CollisionDetect()
 CheckGoThroughTunnels()
Endsub
'*******************************************************************************************
'Ensures that sprites are moving at correct speed:
Sub SetupSpriteSpeed

  If SpriteArray[Sprites][state] = CHASE Then
    SpriteArray[Sprites][spriteSpeed] = 1
  ElseIf SpriteArray[Sprites][state] = FRIGHT Then
    SpriteArray[Sprites][spriteSpeed] = 2
  ElseIf SpriteArray[Sprites][state] = NORMAL Then
    SpriteArray[Sprites][spriteSpeed] = 1
  ElseIf SpriteArray[Sprites][state] = DIE Then
    SpriteArray[Sprites][spriteSpeed] = 1
  EndIf

EndSub
'*******************************************************************************************
'Can't speed up maze drawing, so black out the game screen and then construct maze and position
'bitmaps underneath the black cover:
Sub ConstructGameElements
 BlackOutGameScreen()
  LoadMaze()
  DrawMaze()
  DisplayLevel()
  DisplayLives()
  ClearSpritesFromaze()
  InitializeSprites()
  PositionSpritesInMaze()
 RemoveBlackScreen()
EndSub
'*******************************************************************************************
'Causes the monsters to flash briefly as a warning to the player that the monsters are about
'to swtich from Fright to Chase states:
'***BUG ??: This routine doesn't work well with Silverlight***

Sub FlashMonsters

If (energizerTimer = ACTIVE) And (SpriteArray[Sprites][State] = FRIGHT) Then
  If (energizerTime < 20) Then
    If (Math.Remainder(energizerTime,3)=0) Then
      shapes.SetOpacity(ImageArray[sprites][5],100) 'Visible
    Else
      shapes.SetOpacity(ImageArray[sprites][5],10) 'Faint
    EndIf
  EndIf
EndIf
EndSub
'*********************************************************************************
'Allows game to cage in or release monsters from monster pen:

Sub OpenCloseDoors
  If SpriteArray[Sprites][State] = CHASE Then
    CloseDoors()
  ElseIf SpriteArray[Sprites][State] = FRIGHT Then
    CloseDoors()
  ElseIf SpriteArray[Sprites][State] = NORMAL Then
    CloseDoors()
  ElseIf SpriteArray[Sprites][State] = DIE Then
    OpenLeftDoor()
    OpenRightDoor()
    OpenTopDoor()
  ElseIf SpriteArray[Sprites][State] = EMERGE Then
    OpenLeftDoor()
    OpenRightDoor()
    OpenTopDoor()
  EndIf
EndSub
'**************************************************************************
Sub ScoreAndBonusManager

If (hasEatenMonster = "True") Then
  monsterEatenCtr = monsterEatenCtr + 1
  gameScore = gameScore + monsterPts +(monsterEatenCtr * monsterPts)

  'Give player a bonus when all 4 monsters are eaten in succession:
  If monsterEatenCtr = 4 Then
     gameScore = gameScore + monsterBonusPts
     splashText=monsterBonusPts + "PT BONUS!"
     DisplayLevelSplash()
     monsterEatenCtr=0
  EndIf

  monstersEatenPerLevel = monstersEatenPerLevel + 1

  'Give player an extra life whenever 16 monsters are eaten per level:
  If monstersEatenPerLevel = 16 Then
     SpriteArray[sbc][lives] = SpriteArray[sbc][lives] + 1
     splashText="EXTRA LIFE ADDED!"
     monstersEatenPerLevel=0
     DisplayLevelSplash()
   EndIf
hasEatenMonster="False"
EndIf

If hasReached50K="False" Then
  If gameScore > 50000 Then
  hasReached50K="True"
  SpriteArray[sbc][lives] = SpriteArray[sbc][lives] + 1
  splashText="EXTRA LIFE ADDED!"
  DisplayLevelSplash()
  DisplayLives()
  EndIf
EndIf
EndSub
'*******************************************************************************
'Bounding Box collision detection routine from "Beginning Microsoft Small Basic", 9-30
Sub CheckRectangles

isTouching = "False"

Object1X=SpriteArray[sbc][screenX]
Object1Y=SpriteArray[sbc][screenY]
Object2X=SpriteArray[Sprites][screenX]
Object2Y=SpriteArray[Sprites][screenY]

If ((Object1X + 6 +sWidth - 6) > Object2X +6) Then
 If (Object1X +6 < (Object2X+6 + sWidth - 6)) Then
  If ((Object1Y+6 + sHeight - 6) > Object2Y+6) Then
   If (Object1Y+6 < (Object2Y+6 + sHeight - 6)) Then
     isTouching = "True"
   EndIf
  EndIf
 EndIf
EndIf

EndSub
'************************************************************************
'Allows sprites to travel through tunnels and causes the monsters to slow down at tunnel entrances:
sub CheckGoThroughTunnels

If Sprites <> SBC Then
 if (SpriteArray[Sprites][mazecol]=sld1X And SpriteArray[Sprites][mazeRow]=sld2Y) or (SpriteArray[Sprites][mazecol]=sld2X And SpriteArray[Sprites][mazeRow]=sld2Y) Then
  SpriteArray[Sprites][spriteSpeed]=4
 EndIf
endif

If SpriteArray[Sprites][mazeCol] = rightTunnelX and SpriteArray[Sprites][mazeRow] = rightTunnelY Then
  SpriteArray[Sprites][mazeCol] = leftTunnelX
  SpriteArray[Sprites][mazeRow] = leftTunnelY
  AdjustScreenCoords()

ElseIf SpriteArray[Sprites][mazeCol] = leftTunnelX and SpriteArray[Sprites][mazeRow] = leftTunnelY Then
  SpriteArray[Sprites][mazeCol] = rightTunnelX
  SpriteArray[Sprites][mazeRow] = rightTunnelY
  AdjustScreenCoords()

EndIf
EndSub
'********************************************************************
'Shows the per-monster points at the location where the monster was eaten:
Sub ShowEatSplash
  GraphicsWindow.BrushColor="white"
  GraphicsWindow.FontName="Arial"
  o=shapes.AddText(monsterPts +(monsterEatenCtr * monsterPts))
  osx = SpriteArray[Sprites][screenX] - sWidth
  osy = SpriteArray[Sprites][screenY] + sHeight
  Shapes.Move(o,osx,osy)
  SmallDelay()
  Shapes.Remove(o)
EndSub
 '*******************************************************************************************
sub SetupGraphicsWindow
    GraphicsWindow.Title="Small Basic Chomper"
    GraphicsWindow.Width= gamescreenWidth
    GraphicsWindow.Height=gameScreenHeight
    GraphicsWindow.CanResize="false"
    GraphicsWindow.BrushColor="white"
    GraphicsWindow.FontSize = 10
    GraphicsWindow.FontBold = "False"
    GraphicsWindow.DrawText(10,0,"SCORE: ")
    GraphicsWindow.DrawText(100,0,"LEVEL: ")
    GraphicsWindow.DrawText(180,0,"LIVES: ")
    scoreShape=Shapes.AddText(gameScore)
    livesShape=Shapes.AddText(SpriteArray[sbc][Lives])
    levelShape=Shapes.AddText(gameLevel)
    Shapes.Move(scoreShape,50,0)
    Shapes.Move(levelShape,135,0)
    Shapes.Move(livesShape,220,0)
  endsub
'*******************************************************************************************
Sub DisplayScore
  Shapes.SetText(scoreShape,gamescore)
EndSub
'*******************************************************************************************
Sub DisplayLives
  Shapes.SetText(livesShape,SpriteArray[sbc][lives])
EndSub
'*******************************************************************************************
Sub DisplayLevel
  Shapes.SetText(levelShape,gameLevel)
EndSub
'*******************************************************************************************
Sub BlackoutGameScreen
  GraphicsWindow.BrushColor="black"
  blkScreen = Shapes.AddRectangle(gamescreenWidth, gameScreenHeight)
Endsub
'*******************************************************************************************
Sub RemoveBlackScreen
  Shapes.Remove(blkScreen)
EndSub
Copyright (c) Microsoft Corporation. All rights reserved.