Treceți la conținutul principal

smallbasic sample code

' Asteroids Game
' Copyright (C) 2009, Jason T. Jacques <jtjacques@gmail.com>
' License: MIT license http://www.opensource.org/licenses/mit-license.php

' Game area controls
gameWidth  = 640
gameHeight = 480
backColor = "black"

' Window title
gameTitle = "Asteroids, Score: "

' Target frames per second
fps = 25

' Key controls
leftKey  = "Left"
rightKey = "Right"
forwardKey = "Up"
backKey = "Down"
fireKey = "Space"
pauseKey = "P"

' Asteroid (rock) settings
rockSpeed = 1
rockColor = "white"
rockMin = 20 ' small size rock
rockTypes = 3 ' number of rock sizes (multiples of small rock size)
initRocks = 5

' Ammo settings
ammoSpeed = 5
ammoColor = "white"
ammoLife = 60 ' moves before auto destruct
ammoMax = 10
ammoSize = 5

' Player settings
playerColor  = "white"
playerHeight = 30
playerWidth = 20
safeTime = 100 ' time player has to get out of the way on level up

' Point multiplier
pointsMultiply = 10

' Array name initialisation
rock = "rockArray"
rockAngle = "rockAngle"
rockSize = "rockSize"
ammo = "ammoArray"
ammoAngle = "ammoAngle"
ammoAge = "ammoAge"

rockCount = 0
ammoCount = 0

bigRock = ImageList.LoadImage("http://smallbasic.com/drop/Asteroids_BigRock.png")
medRock = ImageList.LoadImage("http://smallbasic.com/drop/Asteroids_MediumRock.png")
smlRock = ImageList.LoadImage("http://smallbasic.com/drop/Asteroids_SmallRock.png")
background = ImageList.LoadImage("http://smallbasic.com/drop/Asteroids_Sky.png")


' Start game
Init()
Play()


' Setup world
Sub Init
  GraphicsWindow.Hide()
  GraphicsWindow.Title = gameTitle + "0"
  GraphicsWindow.CanResize = "False"
  GraphicsWindow.Width = gameWidth
  GraphicsWindow.Height = gameHeight
  
  
  GraphicsWindow.BackgroundColor = backColor
  GraphicsWindow.BrushColor = backColor
  GraphicsWindow.DrawImage(background, 0, 0)
  
  LevelCheck()
  
  GraphicsWindow.PenColor = playerColor
  player = Shapes.AddImage("http://smallbasic.com/drop/Asteroids_Ship.png")
  ' player = Shapes.AddTriangle(playerWidth/2, 0, 0, playerHeight, playerWidth, playerHeight)
  Shapes.Move(player, (gameWidth - playerWidth) / 2, (gameHeight - playerHeight) / 2)
  playerAngle = 0
EndSub

' Main gane routine
Sub Play
  GraphicsWindow.Show()
  GraphicsWindow.KeyDown = ChangeDirection
  
  ' Main loop
  play = 1
  pause = 0
  While(play = 1)
    Program.Delay(1000/fps)
    If (pause = 0) Then 
      Move()
      CollisionCheck()
      AgeAmmo()
      LevelCheck()
    EndIf
  EndWhile
EndSub

' Read key event and act
Sub ChangeDirection
  If(GraphicsWindow.LastKey = rightKey) Then
    playerAngle = Math.Remainder(playerAngle + 10, 360)
  ElseIf(GraphicsWindow.LastKey = leftKey) Then
    playerAngle = Math.Remainder(playerAngle - 10, 360)
  ElseIf(GraphicsWindow.LastKey = forwardKey) Then
    playerSpeed = playerSpeed + 1
  ElseIf(GraphicsWindow.LastKey = backKey) Then
    playerSpeed = playerSpeed - 1
  ElseIf(GraphicsWindow.LastKey = fireKey) Then
    Fire()
  ElseIf(GraphicsWindow.LastKey = pauseKey) Then
    pause = Math.Remainder(pause + 1, 2)
  EndIf
  Shapes.Rotate(player, playerAngle)
EndSub

' Move all on screen items
Sub Move
  ' Move player
  x = Math.Remainder(Shapes.GetLeft(player) + (Math.Cos(Math.GetRadians(playerAngle - 90)) * playerSpeed) + gameWidth, gameWidth) 
  y = Math.Remainder(Shapes.GetTop(player) + (Math.Sin(Math.GetRadians(playerAngle - 90)) * playerSpeed) + gameHeight, gameHeight)
  Shapes.Move(player, x, y)
  
  ' Move rocks
  For i = 1 To rockCount
    x = Math.Remainder(Shapes.GetLeft(Array.GetValue(rock, i)) + (Math.Cos(Math.GetRadians(Array.GetValue(rockAngle, i) - 90)) * rockSpeed) + gameWidth, gameWidth) 
    y = Math.Remainder(Shapes.GetTop(Array.GetValue(rock, i)) + (Math.Sin(Math.GetRadians(Array.GetValue(rockAngle, i) - 90)) * rockSpeed) + gameHeight, gameHeight)
    Shapes.Move(Array.GetValue(rock, i), x, y)
  EndFor
  
  ' Move ammo
  For i = 1 To ammoCount
    x = Math.Remainder(Shapes.GetLeft(Array.GetValue(ammo, i)) + (Math.Cos(Math.GetRadians(Array.GetValue(ammoAngle, i) - 90)) * ammoSpeed) + gameWidth, gameWidth) 
    y = Math.Remainder(Shapes.GetTop(Array.GetValue(ammo, i)) + (Math.Sin(Math.GetRadians(Array.GetValue(ammoAngle, i) - 90)) * ammoSpeed) + gameHeight, gameHeight)
    Shapes.Move(Array.GetValue(ammo, i), x, y)
    Array.SetValue(ammoAge, i, Array.GetValue(ammoAge, i) + 1)
  EndFor
EndSub

' Check for collisions between onscreen items
Sub CollisionCheck
  ' Calculate player bounding box.
  px1 = Shapes.GetLeft(player) - ( (Math.Abs(playerWidth * Math.Cos(Math.GetRadians(playerAngle)) + playerHeight * Math.Sin(Math.GetRadians(playerAngle))) - playerWidth) / 2)
  py1 = Shapes.GetTop(player) - ( (Math.Abs(playerWidth * Math.Sin(Math.GetRadians(playerAngle)) + playerHeight * Math.Cos(Math.GetRadians(playerAngle))) - playerHeight) / 2)
  px2 = px1 + Math.Abs(playerWidth * Math.Cos(Math.GetRadians(playerAngle)) + playerHeight * Math.Sin(Math.GetRadians(playerAngle)))
  py2 = py1 + Math.Abs(playerWidth * Math.Sin(Math.GetRadians(playerAngle)) + playerHeight * Math.Cos(Math.GetRadians(playerAngle)))
  
  ' Re-order co-oridinates if they are the wrong way arround
  If(px1 > px2) Then
    tmp = px1
    px1 = px2
    px2 = tmp
  EndIf
  If(py1 > py2) Then
    tmp = py1
    py1 = py2
    py2 = tmp
  EndIf
  
  ' Check if each rock has hit something
  For i = 1 To rockCount
    ax1 = Shapes.Getleft(Array.GetValue(rock, i))
    ay1 = Shapes.GetTop(Array.GetValue(rock, i))
    ax2 = ax1 + Array.GetValue(rockSize, i)
    ay2 = ay1 + Array.GetValue(rockSize, i)
    
    
    ' Player collison
    If(playerSafe < 1) Then
      If ( (ax1 < px1 And ax2 > px1) Or (ax1 < px2 And ax2 > px2) ) Then
        If ( (ay1 < py1 And ay2 > py1) Or (ay1 < py2 And ay2 > py2) ) Then
          EndGame()
        EndIf
      EndIf
    EndIf
    
    
    ' Ammo collison
    For j = 1 to ammoCount
      bx1 = Shapes.Getleft(Array.GetValue(ammo, j))
      by1 = Shapes.GetTop(Array.GetValue(ammo, j))
      bx2 = bx1 + ammoSize
      by2 = by1 + ammoSize
      
      If ( (ax1 < bx1 And ax2 > bx1) Or (ax1 < bx2 And ax2 > bx2) ) Then
        If ( (ay1 < by1 And ay2 > by1) Or (ay1 < by2 And ay2 > by2) ) Then
          nextRemove = i
          RemoveRock()
          nextRemove = j
          RemoveAmmo()
        EndIf
      EndIf
    EndFor
    
  EndFor
  
  ' Decrease the time player is safe
  If (playerSafe > 0) Then
    playerSafe = playerSafe - 1
  EndIf
EndSub


' Add a new rock to the world
Sub AddRock
  ' Check if the next rock size/position has been specified
  If (nextSize <> 0) Then
    size = rockMin* nextSize
    x = Shapes.GetLeft(nextPosition)
    y = Shapes.GetTop(nextPosition)
    nextSize = 0
  Else
    ' Choose a random size and position
    size = rockMin * Math.GetRandomNumber(rockTypes)
    x = Math.GetRandomNumber(gameWidth - size)
    y = Math.GetRandomNumber(gameHeight - size)
  EndIf
  
  ' Draw the rock
  GraphicsWindow.PenColor = rockColor
  If size = 60 Then
    Array.SetValue(rock, rockCount + 1, Shapes.AddImage(bigRock))
  ElseIf size = 40 Then
    Array.SetValue(rock, rockCount + 1, Shapes.AddImage(medRock))
  Else
    Array.SetValue(rock, rockCount + 1, Shapes.AddImage(smlRock))
  EndIf
  rockCount = rockCount + 1
  
  Shapes.Move(Array.GetValue(rock, rockCount), x, y)
  Array.SetValue(rockAngle, rockCount, Math.GetRandomNumber(360))
  Array.SetValue(rockSize, rockCount, size)
EndSub

' Remove a rock from the world and update score
Sub RemoveRock
  removeSize = Array.GetValue(rockSize, nextRemove) / rockMin
  ' If not a mini rock
  If (removeSize > 1) Then
    ' ... add new rocks until we have made up for it being broken apart...
    While(removeSize > 0)
      nextSize = Math.GetRandomNumber(removeSize - 1)
      nextPosition = Array.GetValue(rock, nextRemove)
      removeSize = removeSize - nextSize
      AddRock()
    EndWhile
    ' And give a point for a 'hit'
    score = score + 1
  Else
    ' We've destroyed it - give some extra points and 
    score = score + 5
  EndIf
  
  ' Show updated score
  GraphicsWindow.Title = gameTitle + (score * pointsMultiply)
  
  ' Remove all references from the arrays
  Shapes.Remove(Array.GetValue(rock, nextRemove))
  For i = nextRemove To rockCount - 1
    Array.SetValue(rock, i, Array.GetValue(rock, i+1))
    Array.SetValue(rockAngle, i, Array.GetValue(rockAngle, i+1))
    Array.SetValue(rockSize, i, Array.GetValue(rockSize, i+1))
  EndFor
  Array.RemoveValue(rock, rockCount)
  Array.RemoveValue(rockAngle, rockCount)
  Array.RemoveValue(rockSize, rockCount)
  rockCount = rockCount - 1
EndSub

' Check if the player has completed the level, if so, level up
Sub LevelCheck
  If(rockCount < 1) Then
    nextSize = 0
    For i = 1 To initRocks
      AddRock()
    EndFor
    initRocks = initRocks + 1
    
    ' Give players some time to move out of the way
    playerSafe = safeTime
  EndIf
EndSub

' Add ammo to game
Sub Fire
  ' Remove additional ammo
  While(ammoCount > (ammoMax - 1))
    nextRemove = 1
    RemoveAmmo()
  EndWhile
  
  ' Add the ammo
  GraphicsWindow.PenColor = ammoColor
  ammoCount = ammoCount + 1
  Array.SetValue(ammo, ammoCount, Shapes.AddEllipse(ammoSize, ammoSize))
  Shapes.Move(Array.GetValue(ammo, ammoCount), (px1 + px2 - ammoSize) / 2, (py1 + py2 - ammoSize) / 2)
  Array.SetValue(ammoAngle, ammoCount, playerAngle)
EndSub

' Check ammo age
Sub AgeAmmo
  While (Array.GetValue(ammoAge, 1) > ammoLife)
    nextRemove = 1
    RemoveAmmo()
  EndWhile
EndSub

' Remove top Ammo
Sub RemoveAmmo
  Shapes.Remove(Array.GetValue(ammo, nextRemove))
  For i = nextRemove To ammoCount - 1
    Array.SetValue(ammo, i, Array.GetValue(ammo, i+1))
    Array.SetValue(ammoAngle, i, Array.GetValue(ammoAngle, i+1))
    Array.SetValue(ammoAge, i, Array.GetValue(ammoAge, i+1))
  EndFor
  Array.RemoveValue(ammo, ammoCount)
  Array.RemoveValue(ammoAngle, ammoCount)
  Array.RemoveValue(ammoAge, ammoCount)
  ammoCount = ammoCount - 1
EndSub

' Display simple end game message box
Sub EndGame
  play = 0
  Shapes.Remove(player)
  GraphicsWindow.ShowMessage("You scored " + (score * pointsMultiply) + " points. Thanks for Playing.", "Game Over!")
EndSub

start:
TextWindow.Title = "Binary to Decimal To Binary Converter [Amir Rke]"
TextWindow.Write("Enter Your Choice: [1 for binary to decimal] Or [2 four decimal to binary] ")
choice = TextWindow.ReadNumber()
If choice = 1 Then
  Goto start1
ElseIf choice = 2 Then
  Goto start2
EndIf
start1:
TextWindow.Write("Convert Binary To Decimal..."+Text.GetCharacter(10)+"Enter Binary Value : ")
binary = TextWindow.ReadNumber()
For bit_Count = 1 To Text.GetLength(binary)
  binaryNum = binaryNum + Text.GetSubText(binary,Text.GetLength(binary)-bit_Count+1,1)*Math.Power(2,bit_Count-1)
EndFor
TextWindow.ForegroundColor = "red"
TextWindow.Write("Decimal form : "+binaryNum+Text.GetCharacter(10))
TextWindow.ForegroundColor = "white"
binaryNum = ""
Goto start
start2:
count = 0
Bits = ""
TextWindow.Write(Text.GetCharacter(10)+"Convert Decimal To Binary..."+Text.GetCharacter(10)+"Enter Decimal Value : ")
N = TextWindow.ReadNumber()
temp = N
While N > 0
  Bits[count] = Math.Remainder(N,2)
  N = Math.Floor(N / 2)
  count = count + 1
EndWhile
TextWindow.ForegroundColor = "Green"
TextWindow.Write("Binary Form ")
For i = Array.GetItemCount(Bits) To 0 step - 1
    TextWindow.Write(Bits[i])
  EndFor 
  TextWindow.Write(Text.GetCharacter(10))
  TextWindow.ForegroundColor = "White"
Goto start
p = 0

GraphicsWindow.CanResize = 0
GraphicsWindow.Width = 260
GraphicsWindow.Height = 230
GraphicsWindow.Title = "Calculator v. 1.0 by Alex_2000" 

GraphicsWindow.BackgroundColor = GraphicsWindow.GetColorFromRGB(240, 240, 240)
GraphicsWindow.FontBold = "False"
GraphicsWindow.BrushColor = "Black"

m = Shapes.AddText("M")
Shapes.Move(m, 22, 62)
Shapes.HideShape(m)

t = Controls.AddTextBox(10, 10)
Controls.SetSize(t, 240, 22)
Controls.SetTextBoxText(t, "")

GraphicsWindow.BrushColor = "Red"
keyMC = Controls.AddButton("MC", 10, 95)
Controls.SetSize(keyMC, 35, 25)
keyMR = Controls.AddButton("MR", 10, 128)
Controls.SetSize(keyMR, 35, 25)
keyMS = Controls.AddButton("MS", 10, 161)
Controls.SetSize(keyMS, 35, 25)
keyMP = Controls.AddButton("M+", 10, 194)
Controls.SetSize(keyMP, 35, 25)
keyC = Controls.AddButton("C", 202, 58)
Controls.SetSize(keyC, 55, 25, )
keyCE = Controls.AddButton("CE", 139, 58)
Controls.SetSize(keyCE, 55, 25)
keyBackspase = Controls.AddButton("Backspase", 58, 58)
Controls.SetSize(keyBackspase, 70, 25)
keydelenie = Controls.AddButton("/", 181, 95)
Controls.SetSize(keydelenie, 35, 25)
keyumnogenie = Controls.AddButton("*", 181, 128)
Controls.SetSize(keyumnogenie, 35, 25)
keyminus = Controls.AddButton("-", 181, 161)
Controls.SetSize(keyminus, 35, 25)
keyplus = Controls.AddButton("+", 181, 194)
Controls.SetSize(keyplus, 35, 25)
keyravno = Controls.AddButton("=", 222, 194)
Controls.SetSize(keyravno, 35, 25)

GraphicsWindow.BrushColor = "Blue"
key7 = Controls.AddButton("7", 58, 95)
Controls.SetSize(key7, 35, 25)
key8 = Controls.AddButton("8", 99, 95)
Controls.SetSize(key8, 35, 25)
key9 = Controls.AddButton("9", 140, 95)
Controls.SetSize(key9, 35, 25)
key4 = Controls.AddButton("4", 58, 128)
Controls.SetSize(key4, 35, 25)
key5 = Controls.AddButton("5", 99, 128)
Controls.SetSize(key5, 35, 25)
key6 = Controls.AddButton("6", 140, 128)
Controls.SetSize(key6, 35, 25)
key1 = Controls.AddButton("1", 58, 161)
Controls.SetSize(key1, 35, 25)
key2 = Controls.AddButton("2", 99, 161)
Controls.SetSize(key2, 35, 25)
key3 = Controls.AddButton("3", 140, 161)
Controls.SetSize(key3, 35, 25)
key0 = Controls.AddButton("0", 58, 194)
Controls.SetSize(key0, 35, 25)
keyplusminus = Controls.AddButton("+/-", 99, 194)
Controls.SetSize(keyplusminus, 35, 25)
keytochka = Controls.AddButton(".", 140, 194)
Controls.SetSize(keytochka, 35, 25)
keysqrt = Controls.AddButton("sgrt", 222, 95)
Controls.SetSize(keysqrt, 35, 25)
keyprocent = Controls.AddButton("%", 222, 128)
Controls.SetSize(keyprocent, 35, 25)
keynax = Controls.AddButton("1/x", 222, 161)
Controls.SetSize(keynax, 35, 25)

Controls.ButtonClicked = click

Sub click
  Sound.PlayClick()
  If Controls.LastClickedButton = key0 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "0")) 
  ElseIf Controls.LastClickedButton = key1 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "1"))
  ElseIf Controls.LastClickedButton = key2 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "2"))
  ElseIf Controls.LastClickedButton = key3 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "3"))
  ElseIf Controls.LastClickedButton = key4 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "4"))
  ElseIf Controls.LastClickedButton = key5 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "5"))
  ElseIf Controls.LastClickedButton = key6 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "6"))
  ElseIf Controls.LastClickedButton = key7 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "7"))
  ElseIf Controls.LastClickedButton = key8 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "8")) 
  ElseIf Controls.LastClickedButton = key9 Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "9")) 
  ElseIf Controls.LastClickedButton = keytochka Then
    Controls.SetTextBoxText(t, Text.Append(Controls.GetTextBoxText(t), "."))
  ElseIf Controls.LastClickedButton = keyplusminus Then  
    If p = 0 Then
      Controls.SetTextBoxText(t, Text.Append("-", Controls.GetTextBoxText(t))) 
      p = 1 
    Else
      Controls.SetTextBoxText(t, Math.Abs(Controls.GetTextBoxText(t)))
      p = 0
    EndIf   
  ElseIf Controls.LastClickedButton = keyplus Then
    a = Controls.GetTextBoxText(t)
    Controls.SetTextBoxText(t, "")
    знак = "+"
  ElseIf Controls.LastClickedButton = keyminus Then
    a = Controls.GetTextBoxText(t)
    Controls.SetTextBoxText(t, "")
    знак = "-"
  ElseIf Controls.LastClickedButton = keyumnogenie Then
    a = Controls.GetTextBoxText(t)
    Controls.SetTextBoxText(t, "")
    знак = "*"
  ElseIf Controls.LastClickedButton = keydelenie Then
    a = Controls.GetTextBoxText(t)
    Controls.SetTextBoxText(t, "")
    знак = "/"
  ElseIf Controls.LastClickedButton = keysqrt Then
    Controls.SetTextBoxText(t, Math.SquareRoot(Controls.GetTextBoxText(t)))
  ElseIf Controls.LastClickedButton = keynax Then
    Controls.SetTextBoxText(t, 1/Controls.GetTextBoxText(t))
  ElseIf Controls.LastClickedButton = keyC Then  
    a = ""
    b = ""
    Controls.SetTextBoxText(t, "")
  ElseIf Controls.LastClickedButton = keyCE Then
    Controls.SetTextBoxText(t, "")  
  ElseIf Controls.LastClickedButton = keyBackspase Then
    Controls.SetTextBoxText(t, Text.GetSubText(Controls.GetTextBoxText(t), 1, Text.GetLength(Controls.GetTextBoxText(t))-1))
  ElseIf Controls.LastClickedButton = keyMP Or Controls.LastClickedButton = keyMS Then
    c = Controls.GetTextBoxText(t)
    Shapes.ShowShape(m)
  ElseIf Controls.LastClickedButton = keyMC Then  
    c = ""
    Shapes.HideShape(m)
  ElseIf Controls.LastClickedButton = keyMR Then
    Controls.SetTextBoxText(t, c)
  ElseIf Controls.LastClickedButton = keyprocent Then
    Controls.SetTextBoxText(t, (a * Controls.GetTextBoxText(t))/100)
  ElseIf Controls.LastClickedButton = keyravno Then
    b = Controls.GetTextBoxText(t)
    If знак = "+" Then
      Controls.SetTextBoxText(t, a + b)   
    ElseIf знак = "-" Then
      Controls.SetTextBoxText(t, a - b)  
    ElseIf знак = "*" Then
      Controls.SetTextBoxText(t, a * b)
    ElseIf знак = "/" Then
      If b = 0 Then
        Controls.SetTextBoxText(t, "Divide by zero is impossible!")
      Else 
        Controls.SetTextBoxText(t, a / b)  
      EndIf  
    EndIf
  EndIf
EndSub
gw = 600
gh = gw
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.CanResize = 0
GraphicsWindow.KeyDown = keydown
GraphicsWindow.Title="Analog Clock"
img_relogio = ImageList.LoadImage("http://nickm.hdfree.com.br/relogio.png")

Timer.Interval = 1000
Timer.Tick = update

h_raio = 155
m_raio = 205
s_raio = 245

Sub keydown
  last_key = GraphicsWindow.LastKey
  If(last_key = "F1")Then
    show_debug = 1    
  EndIf
  
EndSub



Sub update 
  GraphicsWindow.Clear()
  ' Shapes.AddImage(Program.Directory + "\relogio.png")  
  GraphicsWindow.DrawImage(img_relogio,0,0)
  'draw_numbers()
  hour = Clock.Hour
  minute = Clock.Minute
  second = Clock.Second
  
  GraphicsWindow.BrushColor="black"
  GraphicsWindow.FontSize = 25
  'GraphicsWindow.DrawRectangle(gw/2-80,gh/2+20,160,32)
  'time_txt = Shapes.AddText(Clock.Date)
  'Shapes.Move(time_txt,gw/2 - 78,gh/2 + 20)
  
  
  a_second = 360 / 60 * second   
  angulo = a_second * 0.0174532925199433
  sen = Math.Sin(angulo)
  cos = Math.Cos(angulo)  
  cat_o = sen * s_raio
  cat_a = cos * s_raio
  GraphicsWindow.PenColor= "red" 
  GraphicsWindow.PenWidth = "3" 
  GraphicsWindow.DrawLine(gw / 2,gh/2,(gw/2) + cat_o,( gh / 2) - cat_a)
  GraphicsWindow.PenWidth = "2" 
  
  
  a_minute = 360 / 60 * minute + (0.1 * second)    
  GraphicsWindow.PenColor= "black"  
  angulo = a_minute * 0.0174532925199433
  sen = Math.Sin(angulo)
  cos = Math.Cos(angulo)  
  cat_o = sen * m_raio
  cat_a = cos * m_raio
  GraphicsWindow.PenWidth = "4"
  GraphicsWindow.DrawLine(gw / 2,gh/2,(gw/2) + cat_o,( gh / 2) - cat_a)  
  GraphicsWindow.PenWidth = "2"
  
  If(hour < 12)Then
    a_hour = 360 / 12 * hour + (0.5 * minute)
  Else
    a_hour = 360 / 12 * hour + (0.5 * minute) - 360 
  EndIf
  
  angulo = a_hour * 0.0174532925199433
  sen = Math.Sin(angulo)
  cos = Math.Cos(angulo)  
  cat_o = sen * h_raio
  cat_a = cos * h_raio
  GraphicsWindow.PenWidth = "5"
  GraphicsWindow.DrawLine(gw / 2,gh/2,(gw/2) + cat_o,( gh / 2) - cat_a)  
  GraphicsWindow.PenWidth = "2"
  
  GraphicsWindow.BrushColor = "black"
  GraphicsWindow.FillEllipse(gw/2 - 10,gh/2-10,20,20)
  
  If(show_debug = 1)Then
    TextWindow.Left = GraphicsWindow.Left + 620
    TextWindow.Top = GraphicsWindow.Top
    TextWindow.Clear()
    size = 41
    TextWindow.Title="Analog Clock : Debug"
    TextWindow.WriteLine("+----------------------------------------+")
    TextWindow.WriteLine("| Analog Clock - v1.0 - NM Studio - 2010 |")    
    TextWindow.WriteLine("+----------------------------------------+")
    TextWindow.WriteLine("|                                        |")  
    TextWindow.Write("|Hour     : " + Clock.Hour)
    TextWindow.CursorLeft=size
    TextWindow.WriteLine("|")
    TextWindow.Write("|Minutes  : " + Clock.Minute)
    TextWindow.CursorLeft=size
    TextWindow.WriteLine("|")
    TextWindow.Write("|Seconds  : " + Clock.Second)
    TextWindow.CursorLeft=size
    TextWindow.WriteLine("|")
    TextWindow.WriteLine("|                                        |") 
    
    TextWindow.Write("|a_hour   : " + a_hour)
    TextWindow.CursorLeft=size
    TextWindow.WriteLine("|")
    TextWindow.Write("|a_minutes: " + a_minute)
    TextWindow.CursorLeft=size
    TextWindow.WriteLine("|")
    TextWindow.Write("|a_seconds: " + a_second)   
    TextWindow.CursorLeft=size
    TextWindow.WriteLine("|") 
    TextWindow.WriteLine("|                                        |") 
    TextWindow.WriteLine("+----------------------------------------+")
  EndIf
  
  
EndSub



'Initialise graphics window
GraphicsWindow.Hide()
gw = 800
gh = 600
GraphicsWindow.CanResize = "False"
GraphicsWindow.Top = (Desktop.Height-gh)/2
GraphicsWindow.Left = (Desktop.Width-gw)/2
GraphicsWindow.Title = "Bouncing balls with realistic collision physics"
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.BackgroundColor = "LightBlue"

'Reduce gw for options
gw = gw-200
GraphicsWindow.MouseDown = OnMouseDown

Start:

' Gravity, friction and attraction to mouse
grav = 0.0 ' 0 for none
fric = 0 ' 0 for none
follow = 0 'attract to mouse
attract = 0 'attract balls to each other
dt = 1 'timestep (speed)
shape = 0 '0:ball,1 square
elastic = 1 '1 fully elastic collisions
Colour = "Yellow"

'Initialise some balls
radius = 20
diam = 2*radius
nball = Math.Floor(gw/diam)
istart = "True"
reset()
ireset = "False"
istart = "False"
iend = "False"
iselect = "False"
ioptions = "False"

'Show window - an MS comment
GraphicsWindow.Show()

'Main loop
While ("True")
  If (ioptions) Then
    options()
    ioptions = "False"
  EndIf
  energy = 0.0
  isCollision = "False"
  If (iselect) Then
    For i = 1 To nball
      x = Xpos[i]
      y = Ypos[i]
      dist = (xm-x)*(xm-x)+(ym-y)*(ym-y)
      If (dist < radius*radius) Then
        u = 0
        v = 0
        Xvel[i] = u
        Yvel[i] = v
      EndIf
    EndFor
    iselect = "False"
  EndIf
  For i = 1 To nball
    update()
    move()
    u = Xvel[i]
    v = Yvel[i]
    energy = energy+(u*u+v*v)
  EndFor
  energy = dt*dt*energy
  energy = Math.Floor(energy)
  GraphicsWindow.BrushColor = "LightBlue"
  GraphicsWindow.FillRectangle(gw+15,560,190,20)
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawText(gw+65,560,"Energy "+energy)
  If (ireset) Then
    reset()
    ireset = "False"
  EndIf
  If (istart) Then
    Goto Start
  EndIf
  If (iend) Then
    Program.End()
  EndIf
'  If (isCollision) Then
'    Sound.PlayClick()
'  EndIf
  Program.Delay(10)
EndWhile

'Update ball positions
Sub update
  u = Xvel[i]
  v = Yvel[i]
  u = Math.Min(100,Math.Max(u,-100))
  v = Math.Min(100,Math.Max(v,-100))
  x = Xpos[i]+dt*u
  y = Ypos[i]+dt*v
  bounce()
  gravity()
  collision()
  attraction()
  Xpos[i] = x
  Ypos[i] = y
EndSub

'Check for edge bounces
Sub bounce
  If (x < radius) Then
    Xvel[i] = -Xvel[i]
    x = radius
  EndIf
  If (x > gw-radius) Then
    Xvel[i] = -Xvel[i]
    x = gw-radius
  EndIf
  If (y < radius) Then
    Yvel[i] = -Yvel[i]
    y = radius
  EndIf
  If (y > gh-radius) Then
    Yvel[i] = -Yvel[i]
    y = gh-radius
  EndIf
EndSub

'Check for collisions
Sub collision
  'Only check each pair once
  For j = i+1 To nball
    xi = x
    yi = y
    xj = Xpos[j]
    yj = Ypos[j]
    dx = xi-xj
    dy = yi-yj
    dist = Math.SquareRoot(dx*dx+dy*dy)
    If (dist < diam) Then
      isCollision = "True"
      'Get ball vectors
      ui = Xvel[i]
      vi = Yvel[i]
      uj = Xvel[j]
      vj = Yvel[j]
      'Move backwards (forwards if dt < 0)  in time until balls are just touching
      CoefA = (ui-uj)*(ui-uj)+(vi-vj)*(vi-vj)
      CoefB = 2*((ui-uj)*(xi-xj)+(vi-vj)*(yi-yj))
      CoefC = (xi-xj)*(xi-xj)+(yi-yj)*(yi-yj)-diam*diam
      If (CoefA = 0) Then
        t = -CoefC/CoefB
      Else
        If (dt >= 0) Then
          t = (-CoefB-Math.SquareRoot(CoefB*CoefB-4*CoefA*CoefC))/(2*CoefA)
        Else
          t = (-CoefB+Math.SquareRoot(CoefB*CoefB-4*CoefA*CoefC))/(2*CoefA)
        EndIf
      EndIF
      xi = xi+t*ui
      yi = yi+t*vi
      xj = xj+t*uj
      yj = yj+t*vj
      'Centre of momentum coordinates
      mx = (ui+uj)/2
      my = (vi+vj)/2
      ui = ui-mx
      vi = vi-my
      uj = uj-mx
      vj = vj-my
      'New centre to centre line
      dx = xi-xj
      dy = yi-yj
      dist = Math.SquareRoot(dx*dx+dy*dy)
      dx = dx/dist
      dy = dy/dist
      'Reflect balls velocity vectors in centre to centre line
      OB = -(dx*ui+dy*vi)
      ui = ui+2*OB*dx
      vi = vi+2*OB*dy
      OB = -(dx*uj+dy*vj)
      uj = uj+2*OB*dx
      vj = vj+2*OB*dy
      'Back to moving coordinates with elastic velocity change
      e = Math.SquareRoot(elastic)
      ui = e*(ui+mx)
      vi = e*(vi+my)
      uj = e*(uj+mx)
      vj = e*(vj+my)
      'Move to new bounced position
      xi = xi-t*ui
      yi = yi-t*vi
      xj = xj-t*uj
      yj = yj-t*vj
      'Set velocities
      Xvel[i] = ui
      Yvel[i] = vi
      Xvel[j] = uj
      Yvel[j] = vj
      'Set position
      Xpos[j] = xj
      Ypos[j] = yj
      x = xi
      y = yi    
    EndIf
  EndFor
EndSub

'Gravity and friction and follow mouse
Sub gravity
  xm = GraphicsWindow.MouseX-x
  ym = GraphicsWindow.MouseY-y
  dist = xm*xm+ym*ym
  dist = Math.Max(dist,radius*radius)
  'dist = dist*Math.SquareRoot(dist)
  u = Xvel[i]
  v = Yvel[i]
  fricscale = (1-fric/Math.SquareRoot(1+u*u+v*v))
  Xvel[i] = follow*xm/dist+fricscale*u
  Yvel[i] = follow*ym/dist+fricscale*v+grav
EndSub

'Attract-repell balls to each other
Sub attraction
  If (attract <> 0) Then
    For j = i+1 To nball
      xm = Xpos[j]-x
      ym = Ypos[j]-y
      dist = xm*xm+ym*ym
      dist = Math.Max(dist,radius*radius)
      'dist = dist*Math.SquareRoot(dist)
      Xvel[i] = attract*xm/dist+Xvel[i]
      Yvel[i] = attract*ym/dist+Yvel[i]
      Xvel[j] = attract*xm/dist+Xvel[j]
      Yvel[j] = -attract*ym/dist+Yvel[j]
    EndFor
  EndIf
EndSub

'Move ball
Sub move
  ball = balls[i]
  Shapes.Move(ball,x-radius,y-radius)
EndSub  

'Update options display
Sub options
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.DrawLine(gw,0,gw,gh)
  GraphicsWindow.BrushColor = "LightBlue"
  GraphicsWindow.FillRectangle(gw+10,10,190,gh-20)
  For i = 0 To 5
    GraphicsWindow.DrawLine(gw+10,100*i+10,gw+190,100*i+10)
  EndFor
  GraphicsWindow.DrawLine(gw+100,10,gw+100,510)
  
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawBoundText(gw+15,20,70,"Gravity")
  GraphicsWindow.DrawBoundText(gw+15,40,70,grav)
  GraphicsWindow.DrawBoundText(gw+15,120,70,"Friction")
  GraphicsWindow.DrawBoundText(gw+15,140,70,fric)
  GraphicsWindow.DrawBoundText(gw+15,220,70,"Follow")
  GraphicsWindow.DrawBoundText(gw+15,240,70,follow)
  GraphicsWindow.DrawBoundText(gw+15,320,70,"Size")
  GraphicsWindow.DrawBoundText(gw+15,340,70,radius)
  GraphicsWindow.DrawBoundText(gw+15,420,70,"Count")
  GraphicsWindow.DrawBoundText(gw+15,440,70,nball)
  GraphicsWindow.DrawBoundText(gw+15,520,170,"Click coloured options or a ball to stop it")
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.DrawBoundText(gw+15,580,50,"RESET")
  GraphicsWindow.DrawBoundText(gw+115,580,50,"QUIT")
  GraphicsWindow.DrawBoundText(gw+15,60,70,"More")
  GraphicsWindow.DrawBoundText(gw+15,160,70,"More")
  GraphicsWindow.DrawBoundText(gw+15,260,70,"More")
  GraphicsWindow.DrawBoundText(gw+15,360,70,"More")
  GraphicsWindow.DrawBoundText(gw+15,460,70,"More")
  GraphicsWindow.BrushColor = "Blue"
  GraphicsWindow.DrawBoundText(gw+15,80,70,"Less")
  GraphicsWindow.DrawBoundText(gw+15,180,70,"Less")
  GraphicsWindow.DrawBoundText(gw+15,280,70,"Less")
  GraphicsWindow.DrawBoundText(gw+15,380,70,"Less")
  GraphicsWindow.DrawBoundText(gw+15,480,70,"Less")
  
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawBoundText(gw+115,20,70,"Speed")
  GraphicsWindow.DrawBoundText(gw+115,40,70,dt)
  GraphicsWindow.DrawBoundText(gw+115,120,70,"Attraction")
  GraphicsWindow.DrawBoundText(gw+115,140,70,attract)
  GraphicsWindow.DrawBoundText(gw+115,220,70,"Elastic")
  GraphicsWindow.DrawBoundText(gw+115,240,70,elastic)
  GraphicsWindow.DrawBoundText(gw+115,320,70,"Colour")
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.DrawBoundText(gw+115,60,70,"More")
  GraphicsWindow.DrawBoundText(gw+115,160,70,"More")
  GraphicsWindow.DrawBoundText(gw+115,260,70,"More")
  GraphicsWindow.BrushColor = "Blue"
  GraphicsWindow.DrawBoundText(gw+115,80,70,"Less")
  GraphicsWindow.DrawBoundText(gw+115,180,70,"Less")
  GraphicsWindow.DrawBoundText(gw+115,280,70,"Less")
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.DrawBoundText(gw+115,340,70,"Red")
  GraphicsWindow.BrushColor = "Blue"
  GraphicsWindow.DrawBoundText(gw+115,360,70,"Blue")
  GraphicsWindow.BrushColor = "Yellow"
  GraphicsWindow.DrawBoundText(gw+115,380,70,"Yellow")
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawBoundText(gw+115,420,70,"Shape")
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.DrawBoundText(gw+115,440,70,"Circle")
  GraphicsWindow.DrawBoundText(gw+115,460,70,"Square")
EndSub

'Change settings
Sub OnMouseDown
  xm = GraphicsWindow.MouseX
  ym = GraphicsWindow.MouseY
  'Left column settings
  If (xm > gw+15 And xm < gw+85) Then
    If (ym > 60 And ym < 75) Then
      grav = grav+0.01
    EndIf
    If (ym > 80 And ym < 95) Then
      grav = grav-0.01
    EndIf
    If (ym > 160 And ym < 175) Then
      fric = fric+0.001
    EndIf
    If (ym > 180 And ym < 195) Then
      fric = fric-0.001
    EndIf
    If (ym > 260 And ym < 275) Then
      follow = follow+1
    EndIf
    If (ym > 280 And ym < 295) Then
      follow = follow-1
    EndIf
    If (ym > 360 And ym < 375) Then
      radius = radius+1
      diam = 2*radius
      ireset = "True"
    EndIf
    If (ym > 380 And ym < 395) Then
      radius = radius-1
      radius = Math.Max(1,radius)
      diam = 2*radius
      ireset = "True"
    EndIf
    If (ym > 460 And ym < 475) Then
      nball = nball+1
      ireset = "True"
    EndIf
    If (ym > 480 And ym < 495) Then
      nball = nball-1
      nball = Math.Max(1,nball)
      ireset = "True"
    EndIf
    If (ym > 580 And ym < 595) Then
      istart = "True"
    EndIf
  EndIf
  'Right column settings
  If (xm > gw+115 And xm < gw+185) Then
    If (ym > 60 And ym < 75) Then
      dt = dt+0.1
    EndIf
    If (ym > 80 And ym < 95) Then
      dt = dt-0.1
    EndIf
    If (ym > 160 And ym < 175) Then
      attract = attract+1
    EndIf
    If (ym > 180 And ym < 195) Then
      attract = attract-1
    EndIf
    If (ym > 260 And ym < 275) Then
      elastic = elastic+0.01
    EndIf
    If (ym > 280 And ym < 295) Then
      elastic = elastic-0.01
    EndIf
    If (ym > 340 And ym < 355) Then
      Colour = "Red"
      ireset = "True"
    EndIf
    If (ym > 360 And ym < 375) Then
      Colour = "Blue"
      ireset = "True"
    EndIf
    If (ym > 380 And ym < 395) Then
      Colour = "Yellow"
      ireset = "True"
    EndIf
    If (ym > 440 And ym < 455) Then
      Shape = 0
      ireset = "True"
    EndIf
    If (ym > 460 And ym < 475) Then
      Shape = 1
      ireset = "True"
    EndIf
    If (ym > 580 And ym < 595) Then
      iend = "True"
    EndIf
  EndIf
  'Select a ball
  If (xm < gw) Then
    iselect = "True"
  EndIf
  ioptions = "True"
EndSub

'Reset new balls
Sub reset
  mball = Array.GetItemCount(balls)
  For i = 1 To mball
    balls[i] = ""
    If (istart Or i > nball) Then
      Xpos[i] = ""
      Ypos[i] = ""
      Xvel[i] = ""
      Yvel[i] = ""
    EndIf
  EndFor
  GraphicsWindow.Clear()
  options()
  GraphicsWindow.BrushColor = Colour
  For i = 1 To nball
    If (shape = 0) Then
      ball = Shapes.AddEllipse(diam,diam)
    EndIf
    If (shape = 1) Then
      ball = Shapes.AddRectangle(diam,diam)
    EndIf
    balls[i] = ball
    If (istart Or i > mball) Then
      x = Math.GetRandomNumber(gw)
      y = Math.GetRandomNumber(gh)
      u = Math.GetRandomNumber(500)/100-3
      v = Math.GetRandomNumber(500)/100-3
      Xpos[i] = x
      Ypos[i] = y
      Xvel[i] = u
      Yvel[i] = v
    EndIf
  EndFor
EndSub
size = "medium" 'enter here the size of the palette - "small", "medium" or "large"

sid = 40 'sid = side of unit square, 40 pixels for "medium" size
If (size = "small") Then
  sid = 30
ElseIf (size = "large") Then
  sid = 50
EndIf
int=math.Floor(sid/10) 'int = lenght of interval
GraphicsWindow.Title = "Palette"
GraphicsWindow.Height = 12*(sid+int)+int
GraphicsWindow.Width = 22*(sid+int)+int
GraphicsWindow.CanResize="false"
GraphicsWindow.BackgroundColor = "black"
GraphicsWindow.Show()
GraphicsWindow.FontName="arial"
GraphicsWindow.FontSize=30
GraphicsWindow.Fontbold="true"

color[1]="IndianRed"
color[2]="LightCoral"
color[3]="Salmon"
color[4]="DarkSalmon"
color[5]="LightSalmon"
color[6]="Crimson"
color[7]="Red"
color[8]="FireBrick"
color[9]="DarkRed"
color[10]="Pink"
color[11]="LightPink"
color[12]="HotPink"
color[13]="DeepPink"
color[14]="MediumVioletRed"
color[15]="PaleVioletRed"
color[16]="LightSalmon"
color[17]="Coral"
color[18]="Tomato"
color[19]="OrangeRed"
color[20]="DarkOrange"
color[21]="Orange"
color[22]="Gold"
color[23]="Yellow"
color[24]="LightYellow"
color[25]="LemonChiffon"
color[26]="LightGoldenRodYellow"
color[27]="PapayaWhip"
color[28]="Moccasin"
color[29]="PeachPuff"
color[30]="PaleGoldenrod"
color[31]="Khaki"
color[32]="DarkKhaki"
color[33]="Lavender"
color[34]="Thistle"
color[35]="Plum"
color[36]="Violet"
color[37]="Orchid"
color[38]="Fuchsia"
color[39]="Magenta"
color[40]="MediumOrchid"
color[41]="MediumPurple"
color[42]="BlueViolet"
color[43]="DarkViolet"
color[44]="DarkOrchid"
color[45]="DarkMagenta"
color[46]="Purple"
color[47]="Indigo"
color[48]="SlateBlue"
color[49]="DarkSlateBlue"
color[50]="MediumSlateBlue"
color[51]="GreenYellow"
color[52]="Chartreuse"
color[53]="LawnGreen"
color[54]="Lime"
color[55]="LimeGreen"
color[56]="PaleGreen"
color[57]="LightGreen"
color[58]="MediumSpringGreen"
color[59]="SpringGreen"
color[60]="MediumSeaGreen"
color[61]="SeaGreen"
color[62]="ForestGreen"
color[63]="Green"
color[64]="DarkGreen"
color[65]="YellowGreen"
color[66]="OliveDrab"
color[67]="Olive"
color[68]="DarkOliveGreen"
color[69]="MediumAquamarine"
color[70]="DarkSeaGreen"
color[71]="LightSeaGreen"
color[72]="DarkCyan"
color[73]="Teal"
color[74]="Aqua"
color[75]="Cyan"
color[76]="LightCyan"
color[77]="PaleTurquoise"
color[78]="Aquamarine"
color[79]="Turquoise"
color[80]="MediumTurquoise"
color[81]="DarkTurquoise"
color[82]="CadetBlue"
color[83]="SteelBlue"
color[84]="LightSteelBlue"
color[85]="PowderBlue"
color[86]="LightBlue"
color[87]="SkyBlue"
color[88]="LightSkyBlue"
color[89]="DeepSkyBlue"
color[90]="DodgerBlue"
color[91]="CornflowerBlue"
color[92]="MediumSlateBlue"
color[93]="RoyalBlue"
color[94]="Blue"
color[95]="MediumBlue"
color[96]="DarkBlue"
color[97]="Navy"
color[98]="MidnightBlue"
color[99]="Cornsilk"
color[100]="BlanchedAlmond"
color[101]="Bisque"
color[102]="NavajoWhite"
color[103]="Wheat"
color[104]="BurlyWood"
color[105]="Tan"
color[106]="RosyBrown"
color[107]="SandyBrown"
color[108]="Goldenrod"
color[109]="DarkGoldenrod"
color[110]="Peru"
color[111]="Chocolate"
color[112]="SaddleBrown"
color[113]="Sienna"
color[114]="Brown"
color[115]="Maroon"
color[116]="White"
color[117]="Snow"
color[118]="Honeydew"
color[119]="MintCream"
color[120]="Azure"
color[121]="AliceBlue"
color[122]="GhostWhite"
color[123]="WhiteSmoke"
color[124]="Seashell"
color[125]="Beige"
color[126]="OldLace"
color[127]="FloralWhite"
color[128]="Ivory"
color[129]="AntiqueWhite"
color[130]="Linen"
color[131]="LavenderBlush"
color[132]="MistyRose"
color[133]="Gainsboro"
color[134]="LightGray"
color[135]="Silver"
color[136]="DarkGray"
color[137]="Gray"
color[138]="DimGray"
color[139]="LightSlateGray"
color[140]="SlateGray"
color[141]="DarkSlateGray"
color[142]="Black"

For i = 0 To 11
  For j = 1 To 12
    GraphicsWindow.brushcolor=color[i*12+j]
    GraphicsWindow.FillRectangle(int+i*(sid+int),int+(j-1)*(sid+int),sid,sid)
  Endfor
EndFor
GraphicsWindow.PenColor=" white"
GraphicsWindow.DrawRectangle(int+(i-1)*(sid+int),9*(sid+int)+int,sid,sid)
GraphicsWindow.DrawRectangle(12*(sid+int)+int,int,10*(sid+int)-int,10*(sid+int)-int)
GraphicsWindow.Mousemove = onmousemove

Sub onmousemove
  x = GraphicsWindow.MouseX
  y = GraphicsWindow.MouseY
  GraphicsWindow.BrushColor = "black"
  GraphicsWindow.FillRectangle(12*(sid+int)+int,10.5*(sid+int)+int,10*(sid+int)+int,1.5*sid)
  c = 12*Math.Floor(x/(sid+int))+1+Math.Floor(y/(sid+int))
  GraphicsWindow.BrushColor = color[c]
  GraphicsWindow.FillRectangle(12*(sid+int)+int,int,10*(sid+int)-int,10*(sid+int)-int)
  GraphicsWindow.BrushColor = "white"
  GraphicsWindow.DrawText(12*(sid+int)+int,10.5*(sid+int)+int,color[c])
EndSub
' Dart game   by NaochanON     
'  shape making  codes are made by Nonki_Takahashi's_Shapes 1.31  
GraphicsWindow.MouseDown=Onmousedown 
GraphicsWindow.MouseMove=Onmousemove
GraphicsWindow.Mouseup=Onmouseup 
Controls.ButtonClicked = OnButtonClicked
Resister()


While "true"
  If move="true" Then 
    Shoot()                                            '   Dart is throwed
    Hitcheck()                                         '   if  dart hit at target 
    Program.Delay(20)
  EndIf
endwhile

Sub Hitcheck
   if  shx<newxy["X"] And newxy["X"]<(shx+shape[1]["width"])*3/4  And shy<newxy["Y"] And newxy["Y"]<327  Then  '
    LX=(Shapes.GetLeft(shape[8]["obj"])-Shapes.GetLeft(shape[4]["obj"])-9)*2.5
    LY=(Shapes.Gettop(shape[8]["obj"])-Shapes.Gettop(shape[4]["obj"])-20)
    L=math.SquareRoot(LX*LX+LY*LY)
    If L<50/2 Then 
      SCR=100
    ElseIf 50/2<=L and L<115/2 then 
      SCR=50
    ElseIf 115/2<=L and L<190/2 then 
      SCR=25
    ElseIf 190/2<=L and L<250/2 then 
      SCR=10
    EndIf
    MM=MM+SCR   '  count up  goals
    Shapes.SetText(smsg," Throw "+NN+" times Hit !!!!  Score= "+SCR+ " Total= "+MM)
    Shapes.Animate(smsg,600,50,1000)
    score=MM
    return()
  ElseIf   600<newxy["Y"] then 
    Shapes.Zoom(shape[12]["obj"],1,0.15)              '  Eye   close
    return()
  EndIf   
endsub

Sub onbuttonclicked
  User= Controls.GetTextBoxText(userbox)
  Shapes_Init()
  init_Man()
  man_animate()
  basedata()
EndSub

Sub onmousemove
  If catch="true" Then 
    movexy="X="+ (GraphicsWindow.MouseX)+";Y="+(GraphicsWindow.MouseY)   ' Mouse (X1 ,Y1) position
    Shapes.Move(shape[8]["obj"],movexy["X"]-32,movexy["y"]-8)   ' pin
    Shapes.Move(shape[9]["obj"],movexy["X"]-12,movexy["Y"])     'pin body
    angle= Math.ArcTan( (movexy["Y"]-sxy["Y"])/(movexy["X"]-sxy["X"]-30) )  'sita= math.ArcTan((y1-y0)/(x1-x0))
    If angle<0 Then 
      angle=3.14192+angle
    EndIf
    
    C2=(movexy["Y"]-sxy["Y"]-20)*(movexy["Y"]-sxy["Y"]-20)+(movexy["X"]-sxy["X"]-20)*(movexy["X"]-sxy["X"]-20) 
    C=math.SquareRoot(C2)             'Length (X1,Y1)-(X0,Y0)
    delta=(C2 + a*a -b*b)/2/C/a     'angle (X2,Y2)-(X0,Y0)-(X1,Y1)
    If delta>=1.0 Then 
      delta=1.0
    endif
    angle2=math.ArcCos(delta)
    x2 = sxy["X"] + a*math.cos(angle+angle2)              '
    y2 = sxy["Y"] + a*math.sin(angle+angle2)              'Cross point 
    Shapes.Rotate(shape[7]["obj"],math.getdegrees(-3.4152/2+angle))
    Shapes.Move(shape[7]["obj"],sxy["X"]-b/2*math.cos(angle)+10,sxy["Y"]-b/2*math.sin(angle)-15)  '
    
    angle3 = Math.ArcTan((movexy["Y"]-y2)/(movexy["X"]-x2))   ' angle of arm top
    Shapes.Move(shape[6]["obj"],Shapes.GetLeft(shape[7]["obj"])-a*math.Cos(angle),Shapes.GetTop(shape[7]["obj"])-a*math.Sin(angle))
    Shapes.Rotate(shape[6]["obj"],math.getdegrees(angle3-3.14152/2))
    Shapes.Move(shape[5]["obj"],Shapes.GetLeft(shape[6]["obj"])-20*math.Cos(angle),Shapes.GetTop(shape[6]["obj"])-10*math.Sin(angle))  '
    if  movexy["X"]>Shapes.GetLeft(shape[11]["obj"]) Then 
      t1=clock.ElapsedMilliseconds 
    EndIf  
    If  movexy["X"]<(Shapes.GetLeft(shape[10]["obj"])-a-b) Then 
      onmouseup()
    EndIf  
  EndIf 
endsub

Sub Shoot  
  t3=clock.ElapsedMilliseconds
  newxy="X="+(newxy["X"]+vxy["X"])+";Y="+(newxy["Y"]+vxy["Y"] +(t3-t2)*(t3-t2)*Gravity/2/1000000)  '  flyineg new position 
  Shapes.Move(shape[8]["obj"],newxy["X"],newxy["y"])
  Shapes.Move(shape[9]["obj"],newxy["X"]+22,newxy["Y"]+7)
  GraphicsWindow.Title="Now Dart  X= "+math.Floor(newxy["X"])+ "   Y=  "+math.Floor(newxy["Y"])
EndSub

Sub return 
  If NN<10 Then 
    Move="False"
    Catch="False"
    Program.Delay(1500)
    For i = startNo To  endNo
      Shapes.Remove(shape[i]["obj"])
    EndFor
    init_Man()
    man_animate()
  Else 
    Move="False"
    Set_Highscore()
  EndIf
EndSub

Sub onmouseup
  If catch="true" Then 
    Upxy= "X="+(GraphicsWindow.MouseX)+";Y="+ (GraphicsWindow.MouseY)                   '  released    Mouse X Y position
    t2=clock.ElapsedMilliseconds                                                    '  Dart   release  time 
    catch="false"
    Vxy="X=-"+Math.abs(Upxy["X"]-Mdxy["X"])/(t2-t1)*10+";Y="+(Upxy["Y"]-Mdxy["Y"])/(t2-t1)*10 ' Dart  speed  X,Y
    Newxy="X="+shapes.GetLeft(shape[8]["obj"])+";Y="+shapes.Gettop(shape[8]["obj"])  ' Dart released position   NewXY  X,Y
    Move="true"
  EndIf
endsub

Sub onmousedown
  Mdxy="X=" +(GraphicsWindow.MouseX)+";Y="+ (GraphicsWindow.MouseY)                      '  caught    Mouse X Y position
  If math.Abs(Mdxy["X"]-xy0["X"])<50 And math.Abs(Mdxy["Y"]-xy0["Y"])<50 Then 
    NN=NN+1
    GraphicsWindow.Title=" Throwing......  "+NN+" times"   
    catch="true"
    Gravity=9.8
    Shapes.SetText(smsg," ")                                                         ' erase message 
  EndIf
endsub

Sub basedata
  GraphicsWindow.BrushColor="red" 
  GraphicsWindow.FontSize=25 
  smsg= Shapes.AddText(" ")
  a=shape[6]["height"]  '  arm top
  b=shape[7]["height"]  '  arm under
  xy0="X="+shapes.GetLeft(shape[8]["obj"])+";Y="+Shapes.GetTop(shape[8]["obj"])   '  8....  dart pin  position 
  sXY="X="+shapes.GetLeft(shape[10]["obj"])+";Y="+Shapes.GetTop(shape[10]["obj"])   '  10....  body  (shoulder) position 
  CXY="X="+(shapes.GetLeft(shape[7]["obj"])+b/2*math.Sin(math.GetRadians(60)) )+";Y="+(Shapes.GetTop(shape[7]["obj"])+ b/2*math.cos(math.GetRadians(60))) '  7....  arm (shoulder) position 
endsub  

Sub Shapes_Init  
  Controls.Remove(userbox)
  Controls.Remove(userTxt)
  Controls.Remove(userbutton)
  GraphicsWindow.BackgroundColor="khaki" 
  GraphicsWindow.Top=20
  GraphicsWindow.Left=50
  GraphicsWindow.Width=1200
  GraphicsWindow.Height=600
  message="Inner circle... 100point , 50point , 25point , 10point ....Outer circle"
  GraphicsWindow.DrawText(50,350,message)
  s = 1                   '       s=scale
  shX = 14                ' x offset
  shY = 96                ' y offset
  shape[1] = "func=ell;x=0;y=0;width=100;height=250;bc=#F9FDCD;pc=#FF0000;pw=2;"
  shape[2] = "func=ell;x=17;y=21;width=76;height=190;bc=#F9FDFF;pc=#6A5ACD;pw=2;"
  shape[3] = "func=ell;x=33;y=49;width=46;height=115;bc=#F9FDCD;pc=#FF0000;pw=2;"
  shape[4] = "func=ell;x=48;y=86;width=20;height=50;bc=#FFFD00;pc=#6A5ACD;pw=2;"
  startNo=1
  endNo=4
  shape_setting()
EndSub

Sub init_Man
  shape[5] = "func=ell;x=965;y=100;width=25;height=20;angle=15;bc=#F9FDCD;pc=#CB9065;pw=2;"     'hand
  shape[6] = "func=ell;x=985;y=115;width=20;height=62;angle=-30;bc=#8C9971;pc=#8C9971;pw=2;"    'arm top
  shape[7] = "func=ell;x=1030;y=155;width=20;height=78;angle=-60;bc=#8C9971;pc=#8C9971;pw=2;"   'arm under
  shape[8] = "func=line;x=940;y=90;x1=0;y1=0;x2=52;y2=13;pc=#FF0000;pw=2;"                      'dart pin
  shape[9] = "func=tri;x=965;y=100;x1=0;y1=0;x2=35;y2=8;x3=35;y3=-8;angle=15;bc=#8FB557;pc=#8FB557;pw=2;"      'dart body
  shape[10] = "func=ell;x=1047;y=192;width=53;height=112;angle=15;bc=#8C9971;pc=#8C9971;pw=2;"  'body
  shape[11] = "func=ell;x=1077;y=141;width=37;height=49;angle=10;bc=#F9FDCD;pc=#CB9065;pw=2;"   'face
  shape[12] = "func=ell;x=1088;y=157;width=10;height=9;angle=13;bc=#000000;pc=#000000;pw=2;"    'eye
  shape[13] = "func=line;x=1080;y=176;x1=0;y1=0;x2=10;y2=1;pc=#FF0000;pw=1;"                    'mouth
  shape[14] = "func=tri;x=1068;y=159;x1=5;y1=0;x2=0;y2=13;x3=10;y3=13;angle=279;bc=#F9FDCD;pc=#CB9065;pw=1;" 'nose
  shape[15] = "func=rect;x=1073;y=300;width=14;height=100;angle=350;bc=#8C9971;pc=#8C9971;pw=1;"  ' leg his left
  shape[16] = "func=rect;x=1039;y=295;width=14;height=100;angle=7;bc=#8C9971;pc=#8C9971;pw=1;"    'leg his right
  shape[17] = "func=ell;x=1064;y=396;width=34;height=17;angle=355;bc=#8C9971;pc=#8C9971;pw=2;"    'foot his left
  shape[18] = "func=ell;x=1012;y=387;width=34;height=17;angle=358;bc=#8C9971;pc=#8C9971;pw=2;"    'foot his right
  shape[19] = "func=rect;x=1083;y=187;width=13;height=12;angle=10;bc=#F9FDCD;pc=#8C9971;pw=1;"    '  neck
  shape[20] = "func=ell;x=1087;y=217;width=54;height=18;angle=29;bc=#8C9971;pc=#8C9971;pw=2;"     'arm
  shape[21] = "func=ell;x=1114;y=225;width=17;height=45;angle=246;bc=#8C9971;pc=#8C9971;pw=2;"    'arm
  shape[22] = "func=ell;x=1081;y=248;width=25;height=20;angle=15;bc=#F9FDCD;pc=#CB9065;pw=2;"     'hand
  startNo=5
  endNo=22
  shx=314
  shape_setting()
  Program.Delay(1500)
endsub

Sub man_animate
  shx=14
  For i=5 To 22
    Shapes.Animate(shape[i]["obj"], shX + shape[i]["x"] * s, shY + shape[i]["y"] * s,1500)
  EndFor
EndSub

sub shape_setting
  For i = startNo To  EndNo
    GraphicsWindow.PenWidth = shape[i]["pw"] * s
    GraphicsWindow.PenColor = shape[i]["pc"]
    GraphicsWindow.BrushColor = shape[i]["bc"]
    If shape[i]["func"] = "rect" Then
      shape[i]["obj"] = Shapes.AddRectangle(shape[i]["width"]* s, shape[i]["height"] * s)
    ElseIf shape[i]["func"] = "ell" Then
      shape[i]["obj"] = Shapes.AddEllipse(shape[i]["width"] * s, shape[i]["height"]* s)
    ElseIf shape[i]["func"] = "tri" Then
      shape[i]["obj"] = Shapes.AddTriangle(shape[i]["x1"] * s, shape[i]["y1"] * s, shape[i]["x2"] * s, shape[i]["y2"] * s, shape[i]["x3"] * s, shape[i]["y3"] * s)
    ElseIf shape[i]["func"] = "line" Then
      shape[i]["obj"] = Shapes.AddLine(shape[i]["x1"] * s, shape[i]["y1"]* s, shape[i]["x2"] * s, shape[i]["y2"] * s)
    EndIf
    Shapes.Move(shape[i]["obj"], shX + shape[i]["x"] * s, shY + shape[i]["y"] * s)
    Shapes.Rotate(shape[i]["obj"], shape[i]["angle"])
  EndFor
EndSub

Sub Resister      '  User name 
  GraphicsWindow.Title=" Easy  Darts Game  "
  GraphicsWindow.BackgroundColor="Lightcyan" 
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.FontSize = 20
  user = ""
  userBox = Controls.AddTextBox(50,100)
  Controls.SetTextBoxText(userBox,"")
  Controls.SetSize(userBox,200,30)
  userTxt = Shapes.AddText("Enter your user name here")
  Shapes.Move(userTxt,50,50)
  userButton = Controls.AddButton("OK",50,150)
EndSub

Sub Set_Highscore   '  you need  Litdev Extension 
  highScore = LDNetwork.HighScore("Easy_Darts",user,score)    
  message=" Throw "+NN+" times  Hit !!!!! Last Score= "+SCR+Text.GetCharacter(10)+Text.GetCharacter(10) +"  Total Score= "+MM+Text.GetCharacter(10)+Text.GetCharacter(10)
  message=message+"The high score is "+highScore[2]+" by "+highScore[1]
  Shapes.SetText(smsg,message)
EndSub

url="http://image.weather.com/web/radar/us_radar_plus_usen.jpg" '  every 10min
' "http://image.weather.com/images/maps/current/cur_ne_720x486.jpg"
'  "http://image.weather.com/images/maps/current/curwx_600x405.jpg"
'    "http://image.weather.com/images/sat/canadasat_720x486.jpg"
GraphicsWindow.Title=url+" : "+Clock.Time
GraphicsWindow.DrawResizedImage(url,0,0,640,450)
While "true"
  Program.Delay(60000)  '  wait  1 minute
  GraphicsWindow.Title=url+" : "+Clock.Time
  GraphicsWindow.DrawResizedImage(url,0,0,640,450)
endwhile


'    Easy   Graf   making      Controlbox data Input version          2011/12/21      by   NaoChanON  

  GraphicsWindow.Top=30
  GraphicsWindow.Left=50
  GraphicsWindow.Width=1000
  GraphicsWindow.Height=600
  GraphicsWindow.BackgroundColor="Lavender"
  GraphicsWindow.Show()
  Controls.ButtonClicked=Onclick

  TextBoX_Input()


Sub OnClick
  name=""
  name=controls.LastClickedButton     ' Last button
  nm=controls.GetButtonCaption(name)  ' Button's caption
  If nm="Execute" Then 
    get_data()
    init()
    Plot_Data()
    Regressionline()
  EndIf
EndSub

Sub TextBoX_Input
  GraphicsWindow.BrushColor="Red"
  GraphicsWindow.FontSize=30
  GraphicsWindow.DrawText(80,5," Input boxes and push execute ")
  EXEC=Controls.AddButton("Execute",230,540)
  Controls.SetSize(EXEC,300,50) 
  GraphicsWindow.FontSize=20
  
  GraphicsWindow.BrushColor="Navy"
  GraphicsWindow.FontSize=15
  GraphicsWindow.DrawText(30,50,"Graf Width,Height")  '  Width  and height 
  GraphicsWindow.DrawText(30,70,"EXAM: 800,500")
  GXYBOX= Controls.AddTextBox(230,50)
  Controls.SetSize(GXYBOX,100,40)
  Controls.SetTextBoxText(GXYBOX,"800,500")
  
  GraphicsWindow.DrawText(30,120,"Min-X , Max-X")    ' Min-X  and Max-X
  GraphicsWindow.DrawText(30,140,"EXAM: 0,800")
  MINMAXX= Controls.AddTextBox(230,120)
  Controls.SetSize(MINMAXX,100,40)
  Controls.SetTextBoxText(MINMAXX,"0,800")
  
  GraphicsWindow.DrawText(30,190,"Min-Y , Max-Y")     'Min-Y  and Max-Y
  GraphicsWindow.DrawText(30,210,"EXAM: 0,500")
  MINMAXY= Controls.AddTextBox(230,190)
  Controls.SetSize(MINMAXY,100,40)
  Controls.SetTextBoxText(MINMAXY,"0,500")
  
  GraphicsWindow.DrawText(30,260,"Dividing X , Y")   '  dividing number 
  GraphicsWindow.DrawText(30,280,"EXAM: 4,5")
  DivBOX= Controls.AddTextBox(230,260)
  Controls.SetSize(DivBOX,100,40)
  Controls.SetTextBoxText(DivBOX,"4,5")
  
  GraphicsWindow.DrawText(30,330,"Label  X")         '  Label-X  name
  GraphicsWindow.DrawText(30,350,"EXAM: Weight")
  LABELXBOX=Controls.AddTextBox(230,330)
  Controls.SetSize(LABELXBOX,300,40) 
  Controls.SetTextBoxText(LABELXBOX," Label  X ")
  
  GraphicsWindow.DrawText(30,400,"Label  Y")         '  Label-Y  name
  GraphicsWindow.DrawText(30,420,"EXAM: Height")
  LABELYBOX=Controls.AddTextBox(230,400)
  Controls.SetSize(LABELYBOX,300,40) 
  Controls.SetTextBoxText(LABELYBOX," Label  Y ")
  
  GraphicsWindow.DrawText(30,470,"Title name")        '  Title name 
  GraphicsWindow.DrawText(30,490,"EXAM: Weight vs Height")
  TTLBOX=Controls.AddTextBox(230,470)
  Controls.SetSize(TTLBOX,300,40) 
  Controls.SetTextBoxText(TTLBOX," Test  Graph ")
  
  GraphicsWindow.DrawText(660,5,"Input   X , Y data")   '  X,Y  data 
  GraphicsWindow.DrawText(660,25,"EXAM:  50 , 100    enter")
  GraphicsWindow.DrawText(720,45,"80 , 150    enter")
  MBOX= Controls.AddMultiLineTextBox(700,80)
  Controls.SetSize(MBOX,100,500)
  Controls.SetTextBoxText(MBOX," 50,100")
EndSub  

Sub get_data
  GWH=Controls.GetTextBoxText(GXYBOX)
  GWidth= Text.GetSubText(GWH,1,text.GetIndexOf(GWH,",")-1)    '  Gwidth
  GHeight=Text.GetSubTextToEnd(GWH,text.GetIndexOf(GWH,",")+1)  'Ghight

  MMX=Controls.GetTextBoxText(MINMAXX)
  MinX= Text.GetSubText(MMX,1,text.GetIndexOf(MMX,",")-1)     '  Min-X
  MaxX=Text.GetSubTextToEnd(MMX,text.GetIndexOf(MMX,",")+1)   'Max-X
  
  MMY=Controls.GetTextBoxText(MINMAXY)
  MinY= Text.GetSubText(MMY,1,text.GetIndexOf(MMY,",")-1)      'Min-Y
  MaxY=Text.GetSubTextToEnd(MMY,text.GetIndexOf(MMY,",")+1)    'Max-Y
   
  DXY=Controls.GetTextBoxText(DivBOX)
  XDiv= Text.GetSubText(DXY,1,text.GetIndexOf(DXY,",")-1)      'X-Dividing number
  YDiv=Text.GetSubTextToEnd(DXY,text.GetIndexOf(DXY,",")+1)    'Y-Dividing number
  
  LBLX=Controls.GetTextBoxText(LABELXBOX)            '  Label-X
  LBLY=Controls.GetTextBoxText(LABELYBOX)            '  Label-Y
  TTL=Controls.GetTextBoxText(TTLBOX)                ' Title name 
  
  DatXY=Controls.GetTextBoxText(MBOX)               ' X-Y  data
  Get_XYata()                                       '  Pick Up  X,Y data from multilinetextbox 

EndSub
   
Sub Get_XYata                           '  Pick Up  X,Y data from multilinetextbox 
  DatXY=Controls.GetTextBoxText(MBOX)       
  If Text.GetCharacterCode(text.GetSubText(DatXY,Text.GetLength(datXY),1))=10 Then
    DatXY= text.GetSubText(DatXY,1,Text.GetLength(datXY)-2)  ' if DatXY -end = Chr$(13)+chr$(10) then  delete  
  EndIf
  
   For i=1 To Text.GetLength(DatXY)
     word1=text.GetSubText(datXY,i,1)
     If word1=text.GetCharacter(13) Then     '  delete  chr$(13)
        word1=""
     ElseIf word1=text.GetCharacter(10) Then ' conversion Chr$(10)  to  ":"    =delimiter
        word1=":"
     EndIf
     midw=text.Append(midw,word1)
   EndFor  
    midw=midw+":"                 '   connect all word and  add   ":"  =delimiter
  
   while midw<>"" 
    NN=NN+1
    midp1=Text.GetIndexOf(midw,",")
    midp2=Text.GetIndexOf(midw,":")
    px[NN]=Text.GetSubText(midw,1,midp1-1)              ' pick up  X-data
    py[NN]=Text.GetSubText(midw,midp1+1,midp2-midp1-1)  ' pick up  Y-data
    midw=Text.GetSubTextToEnd(midw,midp2+1)
   EndWhile 
EndSub


Sub init
  GraphicsWindow.Clear()
  GraphicsWindow.top=50
  GraphicsWindow.Left=50
  GraphicsWindow.Width=1000
  GraphicsWindow.Height=650
  GraphicsWindow.Show()
  GraphicsWindow.BackgroundColor="Lightcyan"
  GraphicsWindow.BrushColor="Navy"
  GraphicsWindow.PenColor="Red"
  
  '  Draw   Rectangle  
  GTop=60
  GLeft=150
  GraphicsWindow.DrawRectangle(Gleft,Gtop,GWidth,GHeight)
  
  '   Title and X,Y-labels
  GraphicsWindow.FontSize=30
  GTitle=Shapes.AddText(TTL)
  Shapes.Animate(GTitle,Gleft+150,Gtop-40,1000)
  LabelY=Shapes.AddText(LBLY)
  Shapes.Animate(LabelY,15,(Gtop+GHeight)/2,1500)
  Shapes.Rotate(LabelY,-90)
  LabelX=Shapes.AddText(LBLX)
  Shapes.Animate(LabelX,(Gleft+Gwidth)/2-20,Gtop+GHeight+40,2000)
  
  '   X-----Axis
  GraphicsWindow.FontSize=20
  GraphicsWindow.BrushColor="Red"

  For i= 0 To XDiv
    For j=GTop To GTop+Gheight-5 Step 10
          GraphicsWindow.DrawLine(Gleft+i*(Gwidth/Xdiv),J,Gleft+i*(Gwidth/Xdiv),j+5)
    EndFor 
    DivX=math.round(minX+i*((MaxX-minX)/Xdiv))
    GraphicsWindow.DrawText(Gleft+i*(Gwidth/Xdiv)-20,GTop+GHeight+10,DivX)
  EndFor

 '  Y---Axis
  For i= YDiv To 0 Step -1
    For j=GLeft To GLeft+Gwidth-5 Step 10
      GraphicsWindow.DrawLine(j,GTop+i*(GHeight/Ydiv),j+5,GTop+i*(GHeight/Ydiv))
    EndFor
    DivY=math.Round(MaxY-i*((MaxY-minY)/Ydiv))
    GraphicsWindow.DrawText(Gleft-40,GTop+i*(GHeight/Ydiv)-10,DivY)
  EndFor
   
EndSub
  
Sub  Plot_Data    
  GraphicsWindow.PenColor="Green"
  GraphicsWindow.PenWidth=3
  For i=1 To NN
    plotx=Gleft + (PX[i]-minX)*Gwidth/(MaxX-MinX)
    ploty=GTop + Gheight- (PY[i]-minY)*Gheight/(MaxY-MinY)
    sc[i]=Shapes.AddEllipse(10,10)
    Shapes.Animate(sc[i],plotx-5,ploty-5,1000)
  EndFor
EndSub
  
  
Sub Regressionline
  For i=1 To NN
    sumx=sumx+px[i]
    sumy=sumy+py[i]
    sumX2=sumX2+px[i]*px[i]
    sumXY=sumXY+px[i]*py[i]
    sumY2=sumY2+py[i]*py[i]
  EndFor
  
  slope=(NN*sumXY-sumx*sumy)/(NN*sumx2-sumx*sumx)  '  slope  a
  slope=math.Round(slope*100)/100                   '  round a
  intercept=sumy/NN-slope*sumx/NN                  '  intercept  b
  intercept=math.Round(intercept*100)/100          '  round b 
  
  Reg_line="y= "+slope+"X  + "+intercept          ' y= aX+b  
  sreg=Shapes.AddText(Reg_line)
  Shapes.Animate(sreg,Gleft+10,80,1500)
  
  regY1=slope*minx+intercept                '  X=MinX   Y= intercept
  regY2=maxY*0.8                           ' Y=maxY*0.8
  regx2=(regY2-intercept)/slope             ' X    at  Y
  Gregx1=Gleft                                           'conversion  x1=minX 
  GregX2=Gleft + (regx2-minX)*Gwidth/(MaxX-MinX)         ' conversion x2
  Gregy1=GTop + Gheight- (regY1-minY)*Gheight/(MaxY-MinY) ' conversion y1
  Gregy2=GTop + Gheight- (regY2-minY)*Gheight/(MaxY-MinY) ' conversion y2
  
  slope2=(NN*sumXY-sumx*sumy)/(NN*sumY2-sumY*sumY)  '  slope  c
  slope2=math.Round(slope2*100)/100                 '  round c
  Coefficient=Math.SquareRoot(slope*slope2)         'Correlation coefficient 
  Coefficient=math.Round(Coefficient*1000)/1000   
  scoef= Shapes.AddText("Coefficient= "+Coefficient)
  Shapes.Animate(scoef,Gleft+10,100,1500)
  
  GraphicsWindow.PenColor="Green"
  GraphicsWindow.DrawLine(Gregx1,GregY1,GregX2,GregY2)   ' draw regression Line 

EndSub

  
  
  
Stack.PushValue("a", "a0")
Stack.PushValue("c", "c0")
Stack.PushValue("b", "b0")
Stack.PushValue("ad", "0")
Stack.PushValue("cd", "0")
Stack.PushValue("bd", "0")
'---------------------------------------------------------------------------------------------------------------------------------
GraphicsWindow.Show()
GraphicsWindow.CanResize = 0
GraphicsWindow.Width = 800
GraphicsWindow.Height = 600
GraphicsWindow.PenColor = "DarkSlateGray"
GraphicsWindow.PenWidth = 10
GraphicsWindow.Title = "Game 'Tower of Hanoi. Question of Tonkin.'"
Path = "http://www.ac-acap.org/images/Hanoy/"
background = ImageList.LoadImage(Path + "fon.jpg")
GraphicsWindow.DrawImage(background, 0, 0)
'---------------------------------------------------------------------------------------------------------------------------------
disk = 0
GraphicsWindow.DrawLine(200, 600, 200, 400)
GraphicsWindow.DrawLine(400, 600, 400, 400)
GraphicsWindow.DrawLine(600, 600, 600, 400)
'---------------------------------------------------------------------------------------------------------------------------------
For i = 8 To 1 Step -1
  GraphicsWindow.PenColor = GraphicsWindow.GetRandomColor()
  a[i] = Shapes.AddEllipse(20+20*i, 20)
  Shapes.Move(a[i], 190-10*i, 420+20*i)
  Stack.PushValue("a", a[i])
  Stack.PushValue("ad", i)
EndFor
'---------------------------------------------------------------------------------------------------------------------------------
GraphicsWindow.ShowMessage("The Tower of Hanoi is a mathematical game or puzzle. It consists of three rods, and a number of disks of different sizes which can slide onto any rod. The puzzle starts with the disks in a neat stack in ascending order of size on one rod, the smallest at the top, thus making a conical shape. The objective of the puzzle is to move the entire stack to another rod, obeying the following rules: Only one disk may be moved at a time. Each move consists of taking the upper disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod. No disk may be placed on top of a smaller disk.", "RULES")
Sound.PlayChime()
GraphicsWindow.MouseDown = Down
GraphicsWindow.MouseMove = Move
GraphicsWindow.MouseUp = Up
'---------------------------------------------------------------------------------------------------------------------------------
Sub Down
  If Mouse.IsLeftButtonDown = "true" And Mouse.IsRightButtonDown <> "true" Then
    If Stack.GetCount("a") > 1 Then
      If GraphicsWindow.MouseX >= 0 And GraphicsWindow.MouseX < 300 Then
        s = 1 
        disk = Stack.PopValue("a")
        nomer = Stack.PopValue("ad")
        Shapes.Move(disk, GraphicsWindow.MouseX, GraphicsWindow.MouseY)
      EndIf
    EndIf
    If Stack.GetCount("c") > 1 Then
      If GraphicsWindow.MouseX >= 300 And GraphicsWindow.MouseX <= 500 Then
        s = 2
        disk = Stack.PopValue("c")
        nomer = Stack.PopValue("cd")
        Shapes.Move(disk, GraphicsWindow.MouseX, GraphicsWindow.MouseY)
      EndIf
    EndIf
    If Stack.GetCount("b") > 1 Then
      If GraphicsWindow.MouseX > 500 And GraphicsWindow.MouseX <= 800 Then
        s = 3
        disk = Stack.PopValue("b")
        nomer = Stack.PopValue("bd")
        Shapes.Move(disk, GraphicsWindow.MouseX, GraphicsWindow.MouseY)
      EndIf
    EndIf
  EndIf
EndSub
'---------------------------------------------------------------------------------------------------------------------------------
Sub Move
     Shapes.Move(disk, GraphicsWindow.MouseX, GraphicsWindow.MouseY)
 EndSub
'---------------------------------------------------------------------------------------------------------------------------------
Sub Up
  If disk <> 0 Then
    If GraphicsWindow.MouseX >= 0 And GraphicsWindow.MouseX < 300 Then
      If Stack.GetCount("ad") = 1 Then
        Sound.PlayChimes()
        Stack.PushValue("a", disk)
        Stack.PushValue("ad", nomer)
        Shapes.Move(disk, 190-10*nomer, 620-Stack.GetCount("a")*20)
        disk = 0
        nomer = 0  
      Else
        prov = Stack.PopValue("ad")
        If prov > nomer Then
          Sound.PlayChimes()
          Stack.PushValue("ad", prov)
          Stack.PushValue("a", disk)
          Stack.PushValue("ad", nomer)
          Shapes.Move(disk, 190-10*nomer, 620-Stack.GetCount("a")*20)
          disk = 0
          nomer = 0  
        Else
          Sound.PlayBellRing()
          GraphicsWindow.ShowMessage("Так ходить нельзя", "Ошибка")  
          If s = 1 Then
            Stack.PushValue("a", disk)
            Stack.PushValue("ad", nomer)
            Shapes.Move(disk, 190-10*nomer, 620-Stack.GetCount("a")*20)
          ElseIf s = 2 Then
            Stack.PushValue("c", disk)
            Stack.PushValue("cd", nomer)
            Shapes.Move(disk, 390-10*nomer, 620-Stack.GetCount("c")*20)
          ElseIf s = 3 Then
            Stack.PushValue("b", disk)
            Stack.PushValue("bd", nomer)
            Shapes.Move(disk, 590-10*nomer, 620-Stack.GetCount("b")*20)
          EndIf
          Stack.PushValue("ad", prov)
          disk = 0  
          nomer = 0
        EndIf 
      EndIf
    EndIf
    If  GraphicsWindow.MouseX >= 300 And GraphicsWindow.MouseX <= 500 Then
      If Stack.GetCount("cd") = 1 Then
        Sound.PlayChimes()
        Stack.PushValue("c", disk)
        Stack.PushValue("cd", nomer)
        Shapes.Move(disk, 390-10*nomer, 620-Stack.GetCount("c")*20)
        disk = 0  
        nomer = 0
      Else
        prov = Stack.PopValue("cd") 
        If prov > nomer Then
          Sound.PlayChimes()
          Stack.PushValue("cd", prov)
          Stack.PushValue("c", disk)
          Stack.PushValue("cd", nomer)
          Shapes.Move(disk, 390-10*nomer, 620-Stack.GetCount("c")*20)
          disk = 0  
          nomer = 0
        Else
          Sound.PlayBellRing()
          GraphicsWindow.ShowMessage("Так ходить нельзя", "Ошибка") 
          If s = 1 Then
            Stack.PushValue("a", disk)
            Stack.PushValue("ad", nomer)
            Shapes.Move(disk, 190-10*nomer, 620-Stack.GetCount("a")*20)
          ElseIf s = 2 Then
            Stack.PushValue("c", disk)
            Stack.PushValue("cd", nomer)
            Shapes.Move(disk, 390-10*nomer, 620-Stack.GetCount("c")*20)
          ElseIf s = 3 Then
            Stack.PushValue("b", disk)
            Stack.PushValue("bd", nomer)
            Shapes.Move(disk, 590-10*nomer, 620-Stack.GetCount("b")*20)
          EndIf
          Stack.PushValue("cd", prov)
          disk = 0  
          nomer = 0 
        EndIf 
      EndIf  
    EndIf  
    If GraphicsWindow.MouseX > 500 And GraphicsWindow.MouseX <= 800 Then
      If Stack.GetCount("bd") = 1 Then
        Sound.PlayChimes()
        Stack.PushValue("b", disk)
        Stack.PushValue("bd", nomer)
        Shapes.Move(disk, 590-10*nomer, 620-Stack.GetCount("b")*20)
        disk = 0
        nomer = 0 
      Else
        prov = Stack.PopValue("bd") 
        If prov > nomer Then
          Sound.PlayChimes()
          Stack.PushValue("bd", prov)
          Stack.PushValue("b", disk)
          Stack.PushValue("bd", nomer) 
          Shapes.Move(disk, 590-10*nomer, 620-Stack.GetCount("b")*20)
          disk = 0
          nomer = 0   
        Else
          Sound.PlayBellRing()
          GraphicsWindow.ShowMessage("Так ходить нельзя", "Ошибка")
          If s = 1 Then
            Stack.PushValue("a", disk)
            Stack.PushValue("ad", nomer)
            Shapes.Move(disk, 190-10*nomer, 620-Stack.GetCount("a")*20)
          ElseIf s = 2 Then
            Stack.PushValue("c", disk)
            Stack.PushValue("cd", nomer)
            Shapes.Move(disk, 390-10*nomer, 620-Stack.GetCount("c")*20)
          ElseIf s = 3 Then
            Stack.PushValue("b", disk)
            Stack.PushValue("bd", nomer)
            Shapes.Move(disk, 590-10*nomer, 620-Stack.GetCount("b")*20)
          EndIf
          Stack.PushValue("bd", prov)
          disk = 0  
          nomer = 0  
        EndIf 
      EndIf    
    EndIf
    If Stack.GetCount("b") = 9 Then
      GraphicsWindow.ShowMessage("Congratulation! You Win!" "Victory!")
    EndIf
  EndIf
EndSub
'  Invador game     ver1.0                     by  NaochanON
'

gui()

GraphicsWindow.MouseMove=onmousemove
GraphicsWindow.MouseDown=onmousedown

While "true"
  EShooting()
  EnemyPosition()
  EnemyBullet()
  EHit_check()
  shooting()
  Hit_check()
  GraphicsWindow.Title=" You hit  "+Hit +" times"+ "     You are Hit "+Eht+" times        Elapsedtime= "+Math.Floor((Clock.ElapsedMilliseconds-t0)/100)/10 +" sec"
  Program.Delay(20)
endwhile

sub EnemyPosition                            '   Enemy  position
  If Shapes.GetLeft(enemy[1])<-60 Or 1020<Shapes.GetLeft(enemy[1]) Then 
    Retry:
    PM=2-math.GetRandomNumber(3)
    If PM=0 Then 
      Goto Retry
    EndIf 
    turn=500 +math.GetRandomNumber(400)*PM                     '  set  random turning point
    Shapes.Animate( enemy[1],turn,dy,3000 )                    '  Enemy position
    Shapes.Animate( enemy[2],turn,dy,3000 )
  endif  
  Shapes.Move( enemy[1],Shapes.GetLeft(enemy[1])+PM+acs,dy )   '  Enemy position
  Shapes.Move( enemy[2],Shapes.GetLeft(enemy[2])+PM+acs,dy )
endsub

Sub EShooting                                '   Enemy  shooting
  dXpe=math.Abs(Shapes.GetLeft(enemy[1])-Shapes.GetLeft(player[1]))  '  distance   from player  and enmy
  If 30<dxpe and dxpe<=45 And flag=0 Then    '   if distance is  from 38  to 40         
    MM=MM+1
    acs=5*( Shapes.GetLeft(enemy[1])-Shapes.GetLeft(player[1]))/dxpe
    If MM=21 Then 
      dy=dy+10                               '  enemy  Y level  down  
      MM=1
    EndIf
    edb[MM]=1                                '   bullet ON
    flag=1                                   '   Flag  ....   avoid  continuous  shooting 
  Else
    flag=0
  EndIf
  Shapes.Move(rect[MM],shapes.GetLeft(enemy[1])+20,dy+20)   '   set  bullet  
  Shapes.showShape(rect[MM])                                '   visible  
endsub


Sub  EnemyBullet
  For M=1 To 20
    Shapes.Move(rect[M],Shapes.GetLeft(rect[M]),Shapes.Gettop(rect[M])*edb[M]+8)  '  bullet moves   Y+8
    Shapes.SetOpacity(rect[M],100*edb[M])
    if Shapes.Gettop(rect[M])>700 Then 
      edb[M]=0
      Shapes.Move( rect[M],Shapes.GetLeft(enemy[1])+20,dy+20)   ' set  bullet  
    EndIf
  EndFor
EndSub

Sub  EHit_check
  EHit="False"
  For L=1 To 20
    If EHit="False" And  math.Abs(Shapes.GetLeft(rect[L])*edb[L]- Shapes.GetLeft(player[1])-13 )<13  and  math.Abs(Shapes.Gettop(rect[L])*edb[L]-shapes.Gettop(player[1])) <15 then 
      EHit="True"
      For N=1 To 3
        Shapes.HideShape(player[N])                  '  hide  player 
      endfor
      Shapes.Animate(msg2,-300,300,3000)             '  You are HIT  message 
      Program.Delay(3000)
      EHt=Eht+1
      Shapes.Move(msg2,1400,100) 
      For N=1 To 3
        Shapes.showShape(player[N])                  '  Show  player 
      endfor
      erasebullet()                                  '  erase  bullets 
      L=20                                           '  avoid check
    EndIf
  endfor  
EndSub

Sub  shooting    '  Player  shooting
  acs=0
  For K=1 To 10
    Shapes.Move(ball[k],Shapes.GetLeft(ball[k]),Shapes.Gettop(ball[k])-4*db[k])  '  bullet   moves  Y-4  
    If (shapes.Gettop(ball[k])-Shapes.Gettop(enemy[1]))<85 and math.Abs(Shapes.GetLeft(ball[k])-Shapes.GetLeft(enemy[1]))<55  Then '  if bullet approaches to enemy
      acs=(Shapes.GetLeft(enemy[1])-Shapes.GetLeft(ball[k]))/5              '  enemy  escape  speedy
    EndIf
    if Shapes.Gettop(ball[k])<-5 Then 
      Shapes.Move( ball[k],Shapes.GetLeft(player[2]),625)                   ' set  bullet  
      db[k]=0
      shapes.HideShape(ball[k])
    EndIf
    Hit_check() 
  EndFor
EndSub

Sub  Hit_check
  If  math.Abs(Shapes.GetLeft(ball[k])- Shapes.GetLeft(enemy[2])-12.5 )<12.5  and  math.Abs(Shapes.Gettop(ball[k])-shapes.Gettop(enemy[2])-7.5) <7.5 then 
    PHit="True"
    RX=Shapes.GetLeft(enemy[2]) 
    RY=Shapes.Gettop(enemy[2]) 
  EndIf
  If PHit="True" then
    erasebullet()
    Shapes.Animate(msg,1300,300,3000)                            '  HIT message 
    Program.Delay(3000)
    PHit="False"
    Hit=hit+1
    Shapes.Move(msg,-300,100) 
    Shapes.Move( enemy[1],Shapes.GetLeft(enemy[1])+10,dy )       '  Enemy position
    Shapes.Move( enemy[2],Shapes.GetLeft(enemy[2])+10,dy )
    warp()
    enemymake()                                                  '  new enemy making
    K=10                                                         ' avoid check 
  EndIf
EndSub

Sub onmousedown   '  bullet shooting
  NN=NN+1
  db[NN]=1
  Shapes.ShowShape(ball[NN])
  Shapes.Move(ball[NN],Shapes.GetLeft(player[2]),645)            '   bullet  appears
  If NN=10 Then 
    STP=2+Math.GetRandomNumber(3)
    scatter()
    dy=dy+10
    NN=0
  EndIf
EndSub

Sub onmousemove
  MX= GraphicsWindow.MouseX
  MY= GraphicsWindow.MouseY
  For i=1 To 3
    Shapes.Move(player[i],MX+7*i-15,Shapes.Gettop(player[i]))    '  player  moves 
  EndFor 
EndSub

Sub scatter
  For i=1 To 300 Step stp
    Shapes.Animate(star[i],Math.GetRandomNumber(1400),Math.GetRandomNumber(400)+400*Math.Floor(i/150),500)  '  star  randomposition
  EndFor
endsub

Sub warp
  For i=1 To 300 
    Shapes.Animate(star[i],RX,RY,2000)  '  star  randomposition
  EndFor
  Program.Delay(1500)
  stp=1
  scatter()
endsub

Sub erasebullet
  For K=1 To 20
    Shapes.HideShape(ball[k]) 
    Shapes.HideShape(rect[k])
    db[K]=0
    edb[K]=0  
  EndFor
  MM=0
endsub

Sub gui
  Hit=0
  Eht=0
  color="1=Red;2=Green;3=Yellow;4=Cyan;5=Blue;6=Pink;7=khaki"
  GraphicsWindow.Left=50
  GraphicsWindow.Top=20
  GraphicsWindow.Width=1000
  GraphicsWindow.Height=700
  GraphicsWindow.BackgroundColor="Black"
  Mouse.HideCursor()
  '-----------------------   back stars  ------------------------------
  For i=1 To 300
    GraphicsWindow.PenColor=GraphicsWindow.GetRandomColor()
    dr= 3+Math.GetRandomNumber(7)
    star[i]=Shapes.AddEllipse(DR,DR)
  EndFor
  stp=1                                    '  Initial  scatter step number
  scatter()                                '  background  stars  
  '------------------------  Enemy  -----------------------------------
  enemymake()
  '------------------------  Player  -----------------------------------
  GraphicsWindow.BrushColor="Cyan"
  GraphicsWindow.PenColor="lightcyan"
  player[2]=shapes.AddEllipse(10,35)
  Shapes.Move(player[2],300,645)
  GraphicsWindow.BrushColor="Yellow"
  GraphicsWindow.PenColor="Yellow"
  player[1]=shapes.AddEllipse(8,20)
  Shapes.Move(player[1],293,660)
  player[3]=shapes.AddEllipse(8,20)
  Shapes.Move(player[3],308,660)
  '------------------------  Hit message  -----------------------------------
  GraphicsWindow.FontSize=30
  msg= Shapes.AddText(" You  Hit !!!!!!! ")
  Shapes.Move(msg,-300,100) 
  msg2= Shapes.AddText(" You are  Hit XD XD ")
  Shapes.Move(msg2,1400,200) 
  '---------------------------  bullet  -------------------------------- 
  For k=1 to 10
    db[k]=0
    ball[k]=Shapes.AddEllipse(5,8)
    Shapes.Move(ball[k],304,645)
    Shapes.HideShape(ball[k])
  endfor  
  '---------------------------  bullet2  -------------------------------- 
  GraphicsWindow.BrushColor="Cyan"
  GraphicsWindow.PenColor="Cyan"
  For L=1 to 20
    rect[L]=Shapes.AddRectangle(7,10)
    Shapes.Move(rect[L],Shapes.GetLeft(enemy[1])+22.5,0)
    Shapes.HideShape(rect[L])
  endfor  
  flag=0
  t0=clock.ElapsedMilliseconds
EndSub

Sub enemymake
  CN= Math.GetRandomNumber(7)
  GraphicsWindow.BrushColor=color[CN]
  GraphicsWindow.PenColor=color[CN]
  Shapes.Remove(enemy[1])
  enemy[1]=shapes.AddEllipse(45,15)
  Shapes.Move(enemy[1],500,0)
  Shapes.Remove(enemy[2])
  enemy[2]=Shapes.AddTriangle(10,10,35,10,22.5,25)
  Shapes.Move(enemy[2],500,0)
  PM=1                       '  Plus minus
  turn=520                   '  Initial turning point
  dy=0                       '  Initial  Y-step 
  NN=0                       '  Initial  bullet   number  (player)
  MM=0                       '  Initial  bullet number  ( enemy)
EndSub
' NOTE TO SELF - 
' change this so that the mini-map becomes 5 blocks wide x 6 blocks long
' note 2 -
' change this so that it does not attempt to draw blocks that you cannot see....
' so the minimap needs to be updated to set those "invisible" blocks to zeroes.



'main section
'set up the map to walk around
definemap()
TextWindow.WriteLine ("definemap subroutine completed")
'
'create the 3d map points and 2d (screen) plot points for any potentially drawable map block
createblocks()
TextWindow.WriteLine ("createblocks subroutine completed")
'
setupcolours()
TextWindow.WriteLine ("colour array set up - white to darkgray")
'
'    screenX = screenWidth * x / z   +  screenWidth / 2
'    screenY = screenHeight * y / z   +  screenHeight / 2

'set up graphics window and size of virtual screen
GraphicsWindow.Width = 790
GraphicsWindow.Height = 800
GraphicsWindow.CanResize = 1
GraphicsWindow.BackgroundColor = "black"
'
scrw = 800                'screen width 
scrh = 800                'screen height
scale = 250               'used to scale up the 3d plot points
zoffset = 0               ' z offset - used to move the depth of the 3d blocks, into and out of the screen
xoffset = 0               ' used to move camera slightly, as it didn't line up with window exactly

'set up the starting location and direction to face in the map
myxpos = startx
myypos = starty
mydir  = startdir

TextWindow.WriteLine ("xpos = "+ myxpos)
TextWindow.WriteLine ("ypos = "+ myypos)
TextWindow.WriteLine ("dir  = "+ mydir)

minimap()
TextWindow.WriteLine ("minimap subroutine completed")

drawblocknew()
GraphicsWindow.BrushColor = "yellow"
GraphicsWindow.DrawBoundText (390,50,100,mydir)
'
GraphicsWindow.Keydown = OnKeydown
GraphicsWindow.Keyup = OnKeyup

loop:

Goto loop

Sub OnKeyDown
  ' Code for key presses goes here. 
  keypress = GraphicsWindow.LastKey
  move()
  minimap()
  If moved = 1 Then
    GraphicsWindow.Clear()
    drawblocknew()
    GraphicsWindow.brushcolor = "yellow"
    GraphicsWindow.DrawBoundText (390,50,100,mydir)
    moved = 0
  EndIf
EndSub

Sub OnKeyUp
  keypress = ""
EndSub

Sub move
  If keypress = "Up" Then
    moveforward()
  EndIf
  If keypress = "Left" Then
    turnleft()
  EndIf
  If keypress = "Right" Then
    turnright()
  EndIf
EndSub

Sub moveforward
'determine direction facing and if "Up" (forward) key is being pressed
  If mydir = "n" Then
    If map[myxpos][myypos-1]= 0 Then
      myypos = myypos-1
      moved = 1
    EndIf
  EndIf
  If mydir = "e" Then
    If map[myxpos+1][myypos]= 0 Then
      myxpos = myxpos+1
      moved = 1
    EndIf
  EndIf
  If mydir = "s" Then
    If map[myxpos][myypos+1]= 0 Then
      myypos = myypos+1
      moved = 1
    EndIf
  EndIf
  If mydir = "w" Then
    If map[myxpos-1][myypos]= 0 Then
      myxpos = myxpos-1
      moved = 1
    EndIf
  EndIf
EndSub

Sub turnleft
  'check for rotating to the left
  If mydir = "n" and keypress = "Left" then
    mydir = "w"
    moved = 1
    keypress = ""
  EndIf
  If mydir = "e" and keypress = "Left" then
    mydir = "n"
    moved = 1
    keypress = ""
  EndIf
  If mydir = "s" and keypress = "Left" then
    mydir = "e"
    moved = 1
    keypress = ""
  EndIf
  If mydir = "w" and keypress = "Left" then
    mydir = "s"
    moved = 1
    keypress = ""
  EndIf
EndSub
Sub turnright
  'check for rotating to the right
  If mydir = "n" and keypress = "Right" then
    mydir = "e"
    moved = 1
    keypress = ""
  EndIf
  If mydir = "e" and keypress = "Right" then
    mydir = "s"
    moved = 1
    keypress = ""
  EndIf
  If mydir = "s" and keypress = "Right" then
    mydir = "w"
    moved = 1
    keypress = ""
  EndIf
  If mydir = "w" and keypress = "Right" then
    mydir = "n"
    moved = 1
    keypress = ""
  EndIf
EndSub

Sub drawblocknew
    For f = 6 To 1 Step -1
      If viewrow1[1][f] = 1 Then
        blockdr = f
        colour = colours[f]
        draw3dblock()
      EndIf
    EndFor
    For f = 18 To 13 Step -1
      If viewrow1[3][f-12] = 1 Then
        blockdr = f
        colour = colours[f-12]
        draw3dblock()
      EndIf
    EndFor
    For f = 12 To 8 Step -1
      If viewrow1[2][f-6] = 1 Then
        blockdr = f
        colour = colours[f-7]
        draw3dblock()
      EndIf
    EndFor
    
EndSub

Sub draw3dblock
  'first set the brush colour - used for drawing the block faces,
  'and the pen colour - used for filling in some of the gaps in the faces
  GraphicsWindow.BrushColor = colour
  GraphicsWindow.PenColor = colour
  GraphicsWindow.PenWidth = 3
  '
  'scale up the size of the points for the block
  For a = 1 To 6
    x[a] = block[blockdr][a][1] * scale + xoffset   'used to re-align the render with the screen
    y[a] = block[blockdr][a][2] * (scale/2)         ' i worked out that y settings were too big, so divided the scale by 2
    z[a] = block[blockdr][a][3] * scale + zoffset   'will later be used to zoom in, when walking forward to next block
  EndFor
  '
  'calculate 2d screen co-ords for each visible 3d point of the block to be drawn
  For a = 1 To 6
    scrnx[a] = scrw * x[a]/z[a] + scrw/2
    scrny[a] = scrh * y[a]/z[a] + scrw/2
  EndFor
  '
  'draw the filled in 3d block as 4 triangles (allows for the perspective by using triangles)
  'and draw the forward facing plane of the block as 2 triangles
  'skipfront = 0
  If blockdr = 13 Then
    skipfront = 1
  EndIf
  If skipfront = 0 Then
    GraphicsWindow.Filltriangle (scrnx[1],scrny[1],scrnx[2],scrny[2],scrnx[3],scrny[3])
    GraphicsWindow.FillTriangle (scrnx[2],scrny[2],scrnx[3],scrny[3],scrnx[4],scrny[4]) 
    '
    'for some reason there is a gap between the triangles, so draw an extra line to fill in gap...
    GraphicsWindow.DrawLine (scrnx[2],scrny[2],scrnx[3],scrny[3])
    
  EndIf

  '
  'if the block is either at the left or right of the view, then also draw in the visible side plane, using another 2 triangles
  'and also another line to fill the gap between the triangles.
  GraphicsWindow.FillTriangle (scrnx[2],scrny[2],scrnx[5],scrny[5],scrnx[4],scrny[4])
  GraphicsWindow.FillTriangle (scrnx[4],scrny[4],scrnx[5],scrny[5],scrnx[6],scrny[6])    
  GraphicsWindow.DrawLine (scrnx[4],scrny[4],scrnx[5],scrny[5])
  '
  'now draw lines around each block - to make it easier to see the block edges
  GraphicsWindow.pencolor = "black"
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.DrawLine (scrnx[1],scrny[1],scrnx[2],scrny[2])
  GraphicsWindow.DrawLine (scrnx[2],scrny[2],scrnx[4],scrny[4])
  GraphicsWindow.DrawLine (scrnx[4],scrny[4],scrnx[3],scrny[3])
  GraphicsWindow.DrawLine (scrnx[3],scrny[3],scrnx[1],scrny[1])
  If blockdr < 7 Or blockdr > 13 Then
    GraphicsWindow.DrawLine (scrnx[2],scrny[2],scrnx[5],scrny[5])
    GraphicsWindow.DrawLine (scrnx[5],scrny[5],scrnx[6],scrny[6])
    GraphicsWindow.DrawLine (scrnx[6],scrny[6],scrnx[4],scrny[4])
    GraphicsWindow.DrawLine (scrnx[4],scrny[4],scrnx[2],scrny[2])
  EndIf
  skipfront = 0
EndSub

Sub minimap
  'determing which direction the player is facing
  'and fill in the copy the main map details into the minimap
  'the minimap will be used by the "3d" drawing subroutine to draw
  'the maze blocks that are in front of the player
  '
  'clear the viewrows first to make sure there is no rubbish left in there...
  For x = 1 To 3
    For y = 1 To 6
      viewrow1[x][y] = 0
    EndFor
  EndFor
  '
  'which direction is the player looking?
  If mydir = "n" Then
    minimapn()
  EndIf
  If mydir = "e" Then
    minimape()
  EndIf
  If mydir = "s" Then
    minimaps()
  EndIf
  If mydir = "w" Then 
    minimapw()     
  EndIf
  '
  ' viewrow[2][1] will always be zero as it's where the player is standing
  viewrow1[2][1] = 0
  '
  'tidy the minimap so that it does not hold block data for blocks that you cannot see
  For loop = 2 To 5
    If viewrow1[2][loop] = 1 Then
      For loop2 = loop+1 to 6
        viewrow1[2][loop2] = 0
      EndFor
    EndIf
  EndFor
      
 For yloop1 = 1 To 6
    For xloop1 = 1 To 3
      b = 7-yloop1
      TextWindow.CursorLeft = xloop1
      TextWindow.CursorTop  = 30+yloop1
      TextWindow.WriteLine (viewrow1[xloop1][b])
    EndFor
  EndFor 
EndSub

Sub minimapn
  'the player is facing north...
  'read the row of map cells in line with the player
  viewrow1[1][1] = map[myxpos-1][myypos]
  viewrow1[3][1] = map[myxpos+1][myypos]
  '
  'read the 1st row of map cells in front of the player
  viewrow1[1][2] = map[myxpos-1][myypos-1]
  viewrow1[2][2] = map[myxpos][myypos-1]
  viewrow1[3][2] = map[myxpos+1][myypos-1]
  '
  'need to check if we're going to read beyond the edge of the map...
  If myypos > 2 then
    'read the next row of map cells in front of the player
    viewrow1[1][3] = map[myxpos-1][myypos-2]
    viewrow1[2][3] = map[myxpos][myypos-2]
    viewrow1[3][3] = map[myxpos+1][myypos-2]
  EndIf
  If myypos > 3 Then
    'read the next row of map cells in front of the player
    viewrow1[1][4] = map[myxpos-1][myypos-3]
    viewrow1[2][4] = map[myxpos][myypos-3]
    viewrow1[3][4] = map[myxpos+1][myypos-3]
  EndIf
  If myypos > 4 Then
    'read the next row of map cells in front of the player
    viewrow1[1][5] = map[myxpos-1][myypos-4]
    viewrow1[2][5] = map[myxpos][myypos-4]
    viewrow1[3][5] = map[myxpos+1][myypos-4]
  EndIf  
  If myypos > 5 Then
    'read the next row of map cells in front of the player
    viewrow1[1][6] = map[myxpos-1][myypos-5]
    viewrow1[2][6] = map[myxpos][myypos-5]
    viewrow1[3][6] = map[myxpos+1][myypos-5]
  EndIf    
EndSub

Sub minimape
  'the player is facing east
  'read the row of map cells in line with the player
  viewrow1[1][1] = map[myxpos][myypos-1]
  viewrow1[3][1] = map[myxpos][myypos+1]
  '
  'read the 1st row of map cells in front of the player
  viewrow1[1][2] = map[myxpos+1][myypos-1]
  viewrow1[2][2] = map[myxpos+1][myypos]
  viewrow1[3][2] = map[myxpos+1][myypos+1]
  '
  'need to check if we're going to read beyond the edge of the map...
  If myxpos < mapsizex-1 then
    'read the next row of map cells in front of the player
    viewrow1[1][3] = map[myxpos+2][myypos-1]
    viewrow1[2][3] = map[myxpos+2][myypos]
    viewrow1[3][3] = map[myxpos+2][myypos+1]
  EndIf
  If myxpos < mapsizex-2 Then
    'read the next row of map cells in front of the player
    viewrow1[1][4] = map[myxpos+3][myypos-1]
    viewrow1[2][4] = map[myxpos+3][myypos]
    viewrow1[3][4] = map[myxpos+3][myypos+1]
  EndIf
  If myxpos < mapsizex-3 Then
    'read the next row of map cells in front of the player
    viewrow1[1][5] = map[myxpos+4][myypos-1]
    viewrow1[2][5] = map[myxpos+4][myypos]
    viewrow1[3][5] = map[myxpos+4][myypos+1]
  EndIf
  If myxpos < mapsizex-4 Then
    'read the next row of map cells in front of the player
    viewrow1[1][6] = map[myxpos+5][myypos-1]
    viewrow1[2][6] = map[myxpos+5][myypos]
    viewrow1[3][6] = map[myxpos+5][myypos+1]
  EndIf
EndSub

Sub minimaps
  'the player is facing south...
  'read the row of map cells in line with the player
  viewrow1[1][1] = map[myxpos+1][myypos]
  viewrow1[3][1] = map[myxpos-1][myypos]
  '
  'read the 1st row of map cells in front of the player
  viewrow1[1][2] = map[myxpos+1][myypos+1]
  viewrow1[2][2] = map[myxpos][myypos+1]
  viewrow1[3][2] = map[myxpos-1][myypos+1]
  '
  'need to check if we're going to read beyond the edge of the map...
  If myypos < mapsizey-1 then
    'read the next row of map cells in front of the player
    viewrow1[1][3] = map[myxpos+1][myypos+2]
    viewrow1[2][3] = map[myxpos][myypos+2]
    viewrow1[3][3] = map[myxpos-1][myypos+2]
  EndIf
  If myypos < mapsizey-2 Then
    'read the next row of map cells in front of the player
    viewrow1[1][4] = map[myxpos+1][myypos+3]
    viewrow1[2][4] = map[myxpos][myypos+3]
    viewrow1[3][4] = map[myxpos-1][myypos+3]
  EndIf
  If myypos < mapsizey-3 Then
    'read the next row of map cells in front of the player
    viewrow1[1][5] = map[myxpos+1][myypos+4]
    viewrow1[2][5] = map[myxpos][myypos+4]
    viewrow1[3][5] = map[myxpos-1][myypos+4]
  EndIf
  If myypos < mapsizey-4 Then
    'read the next row of map cells in front of the player
    viewrow1[1][6] = map[myxpos+1][myypos+5]
    viewrow1[2][6] = map[myxpos][myypos+5]
    viewrow1[3][6] = map[myxpos-1][myypos+5]
  EndIf    
EndSub

Sub minimapw
  'the player is facing west...
  'read the row of map cells in line with the player
  viewrow1[1][1] = map[myxpos][myypos+1]
  viewrow1[3][1] = map[myxpos][myypos-1]
  '
  'read the 1st row of map cells in front of the player
  viewrow1[1][2] = map[myxpos-1][myypos+1]
  viewrow1[2][2] = map[myxpos-1][myypos]
  viewrow1[3][2] = map[myxpos-1][myypos-1]
  '
  'need to check if we're going to read beyond the edge of the map...
  If myxpos > 2 then
    'read the next row of map cells in front of the player
    viewrow1[1][3] = map[myxpos-2][myypos+1]
    viewrow1[2][3] = map[myxpos-2][myypos]
    viewrow1[3][3] = map[myxpos-2][myypos-1]
  EndIf
  If myxpos > 3 Then
    'read the next row of map cells in front of the player
    viewrow1[1][4] = map[myxpos-3][myypos+1]
    viewrow1[2][4] = map[myxpos-3][myypos]
    viewrow1[3][4] = map[myxpos-3][myypos-1]
  EndIf
  If myxpos > 4 Then
    'read the next row of map cells in front of the player
    viewrow1[1][5] = map[myxpos-4][myypos+1]
    viewrow1[2][5] = map[myxpos-4][myypos]
    viewrow1[3][5] = map[myxpos-4][myypos-1]
  EndIf
  If myxpos > 5 Then
    'read the next row of map cells in front of the player
    viewrow1[1][6] = map[myxpos-5][myypos+1]
    viewrow1[2][6] = map[myxpos-5][myypos]
    viewrow1[3][6] = map[myxpos-5][myypos-1]
  EndIf
EndSub

Sub definemap
  'trying to set up a small map
  'and covert it into a two dimensional array
  '
  'map set up as text strings to begin with in a single dimension array
  '
  '
  'define the starting position, and direction to face in the map
  startx = 20
  starty = 20
  startdir = "w"
  '
  'define the map in the mapline array as strings
  mapline[1] =  "111111111111111111111"
  mapline[2] =  "100000001001000010001
  mapline[3] =  "101110101101101010111
  mapline[4] =  "100000100000101010001
  mapline[5] =  "101110101110101011101
  mapline[6] =  "101010001000001000001
  mapline[7] =  "101011111011101111101
  mapline[8] =  "100010000010001000101
  mapline[9] =  "111110111010101010101
  mapline[10] = "100000100000001010101
  mapline[11] = "101111101010111011101
  mapline[12] = "100000101010101000101
  mapline[13] = "101110101010101110101
  mapline[14] = "100010001000000010001
  mapline[15] = "101111111011111011011
  mapline[16] = "101000100010000000001
  mapline[17] = "111010101110101101101
  mapline[18] = "101010001000100000001
  mapline[19] = "101010101011101101111
  mapline[20] = "100000001000001000001
  mapline[21] = "111111111111111111111
  
  ' 
  ' define some parameters that state how big the map is
  mapsizex = Text.GetLength (mapline[1])
  mapsizey = array.GetItemCount (mapline)
  TextWindow.WriteLine ("mapsizex = " + mapsizex + " mapsizey = "+ mapsizey)
  '
  'try to read this in and convert it into a two dimensional array
  For yloop = 1 To mapsizey
    For xloop = 1 To mapsizex
      map[xloop][yloop] = Text.GetSubText(mapline[yloop],xloop,1)
    EndFor
  EndFor
  '
'  'now print the contents of the mapline array and see if it's the same as
'  'the input data
'  '
 For yloop1 = 1 To mapsizey
    For xloop1 = 1 To mapsizex
      Textwindow.CursorTop = yloop1
      TextWindow.CursorLeft = xloop1-1
      TextWindow.WriteLine (map[xloop1][yloop1])
    EndFor
  EndFor
EndSub
  
Sub createblocks
  ' [block number][point][x/y/z]
  '
  'block1 face co-ordinates
  block[1][1][1] = -1.5   'x co-ord
  block[1][1][2] = -1   'y co-ord
  block[1][1][3] =  1   'z co-ord
  block[1][2][1] = -0.5
  block[1][2][2] = -1
  block[1][2][3] =  1
  block[1][3][1] = -1.5
  block[1][3][2] =  1
  block[1][3][3] =  1
  block[1][4][1] = -0.5
  block[1][4][2] =  1
  block[1][4][3] =  1
  block[1][5][1] = -0.5
  block[1][5][2] = -1
  block[1][5][3] =  2
  block[1][6][1] = -0.5
  block[1][6][2] =  1
  block[1][6][3] =  2

  'face co-ordinates for remaining blocks on left hand side...
  For a = 2 To 6
    For b = 1 To 6
      block[a][b][1] = block[1][b][1]
      block[a][b][2] = block[1][b][2]
      block[a][b][3] = block[1][b][3]+(a-1)
    EndFor
  EndFor
  '
  For a = 8 To 12
    For b = 1 To 4
      block[a][b][1] = block[1][b][1]+1
      block[a][b][2] = block[1][b][2]
      block[a][b][3] = block[1][b][3]+(a-7)
    EndFor
  EndFor

  'face co-ordinates for remaining blocks on right hand side...
  'x co-ord mutliplied by -1 to flip the x axis
  For a = 13 To 18
    For b = 1 To 6
      c = a-12
      block[a][b][1] = block[c][b][1]*-1
      block[a][b][2] = block[c][b][2]
      block[a][b][3] = block[c][b][3]
    EndFor
  EndFor
  ' clip blocks 2 and 14 so that their front faces don't overlap the edges of the draw window
  block[2][1][1] = -1
  block[2][3][1] = -1  
  block[14][1][1] = 1
  block[14][3][1] = 1
EndSub
  
Sub setupcolours
colours[1] = "#B0B0B0"
colours[2] = "#808080"
colours[3] = "#505050"
colours[4] = "#303030"
colours[5] = "#202020"
colours[6] = "#101010"
For a = 1 To 6
  TextWindow.WriteLine ("Colour " + a + " is " +colours[a])
EndFor

EndSub
' Minesweeper for Small Basic 0.1b
' Copyright (c) 2013 Nonki Takahashi.  All rights reserved.
'
' History:
'  0.1b 07/05/2013 Created.
'
GraphicsWindow.Title = "Minesweeper for Small Basic 0.1b"
Init()
While "True"
  Game()
  playing = "True"
  While playing
    Program.Delay(500)
  EndWhile
EndWhile
Sub Init
  CRLF = Text.GetCharacter(13) + Text.GetCharacter(10)
  nMines = 10
  nCols = 9
  nRows = 9
  bgColor = "#949FB5"
  cellColor = "#D6E3F3"
  coverColor = "#4A64CF"
  frameColor = "#222323"
  color = "1=#414FBD;2=#206602;3=#AA0406;4=#020282;5=#790101;6=#06787F;7=#A70604;8=#AA0808;✸=Black;"
  GraphicsWindow.BackgroundColor = bgColor
  x0 = 31
  y0 = 30
  sizeX = 31
  sizeY = 30
  GraphicsWindow.Width = (nCols + 2) * sizeX
  GraphicsWindow.Height = (nRows + 3) * sizeY
  GraphicsWindow.BrushColor = "Black"
  x = x0
  y = y0 + (nRows + 0.5) * sizeY
  GraphicsWindow.FontSize = sizeY
  GraphicsWindow.DrawText(x, y - 0.12 * sizeY, "◯")
  GraphicsWindow.FontSize = sizeY * 0.8
  GraphicsWindow.DrawText(x + 0.09 * sizeX, y + 0.02 * sizeY, "└")
  GraphicsWindow.FontSize = sizeY
  x = x0 + (nCols - 1) * sizeX
  GraphicsWindow.DrawText(x, y - 0.12 * sizeY, "✸")
  x = x0 + sizeX
  GraphicsWindow.FontSize = sizeY * 0.6
  oTime = Controls.AddTextBox(x, y)
  Controls.SetSize(oTime, 2 * sizeX, sizeY)
  x = x0 + (nCols - 3) * sizeX
  oMines = Controls.AddTextBox(x, y)
  GraphicsWindow.FontSize = sizeY
  Controls.SetSize(oMines, 2 * sizeX, sizeY)
  dirCol = "1=1;2=1;3=0;4=-1;5=-1;6=-1;7=0;8=1;"
  dirRow = "1=0;2=-1;3=-1;4=-1;5=0;6=1;7=1;8=1;"
' The following line could be harmful and has been automatically commented.
'   path = File.GetSettingsFilePath()
' The following line could be harmful and has been automatically commented.
'   settings = File.ReadContents(path)
  If settings["nWins"] = "" Then
    settings["nWins"] = 0
  EndIf
  If settings["nPlays"] = "" Then
    settings["nPlays"] = 0
  EndIf
  If settings["record"] = "" Then
    settings["record"] = 999
  EndIf
' The following line could be harmful and has been automatically commented.
'   File.WriteContents(path, settings)
EndSub
Sub Game
  time = 0
  covered = nCols * nRows
  Controls.SetTextBoxText(oTime, time)
  Controls.SetTextBoxText(oMines, nMines)
  CreateStage()
  ShowStage()
  waiting = "True"
  Timer.Interval = 1000
  Timer.Pause()
  GraphicsWindow.MouseDown = OnMouseDown
EndSub
Sub OnMouseDown
  GraphicsWindow.MouseDown = DoNothing
  x = GraphicsWindow.MouseX
  y = GraphicsWindow.MouseY
  iCol = Math.Floor((x - x0) / sizeX) + 1
  iRow = Math.Floor((y - y0) / sizeY) + 1
  If cover[iCol][iRow] <> "" Then
    If waiting Then
      waiting = "False"
      Timer.Tick = OnTick
      Timer.Resume()
    EndIf
    OpenCover()
  EndIf
  GraphicsWindow.MouseDown = OnMouseDown
EndSub
Sub DoNothing
  OnMouseDown = ""
EndSub
Sub OnTick
  time = time + 1
  Controls.SetTextBoxText(oTime, time)  
EndSub
Sub OpenCover
  Shapes.Remove(cover[iCol][iRow])
  cover[iCol][iRow] = ""
  covered = covered - 1
  If stage[iCol][iRow] = "" Then
    If nMines < covered Then
      checked = ""
      OpenAdjacents()
    EndIf
    If nMines = covered Then
      Win()
    EndIf
  ElseIf stage[iCol][iRow] = "✸" Then
    Lose()
  Else ' numbers
    If covered = nMines Then
      Win()
    EndIf
  EndIf
EndSub
Sub Win
  Timer.Pause()
  If time < settings["record"] Then
    settings["record"] = time
  EndIf
  settings["nWins"] = settings["nWins"] + 1
  settings["nPlays"] = settings["nPlays"] + 1
' The following line could be harmful and has been automatically commented.
'   File.WriteContents(path, settings)
  SetMessage()
  GraphicsWindow.ShowMessage(msg, "You win")
  time = 0
  playing = "False"
EndSub
Sub Lose
  Timer.Pause()
  OpenMines()
  settings["nPlays"] = settings["nPlays"] + 1
' The following line could be harmful and has been automatically commented.
'   File.WriteContents(path, settings)
  SetMessage()
  GraphicsWindow.ShowMessage(msg, "You lose")
  time = 0
  playing = "False"
EndSub
Sub SetMessage
  msg = "Time: " + time + " sec" + CRLF
  msg = msg + "High Score: " + settings["record"] + " sec" + CRLF
  msg = msg + "Game Play Times: " + settings["nPlays"] + CRLF
  msg = msg + "Wins: " + settings["nWins"] + CRLF
  msg = msg + "Rate: " + Math.Floor(settings["nWins"] / settings["nPlays"] * 100) + " %"
EndSub  
Sub OpenAdjacents
  ' param iCol, iRow - space cell
  checked[iCol][iRow] = "True" 
  For dir = 1 To 8
    Stack.PushValue("local", iCol)
    Stack.PushValue("local", iRow)
    Stack.PushValue("local", dir)
    iCol = iCol + dirCol[dir]
    iRow = iRow + dirRow[dir]
    If (1 <= iCol) And (iCol <= nCols) And (1 <= iRow) And (iRow <= nRows) Then
      If checked[iCol][iRow] = "" Then
        If cover[iCol][iRow] <> "" Then
          Shapes.Remove(cover[iCol][iRow])
          cover[iCol][iRow] = ""
          covered = covered - 1
        EndIf
        If stage[iCol][iRow] = "" Then
          OpenAdjacents()
        Else
          checked[iCol][iRow] = "True" 
        EndIf
      EndIf
    EndIf
    dir = Stack.PopValue("local")
    iRow = Stack.PopValue("local")
    iCol = Stack.PopValue("local")
  EndFor
EndSub
Sub OpenMines
  For iRow = 1 To nRows
    For iCol = 1 To nCols
      If stage[iCol][iRow] = "✸" Then
        Shapes.HideShape(cover[iCol][iRow])
      EndIf
    EndFor
  EndFor
EndSub
Sub CreateStage
  stage = ""
  For iMine = 1 To nMines
    iCol = Math.GetRandomNumber(nCols)
    iRow = Math.GetRandomNumber(nRows)
    While stage[iCol][iRow] = "✸"
      iCol = Math.GetRandomNumber(nCols)
      iRow = Math.GetRandomNumber(nRows)
    EndWhile
    stage[iCol][iRow] = "✸"
  EndFor
  For iRow = 1 To nRows
    For iCol = 1 To nCols
      AddNumbers()
    EndFor
  EndFor
EndSub
Sub AddNumbers
  If stage[iCol][iRow] = "✸" Then
    For dir = 1 To 8
      jCol = iCol + dirCol[dir]
      jRow = iRow + dirRow[dir]
      If (1 <= jCol) And (jCol <= nCols) And (1 <= jRow) And (jRow <= nRows) And (stage[jCol][jRow] <> "✸") Then
        stage[jCol][jRow] = stage[jCol][jRow] + 1
      EndIf
    EndFor
  EndIf
EndSub
Sub ShowStage
  GraphicsWindow.FontSize = sizeY
  For iRow = 1 To nRows
    For iCol = 1 To nCols
      x = x0 + (iCol - 1) * sizeX
      y = y0 + (iRow - 1) * sizeY
      ShowCover()
      ShowCell()
    EndFor
  EndFor
EndSub
Sub ShowCover
  ' param iCol, iRow - to show
  ' param x, y - left top coordinate
  GraphicsWindow.BrushColor = coverColor
  GraphicsWindow.PenColor = frameColor
  If cover[iCol][iRow] = "" Then
    cover[iCol][iRow] = Shapes.AddRectangle(sizeX, sizeY)
    Shapes.HideShape(cover[iCol][iRow])
    Shapes.Move(cover[iCol][iRow], x, y)
  EndIf
  Shapes.ShowShape(cover[iCol][iRow])
EndSub
Sub ShowCell
  ' param iCol, iRow - to show
  ' param x, y - left top coordinate
  GraphicsWindow.BrushColor = cellColor
  GraphicsWindow.FillRectangle(x, y, sizeX, sizeY)
  GraphicsWindow.PenColor = frameColor
  GraphicsWindow.DrawRectangle(x, y, sizeX, sizeY)
  GraphicsWindow.BrushColor = color[stage[iCol][iRow]]
  If stage[iCol][iRow] = "✸" Then
    dx = 0
  Else
    dx = 0.2 * sizeX
  EndIf
  GraphicsWindow.DrawText(x + dx, y - 0.12 * sizeY, stage[iCol][iRow])
EndSub
'  Challenge of the month September 2012     Wave      by  NaochanON


gui()
shipimage()   
while "true"
  MM=MM+1
  wave()
  Program.Delay(20)
endwhile

Sub wave
  PY=math.Abs(Math.Cos(math.GetRadians(MM/10)))     '  decide wave height 
  For NN=-10 To 280 
    Shapes.move(rect[NN],Shapes.GetLeft(rect[NN]),math.sin(Math.GetRadians(NN+MM))*200*PY+300)
    If NN=90 Then                                   '  ship position 
      shpy= Shapes.GetTop(rect[NN])-SH/2
      shpx= Shapes.GetLeft(ship)
      GraphicsWindow.Title=" Wave height =  "+(300-(shpy+SH))
      shpy2= Shapes.GetTop(rect[NN+SW/DP])-SH/2   
      angle= Math.GetDegrees(Math.ArcTan((shpy2-shpy)/SW))  '   get angle of ship 
      shipmoving()
    EndIf
  endfor
EndSub

Sub gui
  GraphicsWindow.Hide()
  GraphicsWindow.BackgroundColor="lightcyan"
  GraphicsWindow.Width=1200
  GraphicsWindow.Height=500
  GraphicsWindow.BrushColor="Blue"
  GraphicsWindow.PenColor="Blue"
  DP=5                                     '   wave pitch 
  For I=-10 To 280
    rect[I] = Shapes.AddRectangle(DP,1000)
    Shapes.move(rect[I],I*DP,math.sin(Math.GetRadians(i*DP/5))*200+300)  '   initial wave
    If i=90 Then 
      shpX= Shapes.GetLeft(rect[I])       '  ship position 
      shpy= Shapes.Gettop(rect[I]) -SH/2  
    EndIf
  EndFor
EndSub

Sub shipimage
  ' -------------------  ship  image ----------------------------------
  sW=100           '  ship length
  sH=20           '  ship height
  tW=6            '  head or trail  triangle width
  tH=sH-6          '  head or trail  triangle  height
  GraphicsWindow.BrushColor="darkgreen"
  GraphicsWindow.PenColor="darkgreen"
  tri1=Shapes.AddTriangle(-tw,0,0,0,0,tH)  ' trail
  tri2=Shapes.AddTriangle(sw,0,sw+tW,0,sw,tH)   ' head
  ship= Shapes.AddRectangle(sW,sH)        ' body 
  GraphicsWindow.BrushColor="lightcyan"
  GraphicsWindow.PenColor="Red"
  For i=1 To 6
    window[i]= Shapes.AddEllipse(8,8)   '  window
  EndFor
  angle=0
  shipmoving()  
  GraphicsWindow.Show()
EndSub

Sub shipmoving
  Shapes.Move(tri1,shpX,shpY)
  Shapes.Move(tri2,ShpX,shpY)
  Shapes.Move(ship,ShpX,ShpY)
  Shapes.Rotate(ship,angle) 
  Shapes.Rotate(tri1,angle) 
  Shapes.Rotate(tri2,angle) 
  For i=1 To 6
    dx=Math.Cos(Math.GetRadians(angle))
    dy=Math.sin(Math.GetRadians(angle)) 
    Shapes.Move(window[i],ShpX+(i*14*dx), ShpY+5+(i*14*dy))  
  EndFor
EndSub
    
'left click to add particles
'right click to move the particles right
'Made by Sam Guard, with help from LitDev
'KQR030
GraphicsWindow.Width = 400
GraphicsWindow.Height = 400
GraphicsWindow.Top = 10
l = 0
air = 1.1
grav = 0.1
dmp = 5
cdmp = 1
range = 40
diff = 10
close = 1
speed = 10
n = 2
size = 30
n2 = 1.5
sl = 1.1
jk = 10000
Sub sp
  For spawn = 1 To 6
    For spawn2 = 1 To 6
      am = am + 1
      x[am] = GraphicsWindow.MouseX-90+(30*spawn)
      y[am] = GraphicsWindow.MouseY-90+(30*spawn2)
      fx[am] = 0
      fy[am] = 0
      p[am] = Shapes.AddEllipse(size,size)
    EndFor
  EndFor
EndSub

'LitDev__________________________
While 1=1
  start = Clock.ElapsedMilliseconds
  
  update()
  
  delay = 80 - (Clock.ElapsedMilliseconds-start)
  If (delay > 0) Then
    Program.Delay(delay)
  EndIf
EndWhile
'LitDev__________________________

Sub update
  If Mouse.IsLeftButtonDown Then
    sp()
  EndIf
  If Mouse.IsRightButtonDown Then
    rmouse()
  EndIf
  For d = 1 To 2
    For it = 1 To 2
      draw()
      box()
    EndFor
    iter()
  EndFor
  col()
EndSub

Sub draw
  For i = 1 To am
    Shapes.Move(p[i],x[i]-15,y[i]-15)
  EndFor
EndSub

Sub iter
  For i = 1 To am
    x[i] = x[i] + fx[i] * speed
    y[i] = y[i] + fy[i] * speed
  EndFor
EndSub

Sub col
  For i = 1 To am
    fy[i] = fy[i] + grav
    For c = i+1 To am      
      dif1 = x[i] - x[c]
      dif2 = y[i] - y[c]
      If dif1 < 0 Then
        dif1 = -dif1
        minx = 1
      Else
        minx = 0
      EndIf
      If dif2 < 0 Then
        dif2 = -dif2
        miny = 1
      Else
        miny = 0
      EndIf
      dst = Math.SquareRoot(Math.Power(dif1,2) + Math.Power(dif2,2))
      If dst < range Then
        If minx = 1 then  
          fx[i] = fx[i] - (dmp/dst)
          fx[c] = fx[c] + (dmp/dst)
          fx[i] = fx[i] / sl
        Else
          fx[i] = fx[i] + (dmp/dst)
          fx[c] = fx[c] - (dmp/dst)
          fx[i] = fx[i] / sl
        EndIf
        If miny = 1 then  
          fy[i] = fy[i] - (dmp/dst)
          fy[c] = fy[c] + (dmp/dst)
          fy[i] = fy[i] / sl
        Else
          fy[i] = fy[i] + (dmp/dst)
          fy[c] = fy[c] - (dmp/dst)
          fy[i] = fy[i] / sl
        EndIf
      EndIf
      If dst > range+diff And dst < range+(diff*2) Then
        If minx = 1 then  
          fx[i] = fx[i] + (cdmp/dst)
        Else
          fx[i] = fx[i] - (cdmp/dst)
        EndIf
        If miny = 1 then  
          fy[i] = fy[i] + (cdmp/dst)
        Else
          fy[i] = fy[i] - (cdmp/dst)
        EndIf
      EndIf
    EndFor
  EndFor
EndSub

Sub rmouse
  For i = 1 To am
    For m = 1 To am
      dif1 = x[i] - GraphicsWindow.MouseX
      dif2 = y[i] - GraphicsWindow.MouseY
      If dif1 < 0 Then
        dif1 = -dif1
        minx = 1
      Else
        minx = 0
      EndIf
      If dif2 < 0 Then
        dif2 = -dif2
        miny = 1
      Else
        miny = 0
      EndIf
      If minx = 1 then  
        fx[i] = fx[i] + (dst/jk)
      Else
        fx[i] = fx[i] - (dst/jk)
      EndIf
      If miny = 1 then  
        fy[i] = fy[i] + (dst/jk)
      Else
        fy[i] = fy[i] - (dst/jk)
      EndIf
    EndFor
    
    
  EndFor
EndSub

Sub box
  For i = 1 To am
    '_____________box_____________
    fy[i] = fy[i]/air
    if y[i] > 400 Then
      If fy[i] > 0 Then
        y[i] = 400
        fy[i] = -fy[i]/4
      Else
        fx[i] = fx[i]/air
      EndIf
    Elseif y[i] < 0 and close = 1 Then
      If fy[i] < 0 Then
        y[i] = 0
        fy[i] = -fy[i]/2
      EndIf
    EndIf
    If x[i] < 0 Then
      If fx[i] < 0 Then 
        x[i] = 0
        fx[i] = -fx[i]/2
      EndIf
    ElseIf x[i] > 400 Then
      If fx[i] > 0 Then 
        x[i] = 400
        fx[i] = -fx[i]/2
      EndIf
    EndIf
  EndFor
  '_____________box_end_____________
EndSub
' Piano 0.1
' Copyright (c) 2010, 2012 Nonki Takahshi.  All rights reserved.
'
' History : 
' 0.1 2012/08/07 Title and background color added.
' 0.0 2010/07/21 Created for the 25 line challange in Small Basic Forum ()
'
GraphicsWindow.Title = "Piano 0.1"
GraphicsWindow.BackgroundColor = "#222222"
sKey = "awsedftgyhujkolp;"
sSharp = "## ### ## "
sWhite = "ASDFGHJKL;"
sBlack = "WE TYU OP "
sMML = "O4C8 O4C#8O4D8 O4D#8O4E8 O4F8 O4F#8O4G8 O4G#8O4A8 O4A#8O4B8 O5C8 O5C#8O5D8 O5D#8O5E8 "
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(107, 110, 400, 200)
For i = 1 To 10
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawRectangle(67 + i * 40, 110, 40, 200)
  GraphicsWindow.DrawText(70 + i * 40, 290, Text.GetSubText(sWhite, i, 1))
  If Text.GetSubText(sSharp, i, 1) = "#" Then
    GraphicsWindow.FillRectangle(91 + i * 40, 110, 32, 140)
    GraphicsWindow.BrushColor = "White"
    GraphicsWindow.DrawText(94 + i * 40, 230, Text.GetSubText(sBlack, i, 1))
  EndIf  
EndFor  
GraphicsWindow.KeyUp = OnKeyUp
While "True"
  Program.Delay(500)
EndWhile

Sub OnKeyUp
  sLast = GraphicsWindow.LastText
  sNote = Text.GetSubText(sMML, (Text.GetIndexOf(sKey, sLast) - 1) * 5 + 1, 5)
  Sound.PlayMusic(sNote)
EndSub
'Paddle game extended a bit with fireworks for winners

' set GraphicsWindow window size
gh=600
gw=800
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh

'Paddle width, length and ball size (diameter)
padsize = 12
padlength = 120
ballsize = 32
'Number of ball hits for a win
winscore = 5

' Restart game
Restart:

'Set main game window properties and paddles/ball
GraphicsWindow.Clear()
GraphicsWindow.PenColor = "Black"
GraphicsWindow.BackgroundColor = "lightblue"
GraphicsWindow.BrushColor = "darkblue"
paddle1 = Shapes.AddRectangle(padlength, padsize)
paddle2 = Shapes.AddRectangle(padlength, padsize)
paddle3 = Shapes.AddRectangle(padsize, padlength)
paddle4 = Shapes.AddRectangle(padsize, padlength)
GraphicsWindow.BrushColor = "red"
ball = Shapes.AddEllipse(ballsize,ballsize)

'Allow mouse event to redraw paddles
GraphicsWindow.MouseMove = OnMouseMove

'Initialise random ball position and velocity (deltaX,deltaY)
x = gw/4+Math.GetRandomNumber(gw/2)
y = gh/4+Math.GetRandomNumber(gh/2)
deltaX = (Math.GetRandomNumber(11)-6)/5
deltaY = (Math.GetRandomNumber(11)-6)/5
'We want a non-zero initial velocity in x and y directions to get it going
If (deltaX > -0.5 And deltaX < 0.5) then
  deltaX = 0.5
endif
If (deltaY > -0.5 And deltaY < 0.5) then
  deltaY = 0.5
endif
'Set some gravity and speedup with each bounce
gravity = math.GetRandomNumber(10)/1000
bounce = 1+math.GetRandomNumber(10)/100
'Initialise score and pause flag to not-paused (left mouse click)
score = 0
pause = 0

'Update ball loop
RunLoop:

'New ball position
x = x + deltaX
y = y + deltaY

'Assume mouse position is at paddle centres
padX = GraphicsWindow.MouseX-padlength/2
padY = GraphicsWindow.MouseY-padlength/2

'Top paddle
If (y <= padsize + ballsize/2 and x >= padX and x <= padX + padlength) Then
  deltaY = -deltaY*bounce
  y = padsize + ballsize/2  'Since y is not integer, make sure we start on paddle when bouncing away - prevents double hits
  Sound.PlayClick()
  score = score+1
EndIf
'Bottom paddle
If (y >= gh - padsize - ballsize/2 and x >= padX and x <= padX + padlength) Then
  deltaY = -deltaY*bounce
  y = gh - padsize - ballsize/2
  Sound.PlayClick()
  score = score+1
EndIf
'Left paddle
If (x <= padsize + ballsize/2 and y >= padY and y <= padY + padlength) Then
  deltaX = -deltaX*bounce
  x = padsize + ballsize/2
  Sound.PlayClick()
  score = score+1
EndIf
'Right paddle
If (x >= gw - padsize - ballsize/2 and y >= padY and y <= padY + padlength) Then
  deltaX = -deltaX*bounce
  x = gw - padsize - ballsize/2
  Sound.PlayClick()
  score = score+1
EndIf

'Crude pause toggle option on left mouse click - e.g. allows window repositioning - resizing causes all sorts of obvious problems
'Can be used as a cheat since the paddles move when paused
wait:
If (Mouse.IsLeftButtonDown) then
  pause = 1-pause
  Program.Delay(250)
endif
If (pause = 1) then
  Goto wait
endif

'Redraw ball - since coords for drawing are top left, remove radius (ballsize/2) to keep centred on x,y
Shapes.Move(ball, x-ballsize/2, y-ballsize/2)

'Delay to suit game
Program.Delay(5)

'If inside window add gravity to y(downwards) velocity and do next ball position update
If (x > 0 And x < gw and y > 0 And y < gh) Then
  deltaY = deltaY + gravity
  Goto RunLoop
EndIf

'The ball has left the window - winscore or more hits is a win
If (score >= winscore) then
  Goto Win
endif

'less than winscore hits is a loose - restart game
GraphicsWindow.ShowMessage("You Lose", "Paddle")
Goto Restart

'If we win then fireworks display, with a bell ring to start
Win:

Sound.PlayBellRingAndWait()

'Start fireworks display
start:

'Initialise graphics dispay, firework count and max number of fireworks
GraphicsWindow.Clear()
GraphicsWindow.BackgroundColor = "Black"
count = 0
maxcount = 10

'Set a random set of stars, the randon RGB are designed to be dimish 'off white'
For i = 1 To gh
  x=math.GetRandomNumber(gw)
  y=math.GetRandomNumber(gh)
  size=math.GetRandomNumber(8)
  R=100+math.GetRandomNumber(55)
  G=100+math.GetRandomNumber(55)
  B=100+math.GetRandomNumber(55)
  GraphicsWindow.BrushColor=GraphicsWindow.GetColorFromRGB(R,G,B)
  GraphicsWindow.FillEllipse(x,y,size,size)
EndFor

'loop for each firework
next:

'Update firework count
count = count+1

'Set a random start and end for rocket
startx=math.GetRandomNumber(gw)
starty=gh
endx=50+math.GetRandomNumber(gw-100)
endy=20+math.GetRandomNumber(gh/2)

'Use a random number to set the colour - these are designed to be bright near primary
'Red, Green, Blue, Cyan, Yellow, Magenta
rand = math.GetRandomNumber(6)
If (rand=1) Then
  R=254
  G=math.GetRandomNumber(100)
  B=0
EndIf
If (rand=2) Then
  G=254
  B=math.GetRandomNumber(100)
  R=0
EndIf
If (rand=3) Then
  B=254
  R=math.GetRandomNumber(100)
  G=0
EndIf
If (rand=4) Then
  R=254
  G=254
  B=math.GetRandomNumber(100)
EndIf
If (rand=5) Then
  G=254
  B=254
  R=math.GetRandomNumber(100)
EndIf
If (rand=6) Then
  B=254
  R=254
  G=math.GetRandomNumber(100)
EndIf

'Set our firework color and create a rocket (ball)
GraphicsWindow.PenColor = GraphicsWindow.GetColorFromRGB(R,G,B)
GraphicsWindow.BrushColor = GraphicsWindow.GetColorFromRGB(R,G,B)
ball = Shapes.AddEllipse(15,15)

'Draw the rocket trail from start to end
For i = 1 To 100
  x=startx+i/100*(endx-startx)
  y=starty+i/100*(endy-starty)
  Program.Delay(5)
  Shapes.Move(ball, x, y)
endfor
Shapes.Remove(ball)

'Draw the firework burst
'nlayer is the number of concentric layers
'nangle is the number of angular segments to the burst
nlayer = 50
nangle = 20
'Random gravity for burst
grav = Math.GetRandomNumber(5)/nlayer

'Draw with the firework colour(k=1), then overdraw in black (k=2) - this leaves a trace outline which may be an artifact, but looks ok
For k = 1 To 2
  If (k = 2) then
    'Overdraw in black - also do a bang
    GraphicsWindow.PenColor = "Black"
    GraphicsWindow.BrushColor = "Black"
    'Add you own bang!
'    Sound.PlayAndWait("C:\Users\Public\Documents\SmallBasic\bang_2.wav")
'    Sound.Stop("C:\Users\Public\Documents\SmallBasic\bang_2.wav")
  EndIf
  'A little text to show score above firework
  GraphicsWindow.DrawText(endx-50,endy-100,"Well Done! " + score + " Hits")
  'Loop over concentric layers
  For i = 1 To nlayer
    'Add a delay and set the radius(dist) and size of the burst points
    'These scalings are an attempt to make it OK with different nlayer - not guaranteed!
    Program.Delay(500/nlayer)
    dist = 200/nlayer*i
    size = 1+0.2*nlayer/math.SquareRoot(i)
    ' Loop over angle segments
    For j = 1 To nangle
      'Calculate coordinates of burst point, including the gravity term
      x=endx+dist*math.Cos(j/nangle*2*3.14)
      y=endy+dist*math.Sin(j/nangle*2*3.14)+grav*i*i
      'Draw burst point
      GraphicsWindow.FillEllipse(x,y,size,size)
    EndFor
    'Fireworks fade a little more slowly
    If (k = 2) Then
      Program.Delay(10)
    EndIf
  EndFor
  'Short delay between draw and black overdraw (erase)
  Program.Delay(300)
EndFor

'Limit the maximum number of fireworks
If (count = score Or count = maxcount) Then
  Goto end
EndIf

'Next firework
Goto next

end:

'Restart game
Goto Restart

'Position the paddles accoring to mouse position - remember keep mouse within game window!
Sub OnMouseMove
  paddleX = GraphicsWindow.MouseX
  Shapes.Move(paddle1, paddleX - padlength/2, 0)
  Shapes.Move(paddle2, paddleX - padlength/2, gh - padsize)
  paddleY = GraphicsWindow.MouseY
  Shapes.Move(paddle3, 0, paddleY - padlength/2)
  Shapes.Move(paddle4, gw - padsize, paddleY - padlength/2)
EndSub
' Ruler 0.2
' Copyright (c) 2012 Nonki Takahashi
'
' History :
' 0.2 2012/06/29 Ruler image version.
' 0.1 2012/06/29 Created.
'
GraphicsWindow.BackgroundColor = "White"
GraphicsWindow.BrushColor = "Green"
GraphicsWindow.Title = "Ruler 0.2"
x = 20
For i = 1 To 6
  s = i * 20
  GraphicsWindow.FillEllipse(x, 20, s, s)
  x = x + s + 20
EndFor
Ruler_Add()
Ruler_Loop()

Sub Ruler_Add
  uImage = "http://www.nonkit.com/smallbasic.files/ruler500.png"
  oImage = ImageList.LoadImage(uImage)
  ruler["angle"] = 0
  ruler["move"] = "False"
  ruler["moving"] = "False"
  ruler["clicked"] = "False"
  ruler["left"] = 0
  ruler["top"] = 0
  ruler["width"] = ImageList.GetWidthOfImage(oImage)
  ruler["height"] = ImageList.GetHeightOfImage(oImage)
  ruler["cx"] = ruler["left"] + ruler["width"] / 2
  ruler["cy"] = ruler["top"] + ruler["height"] / 2
  ruler["right"] = ruler["left"] + ruler["width"]
  ruler["bottom"] = ruler["top"] + ruler["height"]
  ruler["oRuler"] = Shapes.AddImage(uImage)
  Shapes.SetOpacity(ruler["oRuler"], 70)
  Shapes.Move(ruler["oRuler"], ruler["px"], ruler["py"])
EndSub

Sub Ruler_Loop
  GraphicsWindow.MouseUp = Ruler_OnMouseUp
  GraphicsWindow.MouseDown = Ruler_OnMouseDown
  While "True"
    Program.Delay(100)
    If ruler["move"] Then
      ruler["move"] = "False"
      x = ruler["movex"] - ruler["mousex"]
      y = ruler["movey"] - ruler["mousey"]
      Ruler_Move()
    EndIf
    If ruler["clicked"] Then
      ruler["clicked"] = "False"
      an = 90 - ruler["angle"]
      Ruler_Rotate()
    EndIf
  EndWhile
EndSub

Sub Ruler_OnMouseDown
  ruler["clicked"] = "N/A"
  x = GraphicsWindow.MouseX
  y = GraphicsWindow.MouseY
  If ruler["left"] <= x And x <= ruler["right"] And ruler["top"] <= y And y <= ruler["bottom"] Then
    ruler["mousex"] = x - ruler["cx"]
    ruler["mousey"] = y - ruler["cy"]
    ruler["move"] = "False"
    GraphicsWindow.MouseMove = Ruler_OnMouseMove
    ruler["moving"] = "True"
  EndIf
EndSub

Sub Ruler_OnMouseUp
  GraphicsWindow.MouseMove = Ruler_DoNothing
  ruler["moving"] = "False"
  If ruler["clicked"] = "N/A" Then
    ruler["clicked"] = "True"
  EndIf
EndSub

Ruler_OnMouseMove=""
Sub Ruler_OnMouseMove
  GraphicsWindow.MouseMove = Ruler_DoNothing
  ruler["clicked"] = "False"
  ruler["move"] = "True"
  ruler["movex"] = GraphicsWindow.MouseX
  ruler["movey"] = GraphicsWindow.MouseY
  GraphicsWindow.MouseMove = Ruler_OnMouseMove
EndSub

Sub Ruler_DoNothing
EndSub

Sub Ruler_Move
  ' param x, y 
  ruler["cx"] = x
  ruler["cy"] = y
  ruler["left"] = x - ruler["width"] / 2
  ruler["right"] = x + ruler["width"] / 2
  ruler["top"] = y - ruler["height"] / 2
  ruler["bottom"] = y + ruler["height"] / 2
  If ruler["angle"] = 0 Then
    px = ruler["left"]
    py = ruler["top"]
  ElseIf ruler["angle"] = 90 Then
    px = x - ruler["height"] / 2
    py = y - ruler["width"] / 2
  EndIf
  Shapes.Move(ruler["oRuler"], px, py)
EndSub
  
Sub Ruler_Rotate
  ' param an - angle 0 or 90
  If (an = 0 Or an = 90) And an <> ruler["angle"] Then
    ruler["angle"] = an
    Shapes.Rotate(ruler["oRuler"], an)
    height = ruler["width"]
    width = ruler["height"]
    ruler["width"] = width
    ruler["left"] = ruler["cx"] - width / 2
    ruler["right"] = ruler["cx"] + width / 2 
    ruler["height"] = height
    ruler["top"] = ruler["cy"] - height / 2
    ruler["bottom"] = ruler["cy"] + height / 2
  EndIf
EndSub
' SBace-Invaders-25 (v2) - A space invader game in under 25 lines by Davey~Wavey, Nov.2009, for Small Basic Forum.
' ===================================================================================
'
' Alien has increasing speed as it descends to increase difficulty, but you also get more score the faster they are!
' Aliens have different personalities (!) and drop further depending on their agression (i.e. a random number)
' You are rated on your score and your hit accuracy. You have 3 lives. Use your mouse to move your rocket and left mousebutton to fire.
' When an alien gets through your defences, they kill you off, then immediately regroup for another assault.
'
' See below game code for notes. Good Luck, civilization is depending on you!!!!!

' initialise game array
gamearry = "1=-1;-1=1;moveables=7;lives=3;ammo=0;score=0;aspeed=2;mx1=0;my1=0;mxo1=-3;myo1=0;m1=" + Shapes.AddEllipse(5,10) + ";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + Shapes.AddImage("http://www.tutorialized.com/upload/(2006.06.21-09:12:44)rocket50x50.jpg") + ";mxo3=-25;myo3=-25;mx3=" + ((GraphicsWindow.Width/2)-160) + ";my3=20;md3=-1;m3=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo4=-25;myo4=-25;mx4=" + ((GraphicsWindow.Width/2)-80) + ";my4=20;md4=-1;m4=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo5=-25;myo5=-25;mx5=" + (GraphicsWindow.Width/2) + ";my5=20;md5=-1;m5=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo6=-25;myo6=-25;mx6=" + ((GraphicsWindow.Width/2)+80) + ";my6=20;md6=-1;m6=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo7=-25;myo7=-25;mx7=" + ((GraphicsWindow.Width/2)+160) + ";my7=20;md7=-1;m7=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png")

While gamearry["lives"] > 0
  
  ' update alien and bullet positions
  gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + gamearry["ammo"] +";score=" + gamearry["score"] +";aspeed=" + gamearry["aspeed"] +";mx1=" + gamearry["mx1"] + ";my1=" + (gamearry["my1"] - gamearry["aspeed"]) +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + (gamearry["mx3"] + (gamearry[ gamearry["md3"] ] * gamearry["aspeed"] )) +";my3=" + gamearry["my3"] +";md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + (gamearry["mx4"] + (gamearry[ gamearry["md4"] ] * gamearry["aspeed"] )) + ";my4=" + gamearry["my4"] + ";md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + (gamearry["mx5"] + (gamearry[ gamearry["md5"] ] * gamearry["aspeed"] )) + ";my5=" + gamearry["my5"] + ";md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + (gamearry["mx6"] + (gamearry[ gamearry["md6"] ] * gamearry["aspeed"] )) + ";my6=" + gamearry["my6"] + ";md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + (gamearry["mx7"] + (gamearry[ gamearry["md7"] ] * gamearry["aspeed"] )) + ";my7=" + gamearry["my7"] + ";md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]
  
  ' move the bullet (m1),  gun (m2)  and aliens (m3+)
  For m=1 To gamearry["moveables"]
    
    ' put the shapes where they're supposed to be
    Shapes.Move(gamearry["m"+m], gamearry["mx"+m]+gamearry["mxo"+m], gamearry["my"+m]+gamearry["myo"+m])
    
    If m > 2 And ( math.abs( math.Floor(gamearry["mx1"]-(gamearry["mx"+m])) ) <25 ) And ( math.Abs( Math.Floor( gamearry["my1"]-gamearry["my"+m] ) ) < 10 ) Then
      ' bullet has collided with alien -  increase score and reset alien
      gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + gamearry["ammo"] +";score=" + (gamearry["score"]+10) +";aspeed=" + gamearry["aspeed"] +";mx1=" + gamearry["mx1"] + ";my1=-200;mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + gamearry["mx3"] +";my3=" + (gamearry["my3"]-(((gamearry["my3"]+80)*(math.Max(0,0-(Math.Remainder(m+10,3+10)*2)+1))))) +";md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + gamearry["mx4"] + ";my4=" + (gamearry["my4"]-((gamearry["my4"]+80)*(math.Max(0,0-(Math.Remainder(m,4)*2)+1)))) + ";md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + gamearry["mx5"] + ";my5=" + (gamearry["my5"]-((gamearry["my5"]+80)*(math.Max(0,0-(Math.Remainder(m,5)*2)+1)))) + ";md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + gamearry["mx6"] + ";my6=" + (gamearry["my6"]-((gamearry["my6"]+80)*(math.Max(0,0-(Math.Remainder(m,6)*2)+1)))) + ";md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + gamearry["mx7"] + ";my7=" + (gamearry["my7"]-((gamearry["my7"]+80)*(math.Max(0,0-(Math.Remainder(m,7)*2)+1)))) + ";md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]
      
      
    ElseIf m > 2 AND ( (gamearry["mx"+m] < 35) Or (gamearry["mx"+m] > GraphicsWindow.Width-55) ) Then
      ' alien has hit edge of screen, so bounce it and increase speed
      gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + gamearry["ammo"] +";score=" + gamearry["score"] +";aspeed=" + (gamearry["aspeed"]+0.01) +";mx1=" + gamearry["mx1"] + ";my1=" + gamearry["my1"] +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + gamearry["mx3"] +";my3=" + (gamearry["my3"]+((math.Max(0,0-(Math.Remainder(m+10,3+10)*4)+1))*(10+Math.GetRandomNumber(20)))) +";md3=" + gamearry[(gamearry["md3"]*(math.Max(-1,0-(Math.Remainder(m+10,3+10)*4)+1)))] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + gamearry["mx4"] + ";my4=" + (gamearry["my4"]+((math.Max(0,0-(Math.Remainder(m,4)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md4=" + gamearry[(gamearry["md4"]*(math.Max(-1,0-(Math.Remainder(m,4)*4)+1)))] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + gamearry["mx5"] + ";my5=" + (gamearry["my5"]+((math.Max(0,0-(Math.Remainder(m,5)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md5=" + gamearry[(gamearry["md5"]*(math.Max(-1,0-(Math.Remainder(m,5)*4)+1)))] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + gamearry["mx6"] + ";my6=" + (gamearry["my6"]+((math.Max(0,0-(Math.Remainder(m,6)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md6=" + gamearry[(gamearry["md6"]*(math.Max(-1,0-(Math.Remainder(m,6)*4)+1)))] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + gamearry["mx7"] + ";my7=" + (gamearry["my7"]+((math.Max(0,0-(Math.Remainder(m,7)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md7=" + gamearry[(gamearry["md7"]*(math.Max(-1,0-(Math.Remainder(m,7)*4)+1)))] + ";m7=" + gamearry["m7"]
      
      
    ElseIf (gamearry["my"+m] >= GraphicsWindow.Height-15) Then
      ' alien has reached the bottom - decrease life and reset alien.
      gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + (gamearry["lives"]-1) +";ammo=" + gamearry["ammo"] +";score=" + gamearry["score"] +";aspeed=" + (gamearry["aspeed"]-0.5) +";mx1=" + gamearry["mx1"] + ";my1=" + gamearry["my1"] +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + ((GraphicsWindow.Width/2)-160) + ";my3=20;md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + ((GraphicsWindow.Width/2)-80) + ";my4=20;md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + (GraphicsWindow.Width/2) + ";my5=20;md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + ((GraphicsWindow.Width/2)+80) + ";my6=20;md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + ((GraphicsWindow.Width/2)+160) + ";my7=20;md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]
      
      
    ElseIf Mouse.IsLeftButtonDown Then
      ' fire button pressed
      gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + (gamearry["ammo"]+1) +";score=" + gamearry["score"] +";aspeed=" + gamearry["aspeed"] +";mx1=" + (GraphicsWindow.mousex) + ";my1=" + (GraphicsWindow.Height-45) +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + gamearry["mx3"] +";my3=" + gamearry["my3"] +";md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + gamearry["mx4"] + ";my4=" + gamearry["my4"] + ";md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + gamearry["mx5"] + ";my5=" + gamearry["my5"] + ";md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + gamearry["mx6"] + ";my6=" + gamearry["my6"] + ";md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + gamearry["mx7"] + ";my7=" + gamearry["my7"] + ";md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]
    EndIf
  EndFor
  
  ' show status in titlebar
  GraphicsWindow.Title = "SBace-Invaders-25: SCORE=" + gamearry["score"] + "   LIVES=" + gamearry["lives"]
  
EndWhile

' Game Over!
GraphicsWindow.ShowMessage ("Well Done, you scored: " + gamearry["score"] + " and your Skill = " + Math.Floor((gamearry["score"]/gamearry["ammo"])*100) + "%", "<<< G-A-M-E   O-V-E-R >>>         ")



' =========================================================================================================
'
' NOTES: This looks more complex than it really is. Instead of defining any variables, I am using the array to handle everything.
'                 Unfortunately this means that every time I change a variable, I have to completely rebuild the array, hence the long 'gamearry' lines (yeah, they're LONG!)
'                If you compare them though, you'll see that only one, or maybe two, values change each time.
'               To cut down on lines, I'm also using the ElseIf's to handle the various checks, which means I only need one endif.
'
'               moveables = number of sprites to be moved (processed) each mainloop cycle
'               The strange '1=-1;-1=1' elements, along with 'md3,4,etc', allow me to simulate a logical 'NOT' type function when I need to bounce the alien. (i.e. md3=NOT md3)
'               mxo, myo are the offsets for each object (to centre object over its x,y)
'               md3,4,5,etc. are the direction of individual aliens (-1,+1)
'
'               Note that the calculations for collisions with alien 1 (m3) are slightly different in the arrays, due to 3 dividing into 3 and 6 without remainders.
'               If adding more aliens, the same issue will be found with alien 2 (m4) and new alien 6 (m8), etc.
'
'               CALCULATION TO RESET ALIEN WHEN HIT BY BULLET = (gamearry["my3"]-(gamearry["my3"]*(math.Max(0,0-(Math.Remainder(m,3)*2)+1))))
'               which 1) calculates the remainder of the alien number being checked divided by the loop number = No remainder for alien being processed!
'               then    2) multiplies the remainder by 2. Alien being processed stays as zero (as zero remainder times 2 still = zero)!
'               then    3) make value negative, then add one to the result. Alien being processed gets a value of 1, all others remain negative.
'               then    4) gets the highest (max) value comparing zero and the above result. Negatives give us zero, while alien being processed gives us 1.
'               then    5) multiply the y position of the alien by the above result. Gives us zero if this is not the alien being processed.
'               then    6) subtract the result above from the alien y position. If this is the alien being processed, it gets returned to the top of the screen. Yay!
'
'               (c) Dave~Wavey, 2009.  Please use this code only to produce further examples for the Small Basic forum to help others learn.
' Shapes 1.42
' Copyright (c) 2012 Nonki Takahashi.  All rights reserved.
'
' History :
'  1.42 2012/10/16 Minor bug fixed - open message remains. (TLW744-2)
'  1.41 2012/10/16 Minor bug fixed - line rotated. (TLW744-1)
'  1.4 2012/10/16 Supported cursor keys and new UI for shapes menu. (XFZ657-14)
'  1.31 2012/09/20 Minor bug fixed - pinches removed at consecutive shapes addition. (TLW744-0)
'  1.3 2012/09/20 Supported palette loading , consecutive shapes addition and (2). (XFZ657-13)
'  1.2 2012/09/20 Bug fixed (1) and supported short cut keys. (XFZ657-12)
'  1.12 2012/09/18 Bug fixed (select line from file). (XFZ657-11)
'  1.1 2012/09/18 Supported file input. (TLW744)
'  1.0 2012/09/15 Supported copy and paste. (XFZ657-10)
'
' Bug fix :
'  (1) No rotation frame after paste
'  (2) Pinches came under a shape after pen or brush color change
'
title = "Shapes 1.42"
GraphicsWindow.Title = title
debug = "False"
WQ = Text.GetCharacter(34)
CRLF = Text.GetCharacter(13) + Text.GetCharacter(10)
CS_InitPalette()                  ' initialize palette for color slider
DrawMenu()
shape = ""
nShapes = 0
cont = "True"                               ' continue
Mouse_Init()
KB_Init()
param = "down=True;move=False;up=True;"     ' wait to click
Mouse_SetHandler()
While cont
  If clicked Then       ' mouse clicked
    DetectClickedObject()
    DoObject()
    param = "down=True;move=False;up=True;"
    Mouse_SetHandler()
  ElseIf in > out Then  ' key input buffer is not empty
    KB_InKey()
    If c = "^x" Then
      obj = "menu" + icut
      DoMenu()
    ElseIf c = "^c" Then
      obj = "menu" + icopy
      DoMenu()
    ElseIf c = "^v" Then
      obj = "menu" + ipaste
      DoMenu()
    ElseIf c = "DEL" Then
      If selectedshape <> "" Then
        DeleteSelectedShape()
        i = selectedshape
        select = "False"
        ShapeSelect()   ' removes pinches
      EndIf
    ElseIf c = "LEFT" Or c = "RIGHT" Or c = "UP" Or c="DOWN" Then
      If selectedshape <> "" Then
        i = selectedshape
        _x = shape[i]["x"] + arrow_dx[c]
        _y = shape[i]["y"] + arrow_dy[c]
        MoveShape()
      EndIf
    EndIf
    param = "down=True;move=False;up=True;"
    Mouse_SetHandler()
  Else
    Program.Delay(100)
  EndIf
EndWhile
' end of program

Sub CalcDetectBorder
  ' param i - index of shapes
  If shape[i]["func"] = "line" Then           ' line
    x = shape[i]["x2"] - shape[i]["x1"]
    y = shape[i]["y2"] - shape[i]["y1"]
    Math_CartesianToPolar()
    If a >= 180 Then
      a = a - 180
    EndIf
    shape[i]["angle"] = a
    cx = shape[i]["x"] + Math.Abs(x) / 2
    cy = shape[i]["y"] + Math.Abs(y) / 2
    len = Math.SquareRoot(x * x + y * y)
    shape[i]["_x0"] = Math.Floor(cx - len / 2)
    shape[i]["_x1"] = Math.Floor(cx + len / 2)
    shape[i]["_y0"] = cy - 4
    shape[i]["_y1"] = cy + 4
  Else                                        ' rectangle, ellipse or triangle
    If shape[i]["func"] = "tri" Then          ' triangle
      shape[i]["width"] = shape[i]["x3"]
      shape[i]["height"] = shape[i]["y2"]
    EndIf
    shape[i]["_x0"] = shape[i]["x"]
    shape[i]["_y0"] = shape[i]["y"]
    shape[i]["_x1"] = shape[i]["x"] + shape[i]["width"]
    shape[i]["_y1"] = shape[i]["y"] + shape[i]["height"]
  EndIf
EndSub

Sub CalcPinchPos
  ' param i - shape index
  ' return mxM, myM - center of pinch
  _x = shape[i]["x"]
  _y = shape[i]["y"]
  width = shape[i]["width"]
  height = shape[i]["height"]
  angle = shape[i]["angle"]
  param = "width=0;height=0;angle=" + angle + ";"
  param["cx"] = _x + width / 2
  param["cy"] = _y + height / 2
  Stack.PushValue("local", x)
  Stack.PushValue("local", y)
  Stack.PushValue("local", _x)
  Stack.PushValue("local", _y)
  param["x"] = param["cx"]
  param["y"] = param["cy"] - 10
  Shapes_CalcRotatePos()
  mxM = x
  myM = y
  _y = Stack.PopValue("local")
  _x = Stack.PopValue("local")
  y = Stack.PopValue("local")
  x = Stack.PopValue("local")
EndSub

Sub CalcVertexes
  ' param i - pinch index
  ' param angle - angle of a shape
  ' param selectedshape - parent shape index of pinch
  ' param shape[] - shape data
  ' return mxM, myM - free vertex
  ' return mxD, myD - fixed vertex
  If shape[selectedshape]["func"] = "line" Then
    If i = 1 Then
      mxM = shape[selectedshape]["x"] + shape[selectedshape]["x1"]
      myM = shape[selectedshape]["y"] + shape[selectedshape]["y1"]
      mxD = shape[selectedshape]["x"] + shape[selectedshape]["x2"]
      myD = shape[selectedshape]["y"] + shape[selectedshape]["y2"]
    ElseIf i = 2 Then
      mxM = shape[selectedshape]["x"] + shape[selectedshape]["x2"]
      myM = shape[selectedshape]["y"] + shape[selectedshape]["y2"]
      mxD = shape[selectedshape]["x"] + shape[selectedshape]["x1"]
      myD = shape[selectedshape]["y"] + shape[selectedshape]["y1"]
    EndIf
  Else
    mxM = shape[selectedshape]["x"]
    myM = shape[selectedshape]["y"]
    mxD = mxM
    myD = myM
    If i = 1 Or i = 3 Then
      mxD = mxD + shape[selectedshape]["width"]
    EndIf
    If i = 1 Or i = 2 Then
      myD = myD + shape[selectedshape]["height"]
    EndIf
    If i = 2 Or i = 4 Then
      mxM = mxM + shape[selectedshape]["width"]
    EndIf
    If i = 3 Or i = 4 Then
      myM = myM + shape[selectedshape]["height"]
    EndIf
    param = "x=" + mxD + ";y=" + myD + ";width=0;height=0;angle=" + angle
    param = param + ";cx=" + (mxD + mxM) / 2 + ";cy=" + (myD + myM) / 2 + ";"
    Shapes_CalcRotatePos()
    mxD = x
    myD = y
    param["x"] = mxM
    param["y"] = myM
    Shapes_CalcRotatePos()
    mxM = x
    myM = y
  EndIf
EndSub  

Sub DeleteSelectedShape
  ' param selectedshape
  Shapes.Remove(shape[selectedshape]["obj"])
  nShapes = nShapes - 1
  For _i = selectedshape To nShapes
    shape[_i] = shape[_i + 1]
  EndFor
  shape[nShapes + 1] = ""
  selectedshape = ""
EndSub

Sub DetectClickedObject
  ' mxD, myD - clicked position
  ' return obj - name of object (menu, shape or pinch)
  Stack.PushValue("local", i)
  obj = ""
  For i = 1 To nPinch
    If pinch[i]["_x0"] <= mxD And mxD <= pinch[i]["_x1"] And pinch[i]["_y0"] <= myD And myD <= pinch[i]["_y1"] Then
      obj = "pinch" + i
      Goto dco_exit
    EndIf
  EndFor
  For i = nShapes To 1 Step -1
    param = "x=" + mxD + ";y=" + myD + ";width=0;height=0;"
    param["cx"] = (shape[i]["_x0"] + shape[i]["_x1"]) / 2
    param["cy"] = (shape[i]["_y0"] + shape[i]["_y1"]) / 2
    param["angle"] = -shape[i]["angle"]
    Shapes_CalcRotatePos()
    If shape[i]["_x0"] <= x And x <= shape[i]["_x1"] And shape[i]["_y0"] <= y And y <= shape[i]["_y1"] Then
      If shape[i]["func"] = "rect" Or shape[i]["func"] = "line" Then
        obj = "shape" + i
        Goto dco_exit
      ElseIf shape[i]["func"] = "ell" Then
        x = (x - param["cx"]) / shape[i]["width"] * 2
        y = (y - param["cy"]) / shape[i]["height"] * 2
        r = Math.SquareRoot(x * x + y * y)
        If r <= 1 Then
          obj = "shape" + i
          Goto dco_exit
        EndIf
      ElseIf shape[i]["func"] = "tri" Then
        x = (x - param["cx"]) / shape[i]["width"] * 2
        y = (y - shape[i]["_y1"]) / shape[i]["height"]
        r = Math.Abs(x) + Math.Abs(y)
        If r <= 1 And y <= 0 Then
          obj = "shape" + i
          Goto dco_exit
        EndIf
      EndIf
    EndIf
  EndFor
  For i = 1 To nMenu
    If menu[i]["func"] <> "" And menu[i]["_x0"] <= mxD And mxD <= menu[i]["_x1"] And menu[i]["_y0"] <= myD And myD <= menu[i]["_y1"] Then
      obj = "menu" + i
      Goto dco_exit
    EndIf
  EndFor
  dco_exit:
  If obj = "" And selectedshape <> "" Then
    i = selectedshape
    select = "False"
    ShapeSelect()
  EndIf
  i = Stack.PopValue("local")
EndSub

Sub DoMenu                        ' if a menu item clicked do the funciton
  If Text.StartsWith(obj, "menu") Then
    param = "down=False;move=False;up=False;"   ' wait button pushed
    Mouse_SetHandler()
    i = Text.GetSubTextToEnd(obj, 5)
    obj = ""
    func = menu[i]["func"]
    select = "True"
    ItemSelect()                  ' shows menu item frame
    If selecteditem = i And Text.IsSubText("rect|ell|tri|line", func) Then
      If mode = "repeat" Then
        mode = "single"
        Shapes.HideShape(repeat[func])
      Else
        mode = "repeat"
        Shapes.ShowShape(repeat[func])
      EndIf
    Else
      mode = "single"
    EndIf
    selecteditem = i
    If Text.IsSubText("open|save|cut|paste|rect|ell|tri|line", func) And selectedshape <> "" Then
      i = selectedshape
      select = "False"
      ShapeSelect()               ' removes pinches if a shape selected
      If func = "cut" Then
        selectedshape = i
      EndIf
    EndIf
    If func = "open" Then         ' open shapes from file
      ReadShapes()
    ElseIf func = "save" Then     ' save shapes to file
      WriteShapes()
    ElseIf func = "cut" Then
      If selectedshape <> "" Then
        clipboard = shape[selectedshape]
        DeleteSelectedShape()
      EndIf
    ElseIf func = "copy" Then
      If selectedshape <> "" Then
        clipboard = shape[selectedshape]
        index = "1=x;2=y;3=_x0;4=_x1;5=_y0;6=_y1;"
        For _i = 1 To 6
          clipboard[index[_i]] = clipboard[index[_i]] + 10
        EndFor
      EndIf
    ElseIf func = "paste" Then
      If clipboard <> "" Then
        nShapes = nShapes + 1
        shape[nShapes] = clipboard
        index = "1=x;2=y;3=_x0;4=_x1;5=_y0;6=_y1;"
        For _i = 1 To 6
          clipboard[index[_i]] = clipboard[index[_i]] + 10
        EndFor
        iMin = nShapes
        iMax = nShapes
        scale = 1
        shX = 0
        shY = 0
        Shapes_Add()
        i = nShapes
        select = "True"
        ShapeSelect()
      EndIf
    ElseIf func = "rect" Or func = "ell" Or func = "tri" Then
      ' rectangle, ellipse or triangle
      While "True"
        WaitToClick()               ' to get mxD, myD
        DetectClickedObject()
        If Text.StartsWith(obj, "menu") Then
          Goto dm_exit              ' cancel to register shape
        EndIf
        obj = ""
        mxM = mxD
        myM = myD
        angle = 0
        WaitToReleaseS()            ' to get mxU, myU
        resize = "False"
        nShapes = nShapes + 1
        i = nShapes                 ' to set shape[nShapes]
        RegisterShapeData()
        If w = 0 And h = 0 Then
          shape[i] = ""
          nShapes = nShapes - 1
          Goto dm_exit              ' cansel to register zero sized shape
        EndIf
        GraphicsWindow.BrushColor = bcolor
        GraphicsWindow.PenWidth = pwidth
        If pwidth > 0 Then
          GraphicsWindow.PenColor = pcolor
        EndIf
        If func = "rect" Then
          shape[nShapes]["obj"] = Shapes.AddRectangle(w, h)
        ElseIf func = "ell" Then
          shape[nShapes]["obj"] = Shapes.AddEllipse(w, h)
        ElseIf func = "tri" Then
          shape[nShapes]["obj"] = Shapes.AddTriangle(xt, 0, 0, h, w, h)
        EndIf
        Shapes.Move(shape[nShapes]["obj"], xmin, ymin)
        If mode = "single" Then
          Goto dm_exit
        EndIf
      EndWhile
    ElseIf func = "line" Then     ' line
      While "True"
        WaitToClick()               ' to get mxD, myD
        DetectClickedObject()
        If Text.StartsWith(obj, "menu") Then
          Goto dm_exit              ' cancel to register line
        EndIf
        obj = ""
        mxM = mxD
        myM = myD
        WaitToReleaseS()            ' to get mxU, myU
        nShapes = nShapes + 1
        i = nShapes                 ' to set shape[nShapes]
        RegisterShapeData()
        If x1 = x2 And y1 = y2 Then
          shape[i] = ""
          nShapes = nShapes - 1
          Goto dm_exit              ' cansel to register zero sized line
        EndIf
        GraphicsWindow.BrushColor = bcolor
        GraphicsWindow.PenWidth = pwidth
        If pwidth > 0 Then
          GraphicsWindow.PenColor = pcolor
        EndIf
        shape[nShapes]["obj"] = Shapes.AddLine(x1, y1, x2, y2)
        Shapes.Move(shape[nShapes]["obj"], xmin, ymin)
        If mode = "single" Then
          Goto dm_exit
        EndIf
      EndWhile
    ElseIf func = "pw" Then       ' pen width
      If pen = nPen Then
        pen = 1
      Else
        pen = pen + 1
      EndIf
      pwidth = pw[pen]
      x = menu[i]["_x0"]
      y = menu[i]["_y0"]
      size = menu[i]["_x1"] - x
      GraphicsWindow.BrushColor = "#EEEEEE"
      GraphicsWindow.FillRectangle(x, y, size, size)
      DrawMenuItem()
    ElseIf func = "pc" Then       ' pen color
      color = pcolor
      CS_ShowPopup()
      pcolor = color
      DrawMenuItem()
    ElseIf func = "bc" Then       ' brush color
      color = bcolor
      CS_ShowPopup()
      bcolor = color
      DrawMenuItem()
    ElseIf func = "menubar" And selectedshape <> "" Then
      i = selectedshape
      select = "False"
      ShapeSelect()
    EndIf
    If selectedshape <> "" And (func = "pw" Or func = "pc" Or func = "bc") Then
      i = selectedshape
      select = "False"
      ShapeSelect()
      If func = "pw" Then
        shape[i]["pw"] = pwidth
      ElseIf func = "pc" Then
        shape[i]["pc"] = pcolor
      ElseIf func = "bc" Then
        shape[i]["bc"] = color
      EndIf
      iMin = i                    ' to re-size Shapes
      iMax = nShapes              ' to keep z-order of Shapes
      Shapes_Remove()
      scale = 1
      shX = 0
      shY = 0
      Shapes_Add()
      select = "True"
      ShapeSelect()
    EndIf
dm_exit:
    i = selecteditem
    select = "False"
    ItemSelect()                  ' removes menu item frame
    If Text.IsSubText("rect|ell|tri|line", func) Then
      Shapes.HideShape(repeat[func])
    EndIf
  EndIf
EndSub

Sub DoObject
  ' param obj - clicked object
  While obj <> ""
    fromMenu = "False"
    DoMenu()
    If obj <> "" Then
      DoShape()
    EndIf
    If obj <> "" Then
      DoPinch()
    EndIf
  EndWhile
EndSub

Sub DoPinch                     ' if a pinch clicked then rotate or re-size a shape
  ' param obj - clicked object
  ' param selectedshape - parent shape index of the pinch
  If Text.StartsWith(obj, "pinch") Then
    i = Text.GetSubTextToEnd(obj, 6)
    obj = ""
    If i = 5 Then               ' rotate a shape
      i = selectedshape
      WaitToReleaseR()          ' to get angle
      Shapes.Rotate(shape[i]["obj"], angle)
      shape[i]["angle"] = Math.Floor(angle)
      select = "False"
      ShapeSelect()             ' remove pinches
      select = "True"
      ShapeSelect()             ' show pinches
    Else                        ' re-size a shape
      angle = shape[selectedshape]["angle"]
      CalcVertexes()            ' to get mxM, myM, mxD, myD
      func = shape[selectedshape]["func"]
      WaitToReleaseS()          ' to get mxU, myU
      i = selectedshape
      select = "False"
      ShapeSelect()             ' remove pinches
      ' selectedshape is broken in ShapeSelect() so use i instead
      RegisterShapeMetrics()    ' re-size shape[i]
      iMin = i                  ' to re-size Shapes
      iMax = nShapes            ' to keep z-order of Shapes
      Shapes_Remove()
      scale = 1
      shX = 0
      shY = 0
      Shapes_Add()
      select = "True"
      ShapeSelect()             ' show pinches
    EndIf
  EndIf
EndSub

Sub DoShape                       ' if a shape clicked then move it
  If Text.StartsWith(obj, "shape") Then
    If selectedshape <> "" Then   ' if other shape selected
      i = selectedshape
      select = "False"
      ShapeSelect()               ' removes pinches
    EndIf
    i = Text.GetSubTextToEnd(obj, 6)  ' shape index
    select = "True"
    ShapeSelect()                 ' shows pinches
    Mouse_SetHandler()
    WaitToReleaseM()              ' for moving a shape
    clicked = "False"
    obj = ""
  EndIf
EndSub

Sub DrawMenu
  ' return menu[] - array of menu data
  pwidth = GraphicsWindow.PenWidth
  cxMenu = 6
  cyMenu = 6
  sizeMenu = 40
  nMenu = 12
  GraphicsWindow.BrushColor = "#EEEEEE"
  GraphicsWindow.FillRectangle(0, 0, GraphicsWindow.Width, 20 + sizeMenu)
  pw = "1=2;2=4;3=8;4=16;5=0;6=1;"  ' pen width
  pen = 1                           ' pen width index
  nPen = 6                          ' number of pen width
  For i = 1 To nMenu
    xMenu = cxMenu + Math.Floor((i - 1) / 1) * (sizeMenu + 4)
    yMenu = cyMenu + Math.Remainder(i - 1, 1) * (sizeMenu + 14)
    GraphicsWindow.BrushColor = "#EEEEEE"
    GraphicsWindow.FillRectangle(xMenu, yMenu, sizeMenu, sizeMenu)
    menu[i]["_x0"] = xMenu
    menu[i]["_y0"] = yMenu
    menu[i]["_x1"] = xMenu + sizeMenu
    menu[i]["_y1"] = yMenu + sizeMenu
    DrawMenuItem()
  EndFor
  nMenu = nMenu + 1
  imenubar = nMenu
  menu[i]["_x0"] = 0
  menu[i]["_y0"] = 0
  menu[i]["_x1"] = GraphicsWindow.Width
  menu[i]["_y1"] = 20 + sizeMenu
  menu[i]["func"] = "menubar"
EndSub

Sub DrawMenuItem
  ' param i - item number
  ' param pwidth - pen width
  ' param pcolor - pen color
  ' param bcolor - brush color
  margin = 4
  x = menu[i]["_x0"]
  y = menu[i]["_y0"]
  size = menu[i]["_x1"] - x
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.FontBold = "False"
  GraphicsWindow.FontSize = 8
  url = "http://www.nonkit.com/smallbasic.files/"
  If i = 1 Then
    menu[i]["func"] = "open"
    GraphicsWindow.DrawImage(url + "open.png", x, y)
    itemname[i] = "Open"
  ElseIf i = 2 Then
    menu[i]["func"] = "save"
    GraphicsWindow.DrawImage(url + "save.png", x, y)
    itemname[i] = "Save"
  ElseIf i = 3 Then
    icut = i                    ' for short cut key
    menu[i]["func"] = "cut"
    ' initialize shapes
    Scissors_Init()
    nShapes = Array.GetItemCount(shape)
    ' add shapes
    scale = 0.11
    iMin = 1
    iMax = nShapes
    Shapes_Add()
    x = x + 14
    Shapes_Move()
    x = x - 14
    nShapes = 3
    For t = 0 To 360 * 0.3
      angle = 30 - 30 * Math.Cos(t * Math.Pi / 180)
      Shapes_Rotate()
    EndFor
    itemname[i] = "Cut"
  ElseIf i = 4 Then
    icopy = i                   ' for short cut key
    menu[i]["func"] = "copy"
    GraphicsWindow.DrawImage(url + "copy.png", x, y)
    itemname[i] = "Copy"
  ElseIf i = 5 Then
    ipaste = i                  ' for short cut key
    menu[i]["func"] = "paste"
    GraphicsWindow.DrawImage(url + "paste.png", x, y)
    itemname[i] = "Paste"
  ElseIf i = 6 Then
    menu[i]["func"] = "rect"
    GraphicsWindow.DrawRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
    itemname[i] = "Rectangle"
    repeat["rect"] = Shapes.AddImage(url + "repeat.png")
    Shapes.Move(repeat["rect"], x, y)   ' for consecutive shapes addition
    Shapes.HideShape(repeat["rect"])
  ElseIf i = 7 Then
    menu[i]["func"] = "ell"
    GraphicsWindow.DrawEllipse(x + margin, y + margin, size - margin * 2, size - margin * 2)
    itemname[i] = "Ellipse"
    repeat["ell"] = Shapes.AddImage(url + "repeat.png")
    Shapes.Move(repeat["ell"], x, y)   ' for consecutive shapes addition
    Shapes.HideShape(repeat["ell"])
  ElseIf i = 8 Then
    menu[i]["func"] = "tri"
    x1 = x + size / 2
    y1 = y + margin
    x2 = x + margin
    y2 = y + size - margin
    x3 = x + size - margin
    y3 = y + size - margin
    GraphicsWindow.DrawTriangle(x1, y1, x2, y2, x3, y3)
    itemname[i] = "Triangle"
    repeat["tri"] = Shapes.AddImage(url + "repeat.png")
    Shapes.Move(repeat["tri"], x, y)   ' for consecutive shapes addition
    Shapes.HideShape(repeat["tri"])
  ElseIf i = 9 Then
    menu[i]["func"] = "line"
    x1 = x + margin
    y1 = y + margin
    x2 = x + size - margin
    y2 = y + size - margin
    GraphicsWindow.DrawLine(x1, y1, x2, y2)
    itemname[i] = "Line"
    repeat["line"] = Shapes.AddImage(url + "repeat.png")
    Shapes.Move(repeat["line"], x, y)   ' for consecutive shapes addition
    Shapes.HideShape(repeat["line"])
  ElseIf i = 10 Then
    menu[i]["func"] = "pw"
    GraphicsWindow.PenWidth = pwidth
    x1 = x + margin
    y1 = y + size / 2
    x2 = x + size - margin
    y2 = y + size / 2
    GraphicsWindow.DrawLine(x1, y1, x2, y2)
    itemname[i] = "Pen Width"
  ElseIf i = 11 Then
    menu[i]["func"] = "pc"
    margin = 6
    GraphicsWindow.PenWidth = 4
    GraphicsWindow.PenColor = pcolor
    GraphicsWindow.DrawRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
    itemname[i] = "Pen Color"
  ElseIf i = 12 Then
    menu[i]["func"] = "bc"
    GraphicsWindow.BrushColor = bcolor
    GraphicsWindow.FillRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
    GraphicsWindow.PenColor = "Black"
    GraphicsWindow.PenWidth = 2
    GraphicsWindow.DrawRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
    itemname[i] = "Brush Color"
  EndIf
  If itemname[i] <> "" And oItem[i] = "" Then
    GraphicsWindow.BrushColor = "Black"
    oItem[i] = Shapes.AddText(itemname[i])
    Shapes.Move(oItem[i], x + margin, y + size)
  EndIf
  GraphicsWindow.FontBold = "True"
  GraphicsWindow.FontSize = 12
EndSub

Sub ItemSelect
  ' i - menu index
  ' select - "True" if selected
  If i <> imenubar Then
    If select Then
      GraphicsWindow.PenColor = "Gray"
    Else
      GraphicsWindow.PenColor = "#EEEEEE"
    EndIf
    GraphicsWindow.PenWidth = 2
    x = menu[i]["_x0"] - 1
    y = menu[i]["_y0"] - 1
    width = menu[i]["_x1"] - x + 1
    height = menu[i]["_y1"] - y + 1
    GraphicsWindow.DrawRectangle(x, y, width, height)
  EndIf
EndSub

Sub NormalizePos
  ' param mxD, myD - fixed vertex of a shape rotated
  ' param mxM, myM - opposite vertex of a shape rotated
  ' param angle - angle of a shape
  ' return _mxD, _myD - fixed vertex of a shape not rotated
  ' return _mxM, _myM - opposite vertex of a shape not rotated
  param = "x=" + mxD + ";y=" + myD + ";width=0;height=0;"
  param["cx"] = (mxD + mxM) / 2
  param["cy"] = (myD + myM) / 2
  param["angle"] = -angle
  Shapes_CalcRotatePos()
  _mxD = Math.Floor(x)
  _myD = Math.Floor(y)
  param["x"] = mxM
  param["y"] = myM
  Shapes_CalcRotatePos()
  _mxM = Math.Floor(x)
  _myM = Math.Floor(y)
EndSub

Sub ReadShapes
  File_Open()
  ' Parse "shX = ..."
  ptr = Text.GetIndexOf(buf, "shX = ")
  If ptr = 0 Then
    Goto rs_exit
  EndIf
  shX = ""
  ptr = ptr + 6
  c = Text.GetSubText(buf, ptr, 1)
  While Text.GetIndexOf("0123456789", c) > 0
    shX = Text.Append(shX, c)
    ptr = ptr + 1
    c = Text.GetSubText(buf, ptr, 1)
  EndWhile
  ' Parse "shY = ..."
  _ptr = Text.GetIndexOf(Text.GetSubTextToEnd(buf, ptr), "shY = ")
  If _ptr = 0 Then
    Goto rs_exit
  EndIf
  shY = ""
  ptr = ptr + _ptr + 5
  c = Text.GetSubText(buf, ptr, 1)
  While Text.GetIndexOf("0123456789", c) > 0
    shY = Text.Append(shY, c)
    ptr = ptr + 1
    c = Text.GetSubText(buf, ptr, 1)
  EndWhile
  ' Parse "shape[i] = ..."
  While "True"
    _ptr = Text.GetIndexOf(Text.GetSubTextToEnd(buf, ptr), "shape[")
    If _ptr = 0 Then
      Goto rs_exit
    EndIf
    ptr = ptr + _ptr + 5
    _ptr = Text.GetIndexOf(Text.GetSubTextToEnd(buf, ptr), "] = " + WQ)
    If _ptr = 0 Then
      Goto rs_exit
    EndIf
    i = Text.GetSubText(buf, ptr, _ptr - 1)
    ptr = ptr + _ptr + 4
    _ptr = Text.GetIndexOf(Text.GetSubTextToEnd(buf, ptr), WQ)
    If _ptr = 0 Then
      Goto rs_exit
    EndIf
    shape[nShapes + i] = Text.GetSubText(buf, ptr, _ptr - 1)
    ptr = ptr + _ptr
  EndWhile
  rs_exit:
  iMin = nShapes + 1
  nShapes = Array.GetItemCount(shape)
  iMax = nShapes
  For i = iMin To iMax
    shape[i]["x"] = shape[i]["x"] + shX
    shape[i]["y"] = shape[i]["y"] + shY
    If shape[i]["func"] = "tri" And (shape[i]["y2"] < shape[i]["y1"]) Then
      shape[i]["y2"] = shape[i]["y1"]
      shape[i]["y1"] = shape[i]["y3"]
      shape[i]["y3"] = shape[i]["y2"]
      shape[i]["angle"] = shape[i]["angle"] + 180
      If shape[i]["angle"] >= 360 Then
        shape[i]["angle"] = shape[i]["angle"] - 360
      EndIf
    EndIf
    CalcDetectBorder()
    If shape[i]["pc"] <> "" Then
      color = shape[i]["pc"]
      CS_AddColorToPalette()
    EndIf
    If shape[i]["bc"] <> "" Then
      color = shape[i]["bc"]
      CS_AddColorToPalette()
    EndIf
  EndFor
  shX = 0
  shY = 0
  scale = 1
  Shapes_Add()
EndSub

Sub RegisterShapeData
  ' param i - index of shapes
  ' param func - "rect", "ell", "tri" or "line"
  ' return shape[i] - shape data
  shape[i]["func"] = func
  RegisterShapeStyle()
  RegisterShapeMetrics()
EndSub

Sub RegisterShapeMetrics
  ' param i - index of shapes
  ' param func - "rect", "ell", "tri" or "line"
  ' param mxD, myD - fixed vertex
  ' param mxU, myU - opposite vertex
  ' return shape[i] - shape data
  ' return xmin, ymin, w, h - shape position and size
  ' return xt - top position for triangle
  ' return x1, y1, x2, y2 - line position
  If func = "line" Then           ' line
    xmin = Math.Min(mxD, mxU)
    ymin = Math.Min(myD, myU)
    xmax = Math.Max(mxD, mxU)
    ymax = Math.Max(myD, myU)
    x1 = mxD - xmin
    y1 = myD - ymin
    x2 = mxU - xmin
    y2 = myU - ymin
    shape[i]["x1"] = x1
    shape[i]["y1"] = y1
    shape[i]["x2"] = x2
    shape[i]["y2"] = y2
  Else                            ' rectangle, ellipse or triangle
    mxM = mxU
    myM = myU
    angle = shape[i]["angle"]
    NormalizePos()
    xmin = Math.Min(_mxD, _mxM)
    ymin = Math.Min(_myD, _myM)
    xmax = Math.Max(_mxD, _mxM)
    ymax = Math.Max(_myD, _myM)
    w = xmax - xmin
    h = ymax - ymin
    shape[i]["width"] = w
    shape[i]["height"] = h
  EndIf
  shape[i]["x"] = xmin
  shape[i]["y"] = ymin
  If func = "tri" Then                    ' triangle
    xt = Math.Floor((xmax - xmin) / 2)    ' x top
    shape[i]["x1"] = xt
    shape[i]["y1"] = 0
    shape[i]["x2"] = 0
    shape[i]["y2"] = h
    shape[i]["x3"] = w
    shape[i]["y3"] = h
  EndIf
  CalcDetectBorder()
EndSub

Sub RegisterShapeStyle
  ' param i - index of shapes
  ' param pwidth  - pen width
  ' param pcolor - pen color
  ' param bcolor - brush color
  ' return shape[i] - shape data
  shape[i]["pw"] = pwidth
  If pwidth > 0 Then
    shape[i]["pc"] = pcolor
  Else
    shape[i]["pc"] = ""
  EndIf
  If func <> "line" Then        ' rectangle, ellipse or triangle
    shape[i]["bc"] = bcolor
  EndIf
EndSub

Sub ShapeSelect
  ' Show or remove pinches for a selected shape
  ' param i - shape index
  ' param select - "True" if selected
  ' return selectedshape - selected shape index
  If select Then
    Stack.PushValue("local", x)
    Stack.PushValue("local", y)
    GraphicsWindow.PenColor = "Black"
    GraphicsWindow.PenWidth = 1
    sizePinch = 10
    selectedshape = i
    shX = shape[i]["x"]
    shY = shape[i]["y"]
    GraphicsWindow.BrushColor = "Lime"
    If shape[i]["func"] = "line" Then
      nPinch = 2
      For _i = 1 To nPinch
        pinch[_i]["obj"] = Shapes.AddEllipse(sizePinch, sizePinch)
        x = shX + shape[i]["x" + _i] - sizePinch / 2
        y = shY + shape[i]["y" + _i] - sizePinch / 2
        Shapes.Move(pinch[_i]["obj"], x, y)
        pinch[_i]["_x0"] = x
        pinch[_i]["_y0"] = y
        pinch[_i]["_x1"] = x + sizePinch
        pinch[_i]["_y1"] = y + sizePinch
      EndFor
    Else
      pinch[5]["obj"] = Shapes.AddEllipse(sizePinch, sizePinch)
      shWidth = shape[i]["width"]
      shHeight = shape[i]["height"]
      param["cx"] = shX + shWidth / 2
      param["cy"] = shY + shHeight / 2
      param["angle"] = shape[i]["angle"]
      param["x"] = shX + shWidth / 2 - sizePinch / 2
      param["y"] = shY - 30 - sizePinch / 2
      param["width"] = sizePinch
      param["height"] = sizePinch
      Shapes_CalcRotatePos()
      Shapes.Move(pinch[5]["obj"], x, y)
      pinch[5]["_x0"] = x
      pinch[5]["_y0"] = y
      pinch[5]["_x1"] = x + sizePinch
      pinch[5]["_y1"] = y + sizePinch
      nPinch = 5
      xPinch = "1=0;2=" + shWidth + ";3=0;4=" + shWidth + ";"
      yPinch = "1=0;2=0;3=" + shHeight + ";4=" + shHeight + ";"
      GraphicsWindow.BrushColor = "#639AE7"
      For _i = 1 To 4
        pinch[_i]["obj"] = Shapes.AddEllipse(sizePinch, sizePinch)
        param["x"] = shX + xPinch[_i] - sizePinch / 2
        param["y"] = shY + yPinch[_i] - sizePinch / 2
        Shapes_CalcRotatePos()
        Shapes.Move(pinch[_i]["obj"], x, y)
        pinch[_i]["_x0"] = x
        pinch[_i]["_y0"] = y
        pinch[_i]["_x1"] = x + sizePinch
        pinch[_i]["_y1"] = y + sizePinch
      EndFor
    EndIf
    y = Stack.PopValue("local")
    x = Stack.PopValue("local")
  Else
    selectedshape = ""
    For _i = 1 To nPinch
      Shapes.Remove(pinch[_i]["obj"])
    EndFor
    nPinch = 0
  EndIf
EndSub

Sub WaitToClick
  ' return mxD, myD - clicked point
  param = "down=True;move=False;up=False;"     ' wait to click
  Mouse_SetHandler()
  While clicked = "False"
    Program.Delay(100)
  EndWhile
EndSub

Sub WaitToReleaseM ' for moving a shape
  ' param i - shape index
  ' param mxD, myD - fixed vertex of a shape
  ' return mxU, myU - opposite vertex of a shape
  GraphicsWindow.PenWidth = 1
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.BrushColor = "White"
  param = "down=False;move=True;"   ' for moving a shape
  Mouse_SetHandler()
  func = shape[i]["func"]
  _x = shape[i]["x"]
  _y = shape[i]["y"]
  shAngle = shape[i]["angle"]
  mxM = mxD
  myM = myD
  moved = "True"
  While released = "False"
    If moved Then
      param = "move=False;"   ' while moving a shape
      Mouse_SetHandler()
      _x = shape[i]["x"] + mxM - mxD
      _y = shape[i]["y"] + myM - myD
      If oFrame[func] = "" Then
        If func = "rect" Then
          oFrame[func] = Shapes.AddRectangle(shape[i]["width"], shape[i]["height"])
        ElseIf func = "ell" Then
          oFrame[func] = Shapes.AddEllipse(shape[i]["width"], shape[i]["height"])
        ElseIf func = "tri" Then
          _x1 = shape[i]["x1"]
          _y1 = shape[i]["y1"]
          _x2 = shape[i]["x2"]
          _y2 = shape[i]["y2"]
          _x3 = shape[i]["x3"]
          _y3 = shape[i]["y3"]
          oFrame[func] = Shapes.AddTriangle(_x1, _y1, _x2, _y2, _x3, _y3)
        ElseIf func = "line" Then
          _x1 = shape[i]["x1"]
          _y1 = shape[i]["y1"]
          _x2 = shape[i]["x2"]
          _y2 = shape[i]["y2"]
          oFrame[func] = Shapes.AddLine(_x1, _y1, _x2, _y2)
          Shapes.SetOpacity(oFrame[func], 50)
        EndIf
      EndIf
      If func = "rect" Or func = "ell" Or func = "tri" Then
        Shapes.SetOpacity(oFrame[func], 0)
        Shapes.Move(oFrame[func], _x, _y)
        Shapes.Rotate(oFrame[func], shAngle)
        Shapes.SetOpacity(oFrame[func], 50)
      ElseIf func = "line" Then
        Shapes.Move(oFrame[func], _x, _y)
      EndIf
      param = "move=True;"   ' for next moving a shape
      Mouse_SetHandler()
    Else
      Program.Delay(100)
    EndIf
  EndWhile
  param = "move=False;up=False;"   ' mouse released
  Mouse_SetHandler()
  MoveShape()
  If oFrame[func] <> "" Then
    Shapes.Remove(oFrame[func])
    oFrame[func] = ""
  EndIf
EndSub

Sub MoveShape
  ' param i - shape index
  ' param _x, _y - new position of the shape
  dx = _x - shape[i]["x"]
  dy = _y - shape[i]["y"]
  shape[i]["x"] = _x
  shape[i]["y"] = _y
  shape[i]["_x0"] = shape[i]["_x0"] + dx
  shape[i]["_x1"] = shape[i]["_x1"] + dx
  shape[i]["_y0"] = shape[i]["_y0"] + dy
  shape[i]["_y1"] = shape[i]["_y1"] + dy
  Shapes.Move(shape[i]["obj"], _x, _y)
  If shape[i]["func"] = "line" Then
    _iMax = 2
  Else
    _iMax = 5
  EndIf
  For _i = 1 To _iMax
    pinch[_i]["_x0"] = pinch[_i]["_x0"] + dx
    pinch[_i]["_x1"] = pinch[_i]["_x1"] + dx
    pinch[_i]["_y0"] = pinch[_i]["_y0"] + dy
    pinch[_i]["_y1"] = pinch[_i]["_y1"] + dy
    Shapes.Move(pinch[_i]["obj"], pinch[_i]["_x0"], pinch[_i]["_y0"])
  EndFor
EndSub

Sub WaitToReleaseR ' for rotating a shape
  ' param i - shape index
  ' return angle - angle for rotation
  GraphicsWindow.PenWidth = 1
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.BrushColor = "White"
  param = "down=False;move=True;up=True;"   ' for rotating a shape / wait to release
  Mouse_SetHandler()
  CalcPinchPos()  ' into mxM, myM
  cx = param["cx"]
  cy = param["cy"]
  func = shape[i]["func"]
  If func = "tri" Then
    x1 = shape[i]["x1"]
    y1 = shape[i]["y1"]
    x2 = shape[i]["x2"]
    y2 = shape[i]["y2"]
    x3 = shape[i]["x3"]
    y3 = shape[i]["y3"]
  EndIf
  moved = "True"
  If oFrame[func] <> "" Then
    Shapes.Remove(oFrame[func])
  EndIf
  If func = "rect" Then
    oFrame[func] = Shapes.AddRectangle(width, height)
  ElseIf func = "ell" Then
    oFrame[func] = Shapes.AddEllipse(width, height)
  ElseIf func = "tri" Then
    oFrame[func] = Shapes.AddTriangle(x1, y1, x2, y2, x3, y3)
  EndIf
  Shapes.SetOpacity(oFrame[func], 0)
  Shapes.Move(oFrame[func], _x, _y)
  While released = "False"
    If moved Then
      param = "move=False;"   ' while sizing a shape
      Mouse_SetHandler()
      x = mxM - cx
      y = myM - cy
      If x <> 0 Or y <> 0 Then
        Math_CartesianToPolar()
        angle = Math.Floor(a + 90)
        If angle >= 360 Then
          angle = angle - 360
        EndIf
      EndIf
      Shapes.Rotate(oFrame[func], angle)
      Shapes.SetOpacity(oFrame[func], 50)
      param = "move=True;"        ' for next sizing a shape
      Mouse_SetHandler()
    Else
      Program.Delay(100)
    EndIf
  EndWhile
  param = "move=False;up=False;"  ' mouse released
  Mouse_SetHandler()
  If oFrame[func] <> "" Then
    Shapes.Remove(oFrame[func])
    oFrame[func] = ""
  EndIf
EndSub

Sub WaitToReleaseS  ' for sizing a shape
  ' param func - "rect", "ell", "tri" or "line" because shape index may not decided
  ' param mxD, myD - fixed vertex of a shape
  ' param mxM, myM - opposite vertex of a shape
  ' param angle - angle of a shape
  ' return mxU, myU - opposite vertex of a shape
  GraphicsWindow.PenWidth = 1
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.BrushColor = "White"
  param = "down=False;move=True;up=True;"   ' for sizing a shape / wait to release
  Mouse_SetHandler()
  moved = "True"
  While released = "False"
    If moved Then
      param = "move=False;"   ' while sizing a shape
      Mouse_SetHandler()
      If func = "rect" Or func = "ell" Or func = "tri" Then
        If oFrame[func] <> "" Then
          Shapes.Remove(oFrame[func])
        EndIf
        NormalizePos()
        xmin = Math.Min(_mxD, _mxM)
        ymin = Math.Min(_myD, _myM)
        xmax = Math.Max(_mxD, _mxM)
        ymax = Math.Max(_myD, _myM)
        If func = "rect" Then
          oFrame[func] = Shapes.AddRectangle(xmax - xmin, ymax - ymin)
        ElseIf func = "ell" Then
          oFrame[func] = Shapes.AddEllipse(xmax - xmin, ymax - ymin)
        ElseIf func = "tri" Then
          oFrame[func] = Shapes.AddTriangle((xmax - xmin) / 2, 0, 0, ymax - ymin, xmax - xmin, ymax - ymin)
        EndIf
        Shapes.SetOpacity(oFrame[func], 0)
        Shapes.Move(oFrame[func], xmin, ymin)
        Shapes.Rotate(oFrame[func], angle)
        Shapes.SetOpacity(oFrame[func], 50)
      ElseIf func = "line" Then
        If oFrame[func] <> "" Then
          Shapes.Remove(oFrame[func])
        EndIf
        oFrame[func] = Shapes.AddLine(mxD, myD, mxM, myM)
        Shapes.SetOpacity(oFrame[func], 50)
      EndIf
      param = "move=True;"        ' for next sizing a shape
      Mouse_SetHandler()
    Else
      Program.Delay(100)
    EndIf
  EndWhile
  param = "move=False;up=False;"  ' mouse released
  Mouse_SetHandler()
  If oFrame[func] <> "" Then
    Shapes.Remove(oFrame[func])
    oFrame[func] = ""
  EndIf
EndSub

Sub WriteShapes
  Stack.PushValue("local", i)
  buf = "' " + Clock.Date + " " + Clock.Time + " Generated"
  buf = buf + " by " + title + CRLF
  buf = buf + "'" + CRLF
  buf = buf + "' initialize shapes" + CRLF
  buf = buf + "Shapes_Init()" + CRLF
  buf = buf + "' add shapes" + CRLF
  buf = buf + "scale = 1" + CRLF
  buf = buf + "Shapes_Add()" + CRLF
  buf = buf + "angle = 0" + CRLF + CRLF
  buf = buf + "Sub Shapes_Init" + CRLF
  buf = buf + "  ' Shapes | Initialize shapes data" + CRLF
  buf = buf + "  ' return shX, shY - current position of shapes" + CRLF
  buf = buf + "  ' return shape - array of shapes" + CRLF
  If nShapes > 0 Then
    xmin = shape[1]["x"]
    ymin = shape[1]["y"]
    xmax = shape[1]["x"]
    ymax = shape[1]["y"]
  EndIf
  For i = 2 To nShapes
    If shape[i]["x"] < xmin Then
      xmin = shape[i]["x"]
    EndIf
    If shape[i]["y"] < ymin Then
      ymin = shape[i]["y"]
    EndIf
    If xmax < shape[i]["x"] Then
      xmax = shape[i]["x"]
    EndIf
    If ymax < shape[i]["y"] Then
      ymax = shape[i]["y"]
    EndIf
  EndFor
  buf = buf + "  shX = " + xmin + " ' x offset" + CRLF
  buf = buf + "  shY = " + ymin + " ' y offset" + CRLF
  buf = buf + "  shape = " + WQ + WQ + CRLF
  For i = 1 To nShapes
    If shape[i]["func"] = "rect" Or shape[i]["func"] = "ell" Then
      buf = buf + "  shape[" + i + "] = " + WQ + "func=" + shape[i]["func"] + ";"
      buf = buf + "x=" + (shape[i]["x"] - xmin) + ";"
      buf = buf + "y=" + (shape[i]["y"] - ymin) + ";"
      buf = buf + "width=" + shape[i]["width"] + ";"
      buf = buf + "height=" + shape[i]["height"] + ";"
      If shape[i]["angle"] <> 0 And shape[i]["angle"] <> "" Then
        buf = buf + "angle=" + shape[i]["angle"] + ";"
      EndIf
      buf = buf + "bc=" + shape[i]["bc"] + ";"
    ElseIf shape[i]["func"] = "tri" Then
      buf = buf + "  shape[" + i + "] = " + WQ + "func=tri;"
      buf = buf + "x=" + (shape[i]["x"] - xmin) + ";"
      buf = buf + "y=" + (shape[i]["y"] - ymin) + ";"
      buf = buf + "x1=" + shape[i]["x1"] + ";"
      buf = buf + "y1=" + shape[i]["y1"] + ";"
      buf = buf + "x2=" + shape[i]["x2"] + ";"
      buf = buf + "y2=" + shape[i]["y2"] + ";"
      buf = buf + "x3=" + shape[i]["x3"] + ";"
      buf = buf + "y3=" + shape[i]["y3"] + ";"
      If shape[i]["angle"] <> 0 And shape[i]["angle"] <> "" Then
        buf = buf + "angle=" + shape[i]["angle"] + ";"
      EndIf
      buf = buf + "bc=" + shape[i]["bc"] + ";"
    ElseIf shape[i]["func"] = "line" Then
      buf = buf + "  shape[" + i + "] = " + WQ + "func=line;"
      buf = buf + "x=" + (shape[i]["x"] - xmin) + ";"
      buf = buf + "y=" + (shape[i]["y"] - ymin) + ";"
      buf = buf + "x1=" + shape[i]["x1"] + ";"
      buf = buf + "y1=" + shape[i]["y1"] + ";"
      buf = buf + "x2=" + shape[i]["x2"] + ";"
      buf = buf + "y2=" + shape[i]["y2"] + ";"
    EndIf
    If shape[i]["pw"] > 0 Then
      buf = buf + "pc=" + shape[i]["pc"] + ";"
    EndIf
    buf = buf + "pw=" + shape[i]["pw"] + ";" + WQ + CRLF
  EndFor
  buf = buf + "EndSub" + CRLF
  buf = buf + CRLF
  buf = buf + "Sub Shapes_Add" + CRLF
  buf = buf + "  ' Shapes | Add shapes as shapes data" + CRLF
  buf = buf + "  ' param shape - array of shapes" + CRLF
  buf = buf + "  ' param scale - to zoom" + CRLF
  buf = buf + "  ' return nShapes - number of shapes" + CRLF
  buf = buf + "  ' return shAngle - current angle of shapes" + CRLF
  buf = buf + "  Stack.PushValue(" + WQ + "local" + WQ + ", i)" + CRLF
  buf = buf + "  nShapes = Array.GetItemCount(shape)" + CRLF
  buf = buf + "  s = scale" + CRLF
  buf = buf + "  For i = 1 To nShapes" + CRLF
  buf = buf + "    GraphicsWindow.PenWidth = shape[i][" + WQ + "pw" + WQ + "] * s" + CRLF
  buf = buf + "    If shape[i][" + WQ + "pw" + WQ + "] > 0 Then" + CRLF
  buf = buf + "      GraphicsWindow.PenColor = shape[i][" + WQ + "pc" + WQ + "]" + CRLF
  buf = buf + "    EndIf" + CRLF
  buf = buf + "    If shape[i][" + WQ + "func" + WQ + "] = " + WQ + "rect" + WQ + " Then" + CRLF
  buf = buf + "      GraphicsWindow.BrushColor = shape[i][" + WQ + "bc" + WQ + "]" + CRLF
  buf = buf + "      shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddRectangle(shape[i][" + WQ + "width" + WQ + "]* s, shape[i][" + WQ + "height" + WQ + "] * s)" + CRLF
  buf = buf + "    ElseIf shape[i][" + WQ + "func" + WQ + "] = " + WQ + "ell" + WQ + " Then" + CRLF
  buf = buf + "      GraphicsWindow.BrushColor = shape[i][" + WQ + "bc" + WQ + "]" + CRLF
  buf = buf + "      shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddEllipse(shape[i][" + WQ + "width" + WQ + "]* s, shape[i][" + WQ + "height" + WQ + "] * s)" + CRLF
  buf = buf + "    ElseIf shape[i][" + WQ + "func" + WQ + "] = " + WQ + "tri" + WQ + " Then" + CRLF
  buf = buf + "      GraphicsWindow.BrushColor = shape[i][" + WQ + "bc" + WQ + "]" + CRLF
  buf = buf + "      shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddTriangle(shape[i][" + WQ + "x1" + WQ + "] * s, shape[i][" + WQ + "y1" + WQ + "] * s, shape[i][" + WQ + "x2" + WQ + "] * s, shape[i][" + WQ + "y2" + WQ + "] * s, shape[i][" + WQ + "x3" + WQ + "] * s, shape[i][" + WQ + "y3" + WQ + "] * s)" + CRLF
  buf = buf + "    ElseIf shape[i][" + WQ + "func" + WQ + "] = " + WQ + "line" + WQ + " Then" + CRLF
  buf = buf + "      shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddLine(shape[i][" + WQ + "x1" + WQ + "] * s, shape[i][" + WQ + "y1" + WQ + "] * s, shape[i][" + WQ + "x2" + WQ + "] * s, shape[i][" + WQ + "y2" + WQ + "] * s)" + CRLF
  buf = buf + "    EndIf" + CRLF
  buf = buf + "    Shapes.Move(shape[i][" + WQ + "obj" + WQ + "], shX + shape[i][" + WQ + "x" + WQ + "] * s, shY + shape[i][" + WQ + "y" + WQ + "] * s)" + CRLF
  buf = buf + "    If Text.IsSubText(" + WQ + "rect|ell|tri" + WQ + ", shape[i][" + WQ + "func" + WQ + "]) And shape[i][" + WQ + "angle" + WQ + "] <> 0 Then" + CRLF
  buf = buf + "      Shapes.Rotate(shape[i][" + WQ + "obj" + WQ + "], shape[i][" + WQ + "angle" + WQ + "])" + CRLF
  buf = buf + "    EndIf" + CRLF
  buf = buf + "    shape[i][" + WQ + "rx" + WQ + "] = shape[i][" + WQ + "x" + WQ + "]" + CRLF
  buf = buf + "    shape[i][" + WQ + "ry" + WQ + "] = shape[i][" + WQ + "y" + WQ + "]" + CRLF
  buf = buf + "  EndFor" + CRLF
  buf = buf + "  shAngle = 0" + CRLF
  buf = buf + "  i = Stack.PopValue(" + WQ + "local" + WQ + ")" + CRLF
  buf = buf + "EndSub" + CRLF
  ' Import GTV460-0 and insert here if you need move and rotation in output program.
  File_Save()
  i = Stack.PopValue("local")
EndSub

Sub Color_ColorToRGB
  ' Color | Convert Color to RGB
  ' param sColor - "#rrggbb"
  ' return iR, iG, iB - [0, 255]
  sR = Text.GetSubText(sColor, 2, 2)
  sG = Text.GetSubText(sColor, 4, 2)
  sB = Text.GetSubText(sColor, 6, 2)
  sHex = sR
  Math_Hex2Dec()
  iR = iDec
  sHex = sG
  Math_Hex2Dec()
  iG = iDec
  sHex = sB
  Math_Hex2Dec()
  iB = iDec
EndSub

Sub Color_HSLtoRGB
  ' Color | Convert HSL to RGB
  ' param rHue - [0, 360) or UNDEFINED
  ' param rLightness - [0, 1]
  ' param rSaturation - [0, 1]
  ' return iR, iG, iB - RGB color
  ' return sColor - "#rrggbb"
  If rLightness <= 0.5 Then
    rN2 = rLightness * (1 + rSaturation)
  Else
    rN2 = rLightness + rSaturation - rLightness * rSaturation
  EndIf
  rN1 = 2 * rLightness - rN2
  If rSaturation = 0 Then
    iR = Math.Round(rLightness * 255)
    iG = Math.Round(rLightness * 255)
    iB = Math.Round(rLightness * 255)
  Else
    rH = rHue + 120
    Color_Value()
    iR = iValue
    rH = rHue
    Color_Value()
    iG = iValue
    rH = rHue - 120
    Color_Value()
    iB = iValue
  EndIf
  sColor = GraphicsWindow.GetColorFromRGB(iR, iG, iB)
EndSub

Sub Color_RGBtoHSL
  ' Color | Convert RGB to HSL
  ' param sColor - "#rrggbb"
  ' return rHue - [0, 360) or UNDEFINED
  ' return rLightness - (0, 1)
  ' return rSaturation - (0, 1)
  Color_ColorToRGB()
  ' rR = iR / 255 ' occurs Math.Max() bug
  rR = Math.Round(iR / 255 * 10000) / 10000
  ' rG = iG / 255 ' occurs Math.Max() bug
  rG = Math.Round(iG / 255 * 10000) / 10000
  ' rB = iB / 255 ' occurs Math.Max() bug
  rB = Math.Round(iB / 255 * 10000) / 10000
  rMax = Math.Max(rR, rG)
  rMax = Math.Max(rMax, rB)
  rMin = Math.Min(rR, rG)
  rMin = Math.Min(rMin, rB)
  rLightness = (rMax + rMin) / 2
  If rMax = rMin Then ' rR = rG = rB
    rSaturation = 0
    rHue = UNDEFINED
  Else
    If rLightness <= 0.5 Then
      rSaturation = (rMax - rMin) / (rMax + rMin)
    Else
      rSaturation = (rMax - rMin) / (2 - rMax - rMin)
    EndIf
    rRC = (rMax - rR) / (rMax - rMin)
    rGC = (rMax - rG) / (rMax - rMin)
    rBC = (rMax - rB) / (rMax - rMin)
    If rR = rMax Then     ' between Yellow and Magenta
      rHue = rBC - rGC
    ElseIf rG = rMax Then ' between Cyan and Yellow
      rHue = 2 + rRC - rBC
    ElseIf rB = rMax Then ' between Magenta and Cyan
      rHue = 4 + rGC - rRC
    Else
      TextWindow.WriteLine("Error:")
      TextWindow.WriteLine("rMax=" + rMax)
      TextWindow.WriteLine("rR=" + rR + ",sR=" + sR)
      TextWindow.WriteLine("rG=" + rG + ",sG=" + sG)
      TextWindow.WriteLine("rB=" + rB + ",sB=" + sB)
    EndIf
    rHue = rHue * 60
    If rHue < 0 Then
      rHue = rHue + 360
    EndIf
  EndIf
EndSub

Sub Color_Value
  ' Color | Function value
  ' param rN1, rN2
  ' param rH - [-120, 480)
  ' return iValue - 0..255
  If rH >= 360 Then
    rH = rH - 360
  EndIF
  If rH < 0 Then
    rH = rH + 360
  EndIF 
  If rH < 60 Then
    rV = rN1 + (rN2 - rN1) * rH / 60
  ElseIf rH < 180 Then
    rV = rN2
  ElseIf rH < 240 Then
    rV = rN1 + (rN2 - rN1) * (240 - rH) / 60
  Else
    rV = rN1
  EndIf
  iValue = Math.Round(rV * 255)
EndSub

Sub CS_AddColorToPalette
  ' Color Selector | Add color to palette
  ' param color - color to set
  ' param maxPalette
  ' param nPalette
  ' param palette
  ' param tPalette - target palette
  Stack.PushValue("local", i)
  For i = 1 To nPalette
    If color = palette[i]["color"] Then
      Goto csactp_not_new_color
    EndIf
  EndFor
  palette[tPalette]["color"] = color
  If nPalette < maxPalette Then
    nPalette = nPalette + 1
  EndIf
  tPalette = tPalette + 1
  If maxPalette < tPalette Then
    tPalette = 1
  EndIf
  csactp_not_new_color:  
  i = Stack.PopValue("local")
EndSub

Sub CS_AdjustSlider
  ' Color Selector | Adjust slider
  ' param iSlider - moved slider
  Stack.PushValue("local", iSlider)
  If iSlider = iHue Or iSlider = iLightness Or iSlider = iSaturation Then
    If iSlider = iHue Then
      Slider_GetLevel()
      rHue = level
    ElseIf iSlider = iLightness Then
      Slider_GetLevel()
      rLightness = level / 100
    Else
      Slider_GetLevel()
      rSaturation = level / 100
    EndIf
    Color_HSLtoRGB()
    iSlider = iRed
    level = iR
    Slider_SetLevel()
    iSlider = iGreen
    level = iG
    Slider_SetLevel()
    iSlider = iBlue
    level = iB
    Slider_SetLevel()
  Else
    CS_GetColorFromSlider()
    sColor = GraphicsWindow.GetColorFromRGB(red, green, blue)
    Color_RGBtoHSL()
    If rHue = UNDEFINED Then
      rHue = 0
    EndIf
    iSlider = iHue
    level = Math.Floor(rHue)
    Slider_SetLevel()
    iSlider = iSaturation
    level = Math.Floor(rSaturation * 100)
    Slider_SetLevel()
    iSlider = iLightness
    level = Math.Floor(rLightness * 100)
    Slider_SetLevel()
  EndIf
  iSlider = Stack.PopValue("local")
EndSub

Sub CS_DoObject
  ' Color Selector | Do object
  ' param - obj
  While obj <> ""
    CS_DoSlider()
    If obj <> "" Then
      CS_DoPalette()
    EndIf
  EndWhile
EndSub

Sub CS_DoPalette
  ' Color Selector | Do palette
  ' param obj - clicked object
  If Text.StartsWith(obj, "palette") Then
    iPalette = Text.GetSubTextToEnd(obj, 8)
    color = palette[iPalette]["color"]
    CS_SetColorToSlider()   ' set color to slider
    CS_ShowNewColor()       ' show new color name
    CS_DrawColorRect()      ' draw new color rectangle
    obj = ""
    param = "down=True;move=False;up=False;"  ' wait to click
    Mouse_SetHandler()
  EndIf
EndSub

Sub CS_DoSlider
  ' Color Selector | Do slider
  ' param obj - clicked object
  ' param iSlider - index of slider
  If Text.StartsWith(obj, "slider") Then
    Slider_WaitToRelease()
    obj = ""
    param = "down=True;move=False;up=False;"  ' wait to click
    Mouse_SetHandler()
  EndIf
EndSub

Sub CS_DrawColorRect
  ' Color Selector | Draw color rectangle
  ' param color - color of rectangle
  ' param x, y, width, height - position and size of rectangle
  ' return oRect - rectangle object
  GraphicsWindow.BrushColor = color
  GraphicsWindow.PenColor = BORDERCOLOR
  If oRect <> "" Then
    Shapes.Remove(oRect)
  EndIf
  oRect = Shapes.AddRectangle(width, height)
  Shapes.Move(oRect, x, y)
EndSub

Sub CS_DrawPalette
  ' Color Selector | Draw palette
  ' param palette[] - color palette
  ' param nPalette - number of color in palette
  ' param x, y, width, height - position and size of rectangle
  ' return oPalette[] - palette object array
  Stack.PushValue("local", i)
  GraphicsWindow.PenColor = BORDERCOLOR
  For i = 1 To nPalette
    GraphicsWindow.BrushColor = palette[i]["color"]
    palette[i]["oCell"] = Shapes.AddRectangle(width, height)
    dx = Math.Remainder((i - 1), 8) * (width + 4)
    dy = Math.Floor((i - 1) / 8) * (height + 4)
    Shapes.Move(palette[i]["oCell"], x + dx, y + dy)
    palette[i]["x"] = x + dx
    palette[i]["y"] = y + dy
    palette[i]["width"] = width
    palette[i]["height"] = height
  EndFor
  i = Stack.PopValue("local")
EndSub

Sub CS_GetColorFromSlider
  ' Color Selector | get color from slider
  ' return color
  Stack.PushValue("local", iSlider)
  iSlider = iRed    ' slider index
  Slider_GetLevel()
  red = level
  iSlider = iGreen  ' slider index
  Slider_GetLevel()
  green = level
  iSlider = iBlue   ' slider index
  Slider_GetLevel()
  blue = level
  color = GraphicsWindow.GetColorFromRGB(red, green, blue)
  iSlider = Stack.PopValue("local")
EndSub

Sub CS_Init
  ' Color Selector | Initialize sliders
  width = 256
  min = 0
  max = 255
  left = 190
  ' add red slider
  top = TOPY
  caption = "R"
  Slider_Add()
  iRed = iSlider        ' index of slider
  ' add green slider
  top = top + DELTAY
  caption = "G"
  Slider_Add()
  iGreen = iSlider      ' index of slider
  ' add blue slider
  top = top + DELTAY
  caption = "B"
  Slider_Add()
  iBlue = iSlider       ' index of slider
  ' add hue slider
  width = 360
  top = top + DELTAY
  max = 360
  caption = "H"
  Slider_Add()
  iHue = iSlider        ' index of slider
  ' add saturation slider
  width = 100
  top = top + DELTAY
  max = 100
  caption = "S"
  Slider_Add()
  iSaturation = iSlider ' index of slider
  ' add lightness slider
  width = 100
  top = top + DELTAY
  max = 100
  caption = "L"
  Slider_Add()
  iLightness = iSlider  ' index of slider
  ' draw color rectangle
  CS_GetColorFromSlider()
  CS_ShowNewColor()
  x = LEFTX
  y = TOPY + DELTAY * 4
  width = 100 
  height = 100
  CS_DrawColorRect()
  ' add text box
  GraphicsWindow.BrushColor = CAPTIONCOLOR
  top = y + height + 4
  oNewColor = Shapes.AddText("")
  Shapes.Move(oNewColor, LEFTX, top)
EndSub

Sub CS_DumpSlider
  ' Color Selector | Dump slider for debug
  For i = 1 To numSlider
    TextWindow.WriteLine("slider" + i)
    TextWindow.WriteLine(slider[i])
  EndFor
EndSub

Sub CS_InitPalette
  ' Color Selector | Initialize palette
  ' This subroutine should be called before CS_ShowPopup().
  pcolor = GraphicsWindow.PenColor
  bcolor = GraphicsWindow.BrushColor
  maxPalette = 16 ' max cell number of palette
  nPalette = 2    ' number of palette in use
  tPalette = 3    ' index of update target cell
  palette[1]["color"] = pcolor
  palette[2]["color"] = bcolor
EndSub

Sub CS_RemovePalette
  ' Color Selector | Remove palette
  ' param nPalette - number of color in palette
  ' return oPalette[] - palette object array
  Stack.PushValue("local", i)
  For i = 1 To nPalette
    oPalette = "Palette" + i
    Shapes.Remove(palette[i]["oCell"])
  EndFor
  i = Stack.PopValue("local")
EndSub

Sub CS_RemoveSliders
  ' Color Selector | Remove sliders
  For iSlider = 1 To numSlider
    Slider_Remove()
  EndFor
  numSlider = 0
EndSub

Sub CS_SearchClickedObject
  ' Color Selector | Check slider clicked
  ' param mxD, myD - clicked point
  ' return obj - clicked slider or palette
  ' return iSlider - index if obj is slider
  ' return iPalette - index if obj is palette
  Stack.PushValue("local", i)
  For iSlider = 1 To numSlider
    obj = "slider" + iSlider
    x2 = slider[iSlider]["x2"]
    y2 = slider[iSlider]["y2"]
    x3 = slider[iSlider]["x3"]
    y3 = slider[iSlider]["y3"]
    If x2 <= mxD And mxD <= x3 And y2 <= myD And myD <= y3 Then
      Goto scco_obj_found
    EndIf
  EndFor
  For iPalette = 1 To nPalette
    obj = "palette" + iPalette
    x2 = palette[iPalette]["x"]
    y2 = palette[iPalette]["y"]
    x3 = palette[iPalette]["x"] + palette[iPalette]["width"]
    y3 = palette[iPalette]["y"] + palette[iPalette]["height"]
    If x2 <= mxD And mxD <= x3 And y2 <= myD And myD <= y3 Then
      Goto scco_obj_found
    EndIf
  EndFor
  obj = ""
  scco_obj_found:
  i = Stack.PopValue("local")
EndSub

Sub CS_SetColorToSlider
  ' Color Selector | Set color to slider
  ' param color
  Stack.PushValue("local", iSlider)
  sColor = color
  Color_ColorToRGB()
  iSlider = iRed
  level = iR
  Slider_SetLevel()
  iSlider = iGreen
  level = iG
  Slider_SetLevel()
  iSlider = iBlue
  level = iB
  Slider_SetLevel()
  CS_AdjustSlider()
  iSlider = Stack.PopValue("local")
EndSub

Sub CS_ShowNewColor
  ' Color Selector | Show new color
  ' param oColor
  ' param color
  Shapes.SetText(oNewColor, color)
EndSub

Sub CS_ShowPopup
  ' Color Selector | Show popup
  ' param color - current color
  ' return color - new color
  ' define constant
  Stack.PushValue("local", cont)
  colorInit = color           ' initial color
  TOPY = 80   ' top y
  LEFTX = 36  ' left x
  BORDERCOLOR = "#666666"
  BOXCOLOR = "LightGray"
  CAPTIONCOLOR = "White"
  DELTAY = 36 ' delta y
  SLITCOLOR = "#555555"
  TEXTCOLOR = "Black"
  UNDEFINED = "N/A"
  POPUPCOLOR = "Black"
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.PenColor = POPUPCOLOR
  GraphicsWindow.BrushColor = POPUPCOLOR
  oPopup = Shapes.AddRectangle(570, 310)
  Shapes.SetOpacity(oPopup, 64)
  Shapes.Move(oPopup, LEFTX - 10, TOPY - 10)
  oOK = Controls.AddButton("OK", LEFTX + 440, TOPY + 260)
  oCancel = Controls.AddButton("Cancel", LEFTX + 480, TOPY + 260)
  Controls.ButtonClicked = CS_OnButtonClicked
  CS_Init()
  Stack.PushValue("local", y)
  y = TOPY
  color = colorInit
  CS_DrawColorRect()    ' original color
  oRectCurrent = oRect
  oRect = ""            ' keep current color
  GraphicsWindow.SetPixel(0, 0, colorInit)
  color = GraphicsWindow.GetPixel(0, 0)
  GraphicsWindow.SetPixel(0, 0, "LightGray")
  GraphicsWindow.BrushColor = CAPTIONCOLOR
  oColor = Shapes.AddText(colorInit)
  Shapes.Move(oColor, x, y + height + 2)
  If color <> colorInit Then
    oColor2 = Shapes.AddText(color)
    Shapes.Move(oColor2, x, y + height + 14)
  EndIf
  y = Stack.PopValue("local")
  CS_SetColorToSlider()
  CS_DrawColorRect()      ' draw new color rectangle
  CS_ShowNewColor()       ' show new color name
  Stack.PushValue("local", x)
  Stack.PushValue("local", y)
  Stack.PushValue("local", width)
  Stack.PushValue("local", height)
  x = x + width + 30
  y = TOPY + height * 2 + 24
  width = 30
  height = 30
  CS_DrawPalette()
  height = Stack.PopValue("local")
  width = Stack.PopValue("local")
  y = Stack.PopValue("local")
  x = Stack.PopValue("local")
  cont = "True"         ' continue
  param = "down=True;move=False;up=False;"   ' wait click
  Mouse_SetHandler()
  While cont
    If clicked Then
      CS_SearchClickedObject()
      CS_DoObject()
      clicked = "False"
    Else
      Program.Delay(100)
    EndIf
  EndWhile
  If cancel Then
    color = colorInit
  Else
    CS_AddColorToPalette()
  EndIf
  CS_RemovePalette()
  CS_RemoveSliders()
  Shapes.Remove(oColor)
  Shapes.Remove(oColor2)
  Shapes.Remove(oNewColor)
  Shapes.Remove(oRectCurrent)
  Shapes.Remove(oRect)
  Controls.Remove(oOK)
  Controls.Remove(oCancel)
  Shapes.Remove(oPopup)
  cont = Stack.PopValue("local")
EndSub

Sub CS_OnButtonClicked
  ' Color Selector | Event handler on button clicked
  cont = "False"
  If Controls.LastClickedButton = oCancel Then
    cancel = "True"
  Else
    cancel = "False"
  EndIf
EndSub

Sub File_Open
  ' File | Show output program to save
  Stack.PushValue("local", cont)
  TOPY = 80   ' top y
  LEFTX = 36  ' left x
  CAPTIONCOLOR = "White"
  POPUPCOLOR = "Black"
  TEXTCOLOR = "Black"
  GraphicsWindow.PenWidth = 0
  GraphicsWindow.BrushColor = POPUPCOLOR
  oPopup = Shapes.AddRectangle(570, 310)
  Shapes.SetOpacity(oPopup, 64)
  Shapes.Move(oPopup, LEFTX - 10, TOPY - 10)
  GraphicsWindow.BrushColor = CAPTIONCOLOR
  oCaption = Shapes.AddText("Filename")
  Shapes.Move(oCaption, LEFTX, TOPY + 2)
  GraphicsWindow.BrushColor = TEXTCOLOR
  oFilename = Controls.AddTextBox(LEFTX + 80, TOPY)
  Controls.SetSize(oFilename, 300, 24)
  oText = Controls.AddTextBox(LEFTX, TOPY + 30)
  Controls.SetSize(oText, 550, 210)
  oOK = Controls.AddButton("OK", LEFTX + 500, TOPY + 260)
  Controls.ButtonClicked = File_OnButtonClicked
  Controls.TextTyped = File_OnTextTyped
  subname = "Shapes_Init"
  fo_retry:
  typed = "False"
  cont = "True"         ' continue
  While cont
    If typed Then
      filename = Controls.GetTextBoxText(oFilename)
      SB_GetSub()
      typed = "False"
    Else
      Program.Delay(200)
    EndIf
  EndWhile
  Controls.Remove(oFilename)
  Controls.Remove(oText)
  Controls.Remove(oOK)
  Controls.Remove(oPopup)
  cont = Stack.PopValue("local")
EndSub

Sub File_OnTextTyped
  ' File | Textbox event handler
  typed = "True"
EndSub

Sub File_Save
  ' File | Show output program to save
  ' param buf - program buffer
  ' define constant
  Stack.PushValue("local", cont)
  TOPY = 80   ' top y
  LEFTX = 36  ' left x
  POPUPCOLOR = "Black"
  TEXTCOLOR = "Black"
  CAPTIONCOLOR = "White"
  GraphicsWindow.PenWidth = 0
  GraphicsWindow.BrushColor = POPUPCOLOR
  oPopup = Shapes.AddRectangle(570, 310)
  Shapes.SetOpacity(oPopup, 64)
  Shapes.Move(oPopup, LEFTX - 10, TOPY - 10)
  GraphicsWindow.BrushColor = TEXTCOLOR
  oText = Controls.AddTextBox(LEFTX, TOPY)
  Controls.SetSize(oText, 550, 240)
  Controls.SetTextBoxText(oText, buf)
  oOK = Controls.AddButton("OK", LEFTX + 500, TOPY + 260)
  GraphicsWindow.BrushColor = CAPTIONCOLOR
  oMsg = Shapes.AddText("Click textbox above, push Ctrl+A, Ctrl+C to copy and save to your editor")
  Shapes.Move(oMsg, LEFTX, TOPY + 260)
  cont = "True"         ' continue
  Controls.ButtonClicked = File_OnButtonClicked
  While cont
    Program.Delay(500)
  EndWhile
  Controls.Remove(oText)
  Controls.Remove(oMsg)
  Controls.Remove(oOK)
  Controls.Remove(oPopup)
  cont = Stack.PopValue("local")
EndSub

Sub File_OnButtonClicked
  ' File | Button event handler
  cont = "False"
EndSub

Sub KB_FlushFIFO
  ' Keyborad | Flush keyboard buffer (FIFO)
  For out = out + 1 To in
    fifok[out] = ""
    fifos[out] = ""
    fifoc[out] = ""
  EndFor    
EndSub

Sub KB_InKey
  ' Keyboard | In key
  ' return c - input key
  c = ""
  If in > out Then
    out = out + 1
    c = fifok[out]
    _shift = fifos[out]
    _ctrl = fifoc[out]
    fifok[out] = ""
    fifos[out] = ""
    fifoc[out] = ""
    If Text.GetLength(c) > 1 Then
      If Array.ContainsIndex(keys, c) Then
        c = keys[_shift + c]
      Else
        c = "<" + c + ">" 
      EndIf
    ElseIf _shift = "" Then
      c = Text.ConvertToLowerCase(c)
    EndIf
    c = Text.Append(_ctrl, c)
  EndIf
EndSub  

Sub KB_Init
  ' Keyboard | Initialization for Shapes (use only ^x, ^c, ^v, del and arrow keys)
  shift = ""
  ctrl = ""
  in = 0
  out = 0
  keys = "Delete=DEL;Left=LEFT;Right=RIGHT;Up=UP;Down=DOWN;"
  arrow_dx = "LEFT=-1;RIGHT=1;UP=0;DOWN=0;"
  arrow_dy = "LEFT=0;RIGHT=0;UP=-1;DOWN=1;"
  GraphicsWindow.KeyDown = KB_OnKeyDown
  GraphicsWindow.KeyUp = KB_OnKeyUp
EndSub  

Sub KB_OnKeyDown
  ' Keyboard | Key down event handler
  key = GraphicsWindow.LastKey
  If key = "LeftShift" Or key = "RightShift" Then
    shift = "+"
  ElseIf key = "LeftCtrl" Or key = "RightCtrl" Then
    ctrl = "^"
  Else
    in = in + 1
    fifok[in] = key
    fifos[in] = shift
    fifoc[in] = ctrl
  EndIf
EndSub

Sub KB_OnKeyUp
  ' Keyboard | Key up event handler
  key = GraphicsWindow.LastKey
  If key = "LeftShift" Or key = "RightShift" Then
    shift = ""
  ElseIf key = "LeftCtrl" Or key = "RightCtrl" Then
    ctrl = ""
  EndIf
EndSub

Sub Math_CartesianToPolar
  ' Math | convert cartesian coodinate to polar coordinate
  ' param x, y - cartesian coordinate
  ' return r, a - polar coordinate
  r = Math.SquareRoot(x * x + y * y)
  If x = 0 And y > 0 Then
    a = 90 ' [degree]
  ElseIf x = 0 And y < 0 Then
    a = -90
  Else
    a = Math.ArcTan(y / x) * 180 / Math.Pi
  EndIf
  If x < 0 Then
    a = a + 180
  ElseIf x > 0 And y < 0 Then
    a = a + 360
  EndIf
EndSub

Sub Math_Hex2Dec
  ' Math | Convert hexadecimal to decimal
  ' param sHex
  ' return iDec
  iDec = 0
  iLen = Text.GetLength(sHex)
  For iPtr = 1 To iLen
    iDec = iDec * 16 + Text.GetIndexOf("0123456789ABCDEF", Text.GetSubText(sHex, iPtr, 1)) - 1
  EndFor
EndSub

Sub Mouse_Init
  ' Mouse | Initialize for common event handler
  clicked = "False"
  moved = "False"
  released = "False"
  If debug Then
    Timer.Interval = 200
    Timer.Tick = Mouse_OnTick
  EndIf
EndSub

Sub Mouse_SetHandler
  ' Mouse | Set or reset common event handler
  ' param["down"] - "True" if set, "False" if reset
  ' param["move"] - "True" if set, "False" if reset
  ' param["up"] -  - "True" if set, "False" if reset
  ' return clicked - "False" if set MouseDown
  ' return moved - "False" if set MouseMove
  ' return released - "False" if set MouseUp
  ' return dmu - which handlers are set for debug
  If param["up"] Then
    released = "False"
    GraphicsWindow.MouseUp = Mouse_OnUp
    handler["up"] = "U"
  ElseIf param["up"] = "False" Then
    GraphicsWindow.MouseUp = Mouse_DoNothing
    handler["up"] = ""
  EndIf
  If param["down"] Then
    clicked = "False"
    GraphicsWindow.MouseDown = Mouse_OnDown
    handler["down"] = "D"
  ElseIf param["down"] = "False" Then
    GraphicsWindow.MouseDown = Mouse_DoNothing
    handler["down"] = ""
  EndIf
  If param["move"] Then
    moved = "False"
    GraphicsWindow.MouseMove = Mouse_OnMove
    handler["move"] = "M"
  ElseIf param["move"] = "False" Then
    GraphicsWindow.MouseMove = Mouse_DoNothing
    handler["move"] = ""
  EndIf
  dmu = handler["down"] + handler["move"] + handler["up"] 
  If debug Then
    smrc = " set "
  EndIf
EndSub

Sub Mouse_OnDown
  ' Mouse | Common event handler on mouse down
  ' return mxD, myD - position on mouse down
  mxD = GraphicsWindow.MouseX
  myD = GraphicsWindow.MouseY
  clicked = "True"
  released = "False"
  If debug Then
    smrc = " clicked " + mxD + "," + myD
  EndIf
EndSub

Sub Mouse_DoNothing
  ' Mouse | Common event handler to do nothing
EndSub

Sub Mouse_OnMove
  ' Mouse | Common event handler on mouse move
  ' return mxM, myM - position on mouse move
  mxM = GraphicsWindow.MouseX
  myM = GraphicsWindow.MouseY
  moved = "True"
  If debug Then
    smrc = " moved " + mxM + "," + myM
  EndIf
EndSub

Sub Mouse_OnTick
  ' Mouse | debug routine
  If clicked Then
    cmr = "C"
  Else
    cmr = ""
  EndIf
  If moved Then
    cmr = cmr + "M"
  EndIf
  If released Then
    cmr = cmr + "R"
  EndIf
  GraphicsWindow.Title = title + smrc + " " + dmu + " " + cmr
EndSub

Sub Mouse_OnUp
  ' Mouse | Common event handler on mouse up
  ' return mxU, myU - position on mouse up
  mxU = GraphicsWindow.MouseX
  myU = GraphicsWindow.MouseY
  released = "True"
  If debug Then
    smrc = " released " + mxU + "," + myU
  EndIf
EndSub

Sub SB_GetSub
  ' Small Basic | Get subroutine from Small Basic source file
  ' param filename - file name
  ' param subname - subroutine name
  ' return buf - subroutine buffer
  len = Text.GetLength(subname)
' The following line could be harmful and has been automatically commented.
'   buf = File.ReadContents(filename)
  ptr = 1
  notFound = "True"
  While notFound
    _ptr = Text.GetIndexOf(Text.GetSubTextToEnd(buf, ptr), "Sub")
    If _ptr = 0 Then
      buf = ""
      Goto sbgs_exit
    EndIf
    ptrSub = ptr + _ptr - 1
    ptr = ptrSub + 3
    While Text.GetSubText(buf, ptr, 1) = " "
      ptr = ptr + 1
    EndWhile
    If Text.GetSubText(buf, ptr, len) = subname Then
      notFound = "False"
    EndIf
  EndWhile
  _ptr = Text.GetIndexOf(Text.GetSubTextToEnd(buf, ptr), "EndSub")
  If _ptr = 0 Then
    buf = ""
    Goto sbgs_exit
  EndIf
  ptrEndSub = ptr + _ptr - 1
  ptr = ptrEndSub + 6
  len = ptr - ptrSub
  buf = Text.GetSubText(buf, ptrSub, len)
  sbgs_exit:
  Controls.SetTextBoxText(oText, buf)
EndSub

Sub Scissors_Init
  ' Scissors | Initialize shapes data for menu icon
  ' return shX, shY - current position of shapes
  ' return shape - array of shapes
  shX = 230 ' x offset
  shY = 30 ' y offset
  shape = ""
  shape[1] = "func=tri;x=45;y=0;x1=22;y1=0;x2=0;y2=213;x3=44;y3=213;bc=#6E6E6E;pw=0;"
  shape[2] = "func=rect;x=45;y=212;width=15;height=47;bc=#6E6E6E;pw=0;"
  shape[3] = "func=ell;x=0;y=235;width=66;height=104;bc=#EEEEEE;pc=#0C95BB;pw=16;"
  shape[4] = "func=tri;x=45;y=0;x1=22;y1=0;x2=0;y2=213;x3=44;y3=213;bc=#939393;pw=0;"
  shape[5] = "func=rect;x=75;y=212;width=14;height=49;bc=#919191;pw=0;"
  shape[6] = "func=ell;x=61;y=163;width=13;height=15;bc=#6E6E6E;pw=0;"
  shape[7] = "func=ell;x=70;y=236;width=64;height=104;bc=#EEEEEE;pc=#0C95BB;pw=16;"
EndSub

Sub Shapes_Add
  ' Shapes | add shapes as shapes data
  ' param shape - array of shapes
  ' param iMin, iMax - shape indices to add
  ' param scale - 1 if same scale
  ' return shWidth, shHeight - total size of shapes
  ' return shAngle - current angle of shapes
  Stack.PushValue("local", i)
  Shapes_CalcWidthAndHeight()
  s = scale
  For i = iMin To iMax
    GraphicsWindow.PenWidth = shape[i]["pw"] * s
    If shape[i]["pw"] > 0 Then
      GraphicsWindow.PenColor = shape[i]["pc"]
    EndIf
    If shape[i]["func"] = "rect" Then
      GraphicsWindow.BrushColor = shape[i]["bc"]
      shape[i]["obj"] = Shapes.AddRectangle(shape[i]["width"]* s, shape[i]["height"] * s)
    ElseIf shape[i]["func"] = "ell" Then
      GraphicsWindow.BrushColor = shape[i]["bc"]
      shape[i]["obj"] = Shapes.AddEllipse(shape[i]["width"]* s, shape[i]["height"] * s)
    ElseIf shape[i]["func"] = "tri" Then
      GraphicsWindow.BrushColor = shape[i]["bc"]
      shape[i]["obj"] = Shapes.AddTriangle(shape[i]["x1"] * s, shape[i]["y1"] * s, shape[i]["x2"] * s, shape[i]["y2"] * s, shape[i]["x3"] * s, shape[i]["y3"] * s)
    ElseIf shape[i]["func"] = "line" Then
      shape[i]["obj"] = Shapes.AddLine(shape[i]["x1"] * s, shape[i]["y1"] * s, shape[i]["x2"] * s, shape[i]["y2"] * s)
    EndIf
    Shapes.Move(shape[i]["obj"], shX + shape[i]["x"] * s, shY + shape[i]["y"] * s)
    If Text.IsSubText("rect|ell|tri", shape[i]["func"]) And shape[i]["angle"] <> 0 Then
      Shapes.Rotate(shape[i]["obj"], shape[i]["angle"])
    EndIf
    shape[i]["rx"] = shape[i]["x"]
    shape[i]["ry"] = shape[i]["y"]
  EndFor
  shAngle = 0
  i = Stack.PopValue("local")
EndSub

Sub Shapes_CalcWidthAndHeight
  ' Shapes | Calculate total width and height of shapes
  ' param iMin, iMax - shape indices to add
  ' return nShapes - number of shapes
  ' return shWidth, shHeight - total size of shapes
  For i = iMin To iMax
    If shape[i]["func"] = "tri" Or shape[i]["func"] = "line" Then
      xmin = shape[i]["x1"]
      xmax = shape[i]["x1"]
      ymin = shape[i]["y1"]
      ymax = shape[i]["y1"]
      If shape[i]["x2"] < xmin Then
        xmin = shape[i]["x2"]
      EndIf
      If xmax < shape[i]["x2"] Then
        xmax = shape[i]["x2"]
      EndIf
      If shape[i]["y2"] < ymin Then
        ymin = shape[i]["y2"]
      EndIf
      If ymax < shape[i]["y2"] Then
        ymax = shape[i]["y2"]
      EndIf
      If shape[i]["func"] = "tri" Then
        If shape[i]["x3"] < xmin Then
          xmin = shape[i]["x3"]
        EndIf
        If xmax < shape[i]["x3"] Then
          xmax = shape[i]["x3"]
        EndIf
        If shape[i]["y3"] < ymin Then
          ymin = shape[i]["y3"]
        EndIf
        If ymax < shape[i]["y3"] Then
          ymax = shape[i]["y3"]
        EndIf
      EndIf
      shape[i]["width"] = xmax - xmin
      shape[i]["height"] = ymax - ymin
    EndIf
    If i = 1 Then
      shWidth = shape[i]["x"] + shape[i]["width"]
      shHeight = shape[i]["y"] + shape[i]["height"]
    Else
      If shWidth < shape[i]["x"] + shape[i]["width"] Then
        shWidth = shape[i]["x"] + shape[i]["width"]
      EndIf
      If shHeight < shape[i]["y"] + shape[i]["height"] Then
        shHeight = shape[i]["y"] + shape[i]["height"]
      EndIf
    EndIf
  EndFor
EndSub

Sub Shapes_CalcRotatePos
  ' Shapes | Calculate position for rotated shape
  ' param["x"], param["y"] - position of a shape
  ' param["width"], param["height"] - size of a shape
  ' param ["cx"], param["cy"] - center of rotation
  ' param ["angle"] - rotate angle
  ' return x, y - rotated position of a shape
  _cx = param["x"] + param["width"] / 2
  _cy = param["y"] + param["height"] / 2
  x = _cx - param["cx"]
  y = _cy - param["cy"]
  Math_CartesianToPolar()
  a = a + param["angle"]
  x = r * Math.Cos(a * Math.Pi / 180)
  y = r * Math.Sin(a * Math.Pi / 180)
  _cx = x + param["cx"]
  _cy = y + param["cy"]
  x = _cx - param["width"] / 2
  y = _cy - param["height"] / 2
EndSub

Sub Shapes_Move
  ' Shapes | Move shapes
  ' param shape - array of shapes
  ' param scale
  ' param x, y - position to move
  ' return shX, shY - new position of shapes
  Stack.PushValue("local", i)
  shX = x
  shY = y
  For i = 1 To nShapes
    _x = shape[i]["x"]
    _y = shape[i]["y"]
    Shapes.Move(shape[i]["obj"], shX + _x * s, shY + _y * s)
  EndFor
  i = Stack.PopValue("local")
EndSub

Sub Shapes_Remove
  ' Shapes | Remove shapes
  ' param iMin, iMax - shapes indices to remove
  ' param shape - array of shapes
  Stack.PushValue("local", i)
  For i = iMin To iMax
    Shapes.Remove(shape[i]["obj"])
  EndFor
  i = Stack.PopValue("local")
EndSub

Sub Shapes_Rotate
  ' Shapes | Rotate shapes
  ' param shape - array of shapes
  ' param scale - to zoom
  ' param angle - to rotate
  Stack.PushValue("local", i)
  Stack.PushValue("local", x)
  Stack.PushValue("local", y)
  s = scale
  param["angle"] = angle
  param["cx"] = shWidth / 2
  param["cy"] = shHeight / 2
  For i = 1 To nShapes
    param["x"] = shape[i]["x"]
    param["y"] = shape[i]["y"]
    param["width"] = shape[i]["width"]
    param["height"] = shape[i]["height"]
    Shapes_CalcRotatePos()
    Shapes.Move(shape[i]["obj"], shX + x * s, shY + y * s)
    Shapes.Rotate(shape[i]["obj"], angle)
  EndFor
  y = Stack.PopValue("local")
  x = Stack.PopValue("local")
  i = Stack.PopValue("local")
EndSub

Sub Slider_Add
  ' Slider | Add slider as shapes and property
  ' param width
  ' param caption
  ' param min, max
  ' param left, top
  ' return slider[] - property of slider
  ' return iSlider - added slider index
  numSlider = numSlider + 1
  iSlider = numSlider
  ' add shapes for slider
  GraphicsWindow.BrushColor = CAPTIONCOLOR
  len = Text.GetLength(caption)
  slider[iSlider]["oCaption"] = Shapes.AddText(caption)
  Shapes.Move(slider[iSlider]["oCaption"], left - (len * 5 + 10), top + 1)
  level = Math.Floor((min + max) / 2)
  slider[iSlider]["level"] = level  ' property
  slider[iSlider]["min"] = min
  slider[iSlider]["max"] = max
  GraphicsWindow.PenColor = BORDERCOLOR
  mag = (level - min) / (max - min)
  GraphicsWindow.BrushColor = SLITCOLOR
  slider[iSlider]["oSlit"] = Shapes.AddRectangle(width, 10)
  GraphicsWindow.PenColor = BORDERCOLOR
  GraphicsWindow.BrushColor = BOXCOLOR
  slider[iSlider]["oBox"] = Shapes.AddRectangle(10, 18)
  GraphicsWindow.BrushColor = CAPTIONCOLOR
  slider[iSlider]["oLevel"] = Shapes.AddText(level)
  slider[iSlider]["x0"] = left
  slider[iSlider]["x1"] = left + width
  slider[iSlider]["y0"] = top
  Shapes.Move(slider[iSlider]["oLevel"], left + width + 5, top)
  ' move and zoom shapes for slider
  Shapes.Move(slider[iSlider]["oSlit"], left, top + 4)
  Slider_SetLevel()
EndSub

Sub Slider_CallBack
  ' Slider | Call back
  ' param iSlider - changed slider
  CS_AdjustSlider()
  CS_GetColorFromSlider()
  CS_ShowNewColor()       ' show new color name
  CS_DrawColorRect()      ' draw new color rectangle
EndSub

Sub Slider_GetLevel
  ' Slider | Get latest level of slider
  ' param iSlider
  ' return level
  level = slider[iSlider]["level"]
EndSub

Sub Slider_GetMouseLevel
  ' Slider | Get mouse level of slider
  ' param iSlider
  ' return level
  x0 = slider[iSlider]["x0"]
  x1 = slider[iSlider]["x1"]
  max = slider[iSlider]["max"]
  min = slider[iSlider]["min"]
  level = min + Math.Floor((max - min) * (mxM - x0) / (x1 - x0))
EndSub

Sub Slider_WaitToRelease
  ' Slider | Get released point for slider moving
  ' param iSlider
  param = "down=False;move=True;up=True;"  ' for slider moving / wait to release
  Mouse_SetHandler()
  While released = "False"
    If moved Then
      param = "move=False;"  ' while slider moving
      Mouse_SetHandler()
      x0_ = slider[iSlider]["x0"]
      x1_ = slider[iSlider]["x1"]
      If mxM < x0_ Then
        mxM = x0_
      EndIf
      If x1_ < mxM Then
        mxM = x1_
      EndIf
      Slider_GetMouseLevel()  ' get mouse level of slider
      Slider_SetLevel()       ' set slider level and move slider box
      Slider_CallBack()
      param = "move=True;"    ' for next slider moving
      Mouse_SetHandler()
    Else
      Program.Delay(100)
    EndIf
  EndWhile
  param = "move=False;up=False;"  ' mouse released
  Mouse_SetHandler()
EndSub

Sub Slider_Remove
  ' Slider | Remove a slider
  ' param iSlider
  Shapes.Remove(slider[iSlider]["oCaption"])
  Shapes.Remove(slider[iSlider]["oSlit"])
  Shapes.Remove(slider[iSlider]["oBox"])
  Shapes.Remove(slider[iSlider]["oLevel"])
EndSub

Sub Slider_SetLevel
  ' Slider | Set slider level and move slider box
  ' param iSlider
  ' param level
  Stack.PushValue("local", width)
  x0 = slider[iSlider]["x0"]
  x1 = slider[iSlider]["x1"]
  y0 = slider[iSlider]["y0"]
  width = x1 - x0
  slider[iSlider]["level"] = level
  Shapes.SetText(slider[iSlider]["oLevel"], level)
  ' move bar
  min = slider[iSlider]["min"]
  max = slider[iSlider]["max"]
  mag = (level - min) / (max - min)
  ' move box
  Shapes.Move(slider[iSlider]["oBox"], x0 + Math.Floor(width * mag) - 5, y0)
  slider[iSlider]["x2"] = x0 + Math.Floor(width * mag) - 5
  slider[iSlider]["x3"] = x0 + Math.Floor(width * mag) - 5 + 10
  slider[iSlider]["y2"] = y0
  slider[iSlider]["y3"] = y0 + 18
  width = Stack.PopValue("local")
EndSub
' Krueg  --  Starfield  --  Sept. 2012

Delay = 60        'Delay for smooth framrate
StarQty = 80      'Number of stars, Too many and it slows the program
SetupWindow()
CreateStars()

While ("True")
  MoveStars()
  RefreshRate()   'Comment out this line to see the jerkiness of the array proccessing
EndWhile

Sub RefreshRate
  While Clock.ElapsedMilliseconds < FrameRate
  EndWhile
  FrameRate = Clock.ElapsedMilliseconds + Delay
EndSub

Sub MoveStars
  For i = 1 To StarQty
    StarY[i] = StarY[i] + StarHeight[i] * 1.5
    If StarY[i] > gh Then
      StarY[i] = StarY[i] - gh
      StarX[i] = Math.GetRandomNumber(gw - 10) + 5
    EndIf
    Shapes.Move(Star[i],StarX[i],StarY[i])      'Checking which moves smother, Shapes.Move or Shapes.Animate
    'Shapes.Animate(Star[i],StarX[i],StarY[i],0)
  EndFor
EndSub

Sub CreateStars
  For i = 1 To StarQty
    GraphicsWindow.PenColor = "White"
    GraphicsWindow.BrushColor = "White"
    StarWidth[i] = Math.GetRandomNumber(2)
    If i < (StarQty * .9) Then
      StarHeight[i] = Math.GetRandomNumber(3)   'Create more small stars than big
    Else
      StarHeight[i] = Math.GetRandomNumber(4)+4
    EndIf
    Star[i] = Shapes.AddEllipse(StarWidth[i],StarHeight[i])
    Shapes.SetOpacity(Star[i],StarHeight[i]*5+50)
    StarX[i] = Math.GetRandomNumber(gw - 10) + 5
    StarY[i] = Math.GetRandomNumber(gh)
    Shapes.Move(Star[i],StarX[i],StarY[i])
  EndFor
EndSub

Sub SetupWindow
  gw = 800
  gh = 600
  GraphicsWindow.Top = 5
  GraphicsWindow.Left = 5
  GraphicsWindow.Width = gw
  GraphicsWindow.Height = gh
  GraphicsWindow.BackgroundColor = "Black"
EndSub
  
GraphicsWindow.PenWidth=0 'This prevents the following objects to habe black lines around them. Makes them "prettier" :P
GraphicsWindow.BrushColor="Purple" 'Sets the color for all the "Swarm" objects.
For i = 1 to 20 'Add 20 "Swarm" objects
  Swarm[i]=shapes.AddEllipse(10,10) 'This adds 20 "Swarm" objects. Wich are circles of 10x10 pixels here. This can be changed to every object you want.
  SX[i]=Math.GetRandomNumber(150)+225 'This here sets the X Position of every "Swarm" object to a random value
  SY[i]=Math.GetRandomNumber(150)+225 'This here sets the Y Position of every "Swarm" object to a random value
endfor
While "true" 'Main Loop
  For i = 1 To 20 'Do the following for all 20 "Swarm" objects:
    If SY[i]<GraphicsWindow.MouseY and SWY[i] < 15 Then 'Accelerates the "Swarm" object down, if it is higher than the Cursor.
      SWY[i]=SWY[i]+0.5 'Increases the Y Speed by 0.5. Its name is WY because Wucht means momentum in german. (this might be not the right name, but im familiar with it that way)
    elseIf SY[i] > GraphicsWindow.MouseY and SWY[i] > -15 THen 'Accelerates the "Swarm" object up, if it is lower than the Cursor.
      SWY[i]=SWY[i]-0.5 'Decreases the Y Speed by -0.5.
    endif
    If SX[i] < GraphicsWindow.MouseX and SWX[i] < 15 THen 'Accelerates the "Swarm" object to the right side, if it is on the left side of the Cursor.
      SWX[i]=SWX[i]+0.5 'Increases the X Speed by 0.5.
    elseIf SX[i] > GraphicsWindow.MouseX and SWX[i] > -15 THen 'Accelerates the "Swarm" object to the left side, if it is on the right side of the Cursor.
      SWX[i]=SWX[i]-0.5 'Decreases the X Speed by -0.5.
    endif
    SX[i]=SX[i]+SWX[i] ' "Combines" the X position of the "Swarm" object with its X speed. This isnt necessary, shapes.move(Swarm[i],SX[i]+SWX[i],SY[i]+SWY[i]), can also be used instead. But this method gives it better overview and makes it easyer to call an objects position.
    SY[i]=SY[i]+SWY[i] ' "Combines" the Y position of the "Swarm" object with its Y speed
    Shapes.Move(Swarm[i],SX[i]+5,SY[i]+5) ' Moves the "Swarm" object to its new assigned position. The +5 is there to make the object move around its center. And its +5 Because the radius of the object is 5 pixels.
  endfor
  Program.Delay(10)' Added a delay of 10 Milliseconds to limit the programs speed. Try to remove it, and see what happens ;D
endwhile 'End of main loop
GraphicsWindow.KeyDown = HandleKey
GraphicsWindow.BackgroundColor = GraphicsWindow.GetColorFromRGB( 253, 252, 251 )

While "True"
  BOXES = 4      ' number of boxes per piece
  BWIDTH = 25    ' box width in pixels
  XOFFSET = 40   ' Screen X offset in pixels of where the board starts
  YOFFSET = 40   ' Screen Y offset in pixels of where the board starts
  CWIDTH = 10    ' Canvas Width, in number of boxes
  CHEIGHT = 20   ' Canvas Height, in number of boxes.
  STARTDELAY = 800
  ENDDELAY = 175
  PREVIEW_xpos = 13
  PREVIEW_ypos = 2
  
  GraphicsWindow.Clear()
  GraphicsWindow.Title = "Small Basic Tetris"
  GraphicsWindow.Height = 580
  GraphicsWindow.Width = 700
  GraphicsWindow.Show()

  SetupTemplates()
  SetupCanvas()
  MainLoop()
  
  GraphicsWindow.ShowMessage( "Game Over", "Small Basic Tetris" )
EndWhile

Sub MainLoop
  template = Text.Append("template", Math.GetRandomNumber(7))

  CreatePiece() ' in: template  ret: h
  nextPiece = h

  end = 0
  sessionDelay = STARTDELAY
  While end = 0
    If sessionDelay > ENDDELAY Then
      sessionDelay = sessionDelay - 1
    EndIf
    
    delay = sessionDelay
    thisPiece = nextPiece
    template = Text.Append("template", Math.GetRandomNumber(7))

    CreatePiece() ' in: template  ret: h
    nextPiece = h
    DrawPreviewPiece()
    
    h = thisPiece    
    
    ypos = 0
    done = 0
    xpos = 3 ' always drop from column 3
    CheckStop() ' in: ypos, xpos, h  ret: done
    If done = 1 Then
      ypos = ypos - 1
      MovePiece()  'in: ypos, xpos, h
      end = 1
    EndIf
    
    yposdelta = 0
    While done = 0 Or yposdelta > 0
      MovePiece()  'in: ypos, xpos, h
      
      ' Delay, but break if the delay get set to 0 if the piece gets dropped
      delayIndex = delay      
      While delayIndex > 0 And delay > 0
        Program.Delay(10)
        delayIndex = delayIndex - 10
      EndWhile  

      If yposdelta > 0 Then
        yposdelta = yposdelta - 1  ' used to create freespin, when the piece is rotated
      Else
        ypos = ypos + 1            ' otherwise, move the piece down.
      EndIf
      
      ' Check if the piece should stop.
      CheckStop() ' in: ypos, xpos, h  ret: done            
    EndWhile
  EndWhile
EndSub

Sub HandleKey
  ' Stop game
  If GraphicsWindow.LastKey = "Escape" Then
    Program.End()
  EndIf

  ' Move piece left
  If GraphicsWindow.LastKey = "Left" Then
    moveDirection = -1
    ValidateMove()  ' in: ypos, xpos, h, moveDirection  ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
    If invalidMove = 0 Then
      xpos = xpos + moveDirection
    EndIf
    MovePiece()  'in: ypos, xpos, h
  EndIf
  
  ' Move piece right
  If GraphicsWindow.LastKey = "Right" Then
    moveDirection = 1
    ValidateMove()  ' in: ypos, xpos, h, moveDirection  ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
    If invalidMove = 0 Then
      xpos = xpos + moveDirection
    EndIf
    MovePiece()  'in: ypos, xpos, h
  EndIf
  
  ' Move piece down
  If GraphicsWindow.LastKey = "Down" or GraphicsWindow.LastKey = "Space" Then
    delay = 0
  EndIf
  
  ' Rotate piece
  If GraphicsWindow.LastKey = "Up" Then
    basetemplate = Array.GetValue(h, -1)  ' Array.GetValue(h, -1) = the template name
    template = "temptemplate"
    rotation = "CW"
    CopyPiece()  'in basetemplate, template, rotation

    Array.SetValue(h, -1, template) ' Array.GetValue(h, -1) = the template name
    moveDirection = 0
    ValidateMove()  ' in: ypos, xpos, h, moveDirection  ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
    
    ' See if it can be moved so that it will rotate.
    xposbk = xpos
    yposdelta = 0
    While yposdelta = 0 And Math.Abs(xposbk - xpos) < 3 ' move up to 3 times only
      ' if the rotation move worked, copy the temp to "rotatedtemplate" and use that from now on
      If invalidMove = 0 Then
        basetemplate = template
        template = "rotatedtemplate"
        Array.SetValue(h, -1, template) ' Array.GetValue(h, -1) = the template name
        rotation = "COPY"
        CopyPiece()  'in basetemplate, template, rotation
        yposdelta = 1 ' Don't move down if we rotate
        MovePiece()  'in: ypos, xpos, h
      ElseIf invalidMove = 2 Then
        ' Don't support shifting piece when hitting another piece to the right or left.
        xpos = 99 ' exit the loop
      Else
        ' if the rotated piece can't be placed, move it left or right and try again.
        xpos = xpos - invalidMove
        ValidateMove()  ' in: ypos, xpos, h, moveDirection  ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
      EndIf
    EndWhile
        
    If invalidMove <> 0 Then
      xpos = xposbk
      Array.SetValue(h, -1, basetemplate) ' Array.GetValue(h, -1) = the template name
      template = ""
    EndIf      
  EndIf
EndSub


Sub DrawPreviewPiece
  xpos = PREVIEW_xpos
  ypos = PREVIEW_ypos
  h = nextPiece

  XOFFSETBK = XOFFSET
  YOFFSETBK = YOFFSET
  XOFFSET = XOFFSET + Array.GetValue(Array.GetValue(h, -1), "pviewx") ' Array.GetValue(h, -1) = the template name
  YOFFSET = YOFFSET + Array.GetValue(Array.GetValue(h, -1), "pviewy") ' Array.GetValue(h, -1) = the template name
  MovePiece()  'in: ypos, xpos, h

  XOFFSET = XOFFSETBK
  YOFFSET = YOFFSETBK
EndSub

' creates template that's a rotated basetemplate
Sub CopyPiece  'in basetemplate, template, rotation  
  L = Array.GetValue(basetemplate, "dim")
  
  If rotation = "CW" Then
    For i = 0 to BOXES - 1 '      x' = y     y' = L - 1 - x
      v = Array.GetValue(basetemplate, i)

      'x = Math.Floor(v/10)
      'y = Math.Remainder(v, 10)
      
      ' new x and y
      x = (Math.Remainder(v, 10))
      y = (L - 1 - Math.Floor(v/10))
      Array.SetValue(template, i, x * 10 + y)
    EndFor
  ' Count-Cockwise is not currently used
  ElseIf rotation = "CCW" Then
    For i = 0 to BOXES - 1 '      x' = L - 1 - y     y' = x
      v = Array.GetValue(basetemplate, i)
      'x = Math.Floor(v/10)
      'y = Math.Remainder(v, 10)

      ' new x and y
      x = (L - 1 - Math.Remainder(v, 10))
      y = Math.Floor(v/10)
      Array.SetValue(template, i, x * 10 + y)
    EndFor
  ElseIf rotation = "COPY" Then
    For i = 0 to BOXES - 1
      Array.SetValue(template, i, Array.GetValue(basetemplate, i))
    EndFor
  Else
    GraphicsWindow.ShowMessage("invalid parameter", "Error")
    Program.End()
  EndIf
  
  ' Copy the remain properties from basetemplate to template.
  Array.SetValue(template, "color", Array.GetValue(basetemplate, "color"))
  Array.SetValue(template, "dim", Array.GetValue(basetemplate, "dim"))
  Array.SetValue(template, "pviewx", Array.GetValue(basetemplate, "pviewx"))
  Array.SetValue(template, "pviewy", Array.GetValue(basetemplate, "pviewy"))
EndSub
    
Sub CreatePiece ' in: template  ret: h
  ' Create a new handle, representing an arrayName, that will represent the piece
  hcount = hcount + 1
  h = Text.Append("piece", hcount)
  
  Array.SetValue(h, -1, template) ' Array.GetValue(h, -1) = the template name

  GraphicsWindow.PenWidth = 1
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.BrushColor = Array.GetValue(template, "color")
  
  For i = 0 to BOXES - 1
    s = Shapes.AddRectangle(BWIDTH, BWIDTH)
    Shapes.Move(s, -BWIDTH, -BWIDTH) ' move off screen
    Array.SetValue(h, i, s)
  EndFor
EndSub

Sub MovePiece 'in: ypos, xpos, h.  ypos/xpos is 0-19, representing the top/left box coordinate of the piece on the canvas.  h returned by CreatePiece
  For i = 0 to BOXES - 1
    v = Array.GetValue(Array.GetValue(h, -1), i)  ' Array.GetValue(h, -1) = the template name
    x = Math.Floor(v/10)
    y = Math.Remainder(v, 10)
    
    ' Array.GetValue(h, i) = box for piece h.
    ' xpos/ypos = are topleft of shape.  x/y is the box offset within the shape.
    Shapes.Move(Array.GetValue(h, i), XOFFSET + xpos * BWIDTH + x * BWIDTH, YOFFSET + ypos * BWIDTH + y * BWIDTH)
  EndFor
EndSub

Sub ValidateMove ' in: ypos, xpos, h, moveDirection  ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
  i = 0
  invalidMove = 0
  While i < BOXES
    v = Array.GetValue(Array.GetValue(h, -1), i)  ' Array.GetValue(h, -1) = the template name

    'x/y is the box offset within the shape.
    x = Math.Floor(v/10)
    y = Math.Remainder(v, 10)
    
    If (x + xpos + moveDirection) < 0 Then
      invalidMove = -1
      i = BOXES ' force getting out of the loop
    EndIf

    If (x + xpos + moveDirection) >= CWIDTH Then
      invalidMove = 1
      i = BOXES ' force getting out of the loop
    EndIf

    If Array.GetValue("c", (x + xpos + moveDirection) + (y + ypos) * CWIDTH) <> "." Then
      invalidMove = 2
      i = BOXES ' force getting out of the loop
    EndIf

    i = i + 1
  EndWhile
EndSub


Sub CheckStop ' in: ypos, xpos, h  ret: done
  done = 0
  i = 0
  While i < BOXES
    v = Array.GetValue(Array.GetValue(h, -1), i)  ' Array.GetValue(h, -1) = the template name

    'x/y is the box offset within the shape.
    x = Math.Floor(v/10)
    y = Math.Remainder(v, 10)
    
    If y + ypos > CHEIGHT Or Array.GetValue("c", (x + xpos) + (y + ypos) * CWIDTH) <> "." Then
      done = 1
      i = BOXES ' force getting out of the loop
    EndIf

    i = i + 1
  EndWhile

  ' If we need to stop the piece, move the box handles to the canvas
  If done = 1 Then
    For i = 0 to BOXES - 1
      v = Array.GetValue(Array.GetValue(h, -1), i) ' Array.GetValue(h, -1) = the template name
      'x = Math.Floor(v/10)
      'y = Math.Remainder(v, 10)      
      Array.SetValue("c", (Math.Floor(v/10) + xpos) + (Math.Remainder(v, 10) + ypos - 1) * CWIDTH, Array.GetValue(h, i))
    EndFor
    
    ' 1 points for every piece successfully dropped
    score = score + 1
    PrintScore()
     
    ' Delete clared lines
    DeleteLines()
  EndIf
EndSub


Sub DeleteLines
  linesCleared = 0
  
  ' Iterate over each row, starting from the bottom
  For y = CHEIGHT - 1 to 0 Step -1  
    
    ' Check to see if the whole row is filled
    x = CWIDTH
    While x = CWIDTH
      x = 0
      While x < CWIDTH
        piece = Array.GetValue("c", x + y * CWIDTH)
        If piece = "." then
          x = CWIDTH
        EndIf
        x = x + 1
      EndWhile
      
      ' if non of them were empty (i.e "."), then remove the line.
      If x = CWIDTH Then
        
        ' Delete the line
        For x1 = 0 to CWIDTH - 1
          Shapes.Remove(Array.GetValue("c", x1 + y * CWIDTH))
        EndFor
        linesCleared = linesCleared + 1
        
        ' Move everything else down one.
        For y1 = y To 1 Step -1
          For x1 = 0 to CWIDTH - 1
            piece = Array.GetValue("c", x1 + (y1 - 1) * CWIDTH)
            Array.SetValue("c", x1 + y1 * CWIDTH, piece)
            Shapes.Move(piece, Shapes.GetLeft(piece), Shapes.GetTop(piece) + BWIDTH)
          EndFor
        EndFor
      EndIf
    EndWhile
  EndFor
  
  If linesCleared > 0 Then
    score = score + 100 * Math.Round(linesCleared * 2.15 - 1)
    PrintScore()
  EndIf
EndSub

Sub SetupCanvas
'    GraphicsWindow.DrawResizedImage( Flickr.GetRandomPicture( "bricks" ), 0, 0, GraphicsWindow.Width, GraphicsWindow.Height)

  
  GraphicsWindow.BrushColor = GraphicsWindow.BackgroundColor
  GraphicsWindow.FillRectangle(XOFFSET, YOFFSET, CWIDTH*BWIDTH, CHEIGHT*BWIDTH)

  Program.Delay(200)
  GraphicsWindow.PenWidth = 1
  GraphicsWindow.PenColor = "Pink"
  For x = 0 To CWIDTH-1
    For y = 0 To CHEIGHT-1
      Array.SetValue("c", x + y * CWIDTH, ".") ' "." indicates spot is free
      GraphicsWindow.DrawRectangle(XOFFSET + x * BWIDTH, YOFFSET + y * BWIDTH, BWIDTH, BWIDTH)
    EndFor
  EndFor

  GraphicsWindow.PenWidth = 4
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.DrawLine(XOFFSET, YOFFSET, XOFFSET, YOFFSET + CHEIGHT*BWIDTH)
  GraphicsWindow.DrawLine(XOFFSET + CWIDTH*BWIDTH, YOFFSET, XOFFSET + CWIDTH*BWIDTH, YOFFSET + CHEIGHT*BWIDTH)
  GraphicsWindow.DrawLine(XOFFSET, YOFFSET + CHEIGHT*BWIDTH, XOFFSET + CWIDTH*BWIDTH, YOFFSET + CHEIGHT*BWIDTH)
  
  GraphicsWindow.PenColor = "Lime"
  GraphicsWindow.DrawLine(XOFFSET - 4, YOFFSET, XOFFSET - 4, YOFFSET + CHEIGHT*BWIDTH + 6)
  GraphicsWindow.DrawLine(XOFFSET + CWIDTH*BWIDTH + 4, YOFFSET, XOFFSET + CWIDTH*BWIDTH + 4, YOFFSET + CHEIGHT*BWIDTH + 6)
  GraphicsWindow.DrawLine(XOFFSET - 4, YOFFSET + CHEIGHT*BWIDTH + 4, XOFFSET + CWIDTH*BWIDTH + 4, YOFFSET + CHEIGHT*BWIDTH + 4)
  
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.BrushColor = "Pink"
  x = XOFFSET + PREVIEW_xpos * BWIDTH - BWIDTH
  y = YOFFSET + PREVIEW_ypos * BWIDTH - BWIDTH
  GraphicsWindow.FillRectangle(x, y, BWIDTH * 5, BWIDTH * 6)
  GraphicsWindow.DrawRectangle(x, y, BWIDTH * 5, BWIDTH * 6)
  
  GraphicsWindow.FillRectangle(x - 20, y + 190, 310, 170)
  GraphicsWindow.DrawRectangle(x - 20, y + 190, 310, 170)
  
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.FontItalic = "False"
  GraphicsWindow.FontName = "Comic Sans MS"
  GraphicsWindow.FontSize = 16
  GraphicsWindow.DrawText(x, y + 200, "Game control keys:")
  GraphicsWindow.DrawText(x + 25, y + 220, "Left Arrow = Move piece left")
  GraphicsWindow.DrawText(x + 25, y + 240, "Right Arrow = Move piece right")
  GraphicsWindow.DrawText(x + 25, y + 260, "Up Arrow = Rotate piece")
  GraphicsWindow.DrawText(x + 25, y + 280, "Down Arrow = Drop piece")
  GraphicsWindow.DrawText(x, y + 320, "Press  to stop game")

  Program.Delay(200) ' without this delay, the above text will use the fontsize of the score 

  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.FontName = "Georgia"
  GraphicsWindow.FontItalic = "True"
  GraphicsWindow.FontSize = 36
  GraphicsWindow.DrawText(x - 20, y + 400, "Small Basic Tetris")
  Program.Delay(200) ' without this delay, the above text will use the fontsize of the score 
  GraphicsWindow.FontSize = 16
  GraphicsWindow.DrawText(x - 20, y + 440, "ver.0.1")

  Program.Delay(200) ' without this delay, the above text will use the fontsize of the score 
  score = 0
  PrintScore() 
EndSub


Sub PrintScore
  GraphicsWindow.PenWidth = 4
  GraphicsWindow.BrushColor = "Pink"
  GraphicsWindow.FillRectangle(500, 65, 153, 50)
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawRectangle(500, 65, 153, 50)
  GraphicsWindow.FontItalic = "False"
  GraphicsWindow.FontSize = 32
  GraphicsWindow.FontName = "Impact"
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawText(505, 70, Text.Append(Text.GetSubText( "00000000", 0, 8 - Text.GetLength( score ) ), score))
EndSub


Sub SetupTemplates
  ' each piece has 4 boxes.
  ' the index of each entry within a piece represents the box number (1-4)
  ' the value of each entry represents to box zero-based box coordinate within the piece: tens place is x, ones place y

  '_X_
  '_X_
  '_XX

  Array.SetValue("template1", 0, 10)
  Array.SetValue("template1", 1, 11)
  Array.SetValue("template1", 2, 12)
  Array.SetValue("template1", 3, 22)
  Array.SetValue("template1", "color", "Yellow")
  Array.SetValue("template1", "dim", 3)
  Array.SetValue("template1", "pviewx", -12)
  Array.SetValue("template1", "pviewy", 12)


  '_X_
  '_X_
  'XX_
  Array.SetValue("template2", 0, 10)
  Array.SetValue("template2", 1, 11)
  Array.SetValue("template2", 2, 12)
  Array.SetValue("template2", 3, 02)
  Array.SetValue("template2", "color", "Magenta")
  Array.SetValue("template2", "dim", 3)
  Array.SetValue("template2", "pviewx", 12)
  Array.SetValue("template2", "pviewy", 12)
  
  
  '_X_
  'XXX
  '_
  Array.SetValue("template3", 0, 10)
  Array.SetValue("template3", 1, 01)
  Array.SetValue("template3", 2, 11)
  Array.SetValue("template3", 3, 21)
  Array.SetValue("template3", "color", "Gray")
  Array.SetValue("template3", "dim", 3)
  Array.SetValue("template3", "pviewx", 0)
  Array.SetValue("template3", "pviewy", 25)
  
  
  'XX_
  'XX_
  '_
  Array.SetValue("template4", 0, 00)
  Array.SetValue("template4", 1, 10)
  Array.SetValue("template4", 2, 01)
  Array.SetValue("template4", 3, 11)
  Array.SetValue("template4", "color", "Cyan")
  Array.SetValue("template4", "dim", 2)
  Array.SetValue("template4", "pviewx", 12)
  Array.SetValue("template4", "pviewy", 25)
  
  
  'XX_
  '_XX
  '_
  Array.SetValue("template5", 0, 00)
  Array.SetValue("template5", 1, 10)
  Array.SetValue("template5", 2, 11)
  Array.SetValue("template5", 3, 21)
  Array.SetValue("template5", "color", "Green")
  Array.SetValue("template5", "dim", 3)
  Array.SetValue("template5", "pviewx", 0)
  Array.SetValue("template5", "pviewy", 25)
  
  
  '_XX
  'XX_
  '_
  Array.SetValue("template6", 0, 10)
  Array.SetValue("template6", 1, 20)
  Array.SetValue("template6", 2, 01)
  Array.SetValue("template6", 3, 11)
  Array.SetValue("template6", "color", "Blue")
  Array.SetValue("template6", "dim", 3)
  Array.SetValue("template6", "pviewx", 0)
  Array.SetValue("template6", "pviewy", 25)
  
  
  '_X
  '_X
  '_X
  '_X
  Array.SetValue("template7", 0, 10)
  Array.SetValue("template7", 1, 11)
  Array.SetValue("template7", 2, 12)
  Array.SetValue("template7", 3, 13)
  Array.SetValue("template7", "color", "Red")
  Array.SetValue("template7", "dim", 4)
  Array.SetValue("template7", "pviewx", 0)
  Array.SetValue("template7", "pviewy", 0)
EndSub




gw = GraphicsWindow.Width
gh = GraphicsWindow.Height
DrawGrid()
x = 200
y = 300
r = 200
DrawArcwoTrigo()
Program.Delay(3000)
GraphicsWindow.Clear()
DrawGrid()
a1 = -30
a2 = -60
DrawArcwTrigo()
Sub DrawArcwoTrigo  ' draw arc without trigonometric functions
  GraphicsWindow.Title = "Arc without Trigonometric Functions"
  c1 = r * Math.SquareRoot(3) / 2   ' a1 = -30
  c2 = r / 2                        ' a2 = -60
  r2 = Math.Power(r, 2)
  For c = c1 To c2 Step -1
    s = Math.SquareRoot(r2 - Math.Power(c, 2))
    x2 = x + c
    y2 = y - s
    If c = c1 Then
      GraphicsWindow.PenColor = "Gray"
      GraphicsWindow.DrawLine(x, y, x2, y2)
    Else
      GraphicsWindow.PenColor = "Black"
      GraphicsWindow.DrawLine(x1, y1, x2, y2)
    EndIf
    If c - 1 < c2 Then
      GraphicsWindow.PenColor = "Gray"
      GraphicsWindow.DrawLine(x, y, x2, y2)
    EndIf
    x1 = x2
    y1 = y2
  EndFor
EndSub
Sub DrawArcwTrigo  ' draw arc with trigonometric functions
  GraphicsWindow.Title = "Arc with Trigonometric Functions"
  For a = a1 To a2 Step -0.3
    x2 = x + r * Math.Cos(Math.GetRadians(a))
    y2 = y + r * Math.Sin(Math.GetRadians(a))
    If a = a1 Then
      GraphicsWindow.PenColor = "Gray"
      GraphicsWindow.DrawLine(x, y, x2, y2)
    Else
      GraphicsWindow.PenColor = "Black"
      GraphicsWindow.DrawLine(x1, y1, x2, y2)
    EndIf
    If a - 0.3 < a2 Then
      GraphicsWindow.PenColor = "Gray"
      GraphicsWindow.DrawLine(x, y, x2, y2)
    EndIf
    x1 = x2
    y1 = y2
  EndFor
EndSub
Sub DrawGrid
  GraphicsWindow.PenColor = "MediumSeaGreen"
  GraphicsWindow.BrushColor = "MediumSeaGreen"
  For _x = 0 To gw Step 50
    GraphicsWindow.DrawLine(_x, 0, _x, gh)
    If gw - 50 < _x Then
      GraphicsWindow.DrawText(_x + 4, 4, "x")
    Else
      GraphicsWindow.DrawText(_x + 4, 4, _x)
    EndIf
  EndFor
  For _y = 0 To gh Step 50
    GraphicsWindow.DrawLine(0, _y, gw, _y)
    If gh - 50 < _y Then
      GraphicsWindow.DrawText(4, _y + 4, "y")
    Else
      GraphicsWindow.DrawText(4, _y + 4, _y)
    EndIf
  EndFor
EndSub' TicTacToe v0.4
'
'  RANDOM vs
'  CENTER vs
'  RUNORSTOP vs
'  MONTECARLO vs
'  HUMAN
'
' Copyright (c) 2010 NonkiTakahashi
'
' constants
SPACE = 0 ' none
TURN1 = 1 ' X
TURN2 = 2 ' O
OB = 3    ' out bound
GMAX = 10 ' max number of games
iRo = 3  ' number of ro (dimension)
iNR = 0  ' number of record
'
sVersion = "v0.4"  ' program version
GraphicsWindow.Title = "TicTacToe " + sVersion 
sFigure[1] = "X"
sFigure[2] = "O"
'
sEntry[1] = "HUMAN"
sEntry[2] = "RANDOM"
sEntry[3] = "CENTER"
sEntry[4] = "RUNORSTOP"
sEntry[5] = "MONTECARLO"
iNE = 5  ' number of entries
'
iTGMax = GMAX
iE1 = 2
iE2 = 2
sPlayer[1] = sEntry[iE1]
sPlayer[2] = sEntry[iE2]
'
lMainMenu:
GraphicsWindow.Clear()
InitGame()
If bStart <> "True" Then
  Program.End()
EndIf  
'
GraphicsWindow.BrushColor = "SteelBlue"
iSeed = 0
bDebug = "False"
'
lReplay:
iT1 = 0 ' times X win
iT2 = 0 ' times O win
iTD = 0 ' times draw
iTG = 0 ' times games
iTW = 10 ' times work out for MONTECARLO
'
lNextGame:
GraphicsWindow.Clear()
If iTG > 0 Then
  ShowResult()
EndIf  
iS = 0  ' step
InitBoard() ' initialize board
SaveBoard() ' current board <- board
DrawBoard()
'
' game start
While "True"
'
  ' turn X (Player 1)
  iTurn = TURN1
  EachTurn()
  If sGame <> "continue" Then
    Goto lExit
  EndIf
'
  ' turn O (Player 2)
  iTurn = TURN2
  EachTurn()
  If sGame <> "continue" Then
    Goto lExit
  EndIf
'
EndWhile
'
lExit:
GraphicsWindow.BrushColor = "SteelBlue"
GraphicsWindow.DrawText(10, 10, sGame)
If sGame = "X win" then
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.PenColor = "SteelBlue"
  GraphicsWindow.DrawLine(iWX0, iWY0, iWX1, iWY1)
  iT1 = iT1 + 1
ElseIf sGame = "O win" then
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.PenColor = "SteelBlue"
  GraphicsWindow.DrawLine(iWX0, iWY0, iWX1, iWY1)
  iT2 = iT2 + 1
Else
  iTD = iTD + 1
EndIf
iTG = iTG + 1
If sGame = "X win" then
  Program.Delay(500)
Else
  Program.Delay(1000)
EndIf
If iTG < iTGmax Then
  Goto lNextGame
EndIf
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(400, 20, 150, 150)
GraphicsWindow.BrushColor = "SteelBlue"
ShowResult()
Continue()
If bRestart Then
  Goto lReplay
Else
  Goto lMainMenu
EndIf  
'
' EachTurn
' in: integer iTurn - 1 or 2
' in: string sPlayer[] - selected player
Sub EachTurn
  GetPutList()  ' find next possible puts
  iS = iS + 1
  If sPlayer[iTurn] = "RANDOM" Then
    Random()
  ElseIf sPlayer[iTurn] = "CENTER" Then
    Center()
  ElseIf sPlayer[iTurn] = "RUNORSTOP" Then
    RunOrStop()
  ElseIf sPlayer[iTurn] = "MONTECARLO" Then
    WorkOut() 'determine a from put list by MONTECARLO method
  ElseIf sPlayer[iTurn] = "HUMAN" Then
    Human()
  EndIf
  Sound.PlayClickAndWait()
  PutFigure()
  Record()    ' record game score
  RestoreBoard() ' board <- current board
  DrawBoard()
  Judge()
EndSub  
'  
' Initialize Game
' work: integer iY1, iY2, iY3, iY4, iY5, idY
Sub InitGame
  idY = 40
  iY1 = 50
  iY2 = iY1 + idY
  iY3 = iY2 + idY
  iY4 = iY3 + idY
  iY5 = iY4 + idY
  GraphicsWindow.FontSize = 18
  GraphicsWindow.BrushColor = "Black"
  GraphicsWindow.DrawBoundText(10, 10, 400, "TicTacToe " + sVersion)
  GraphicsWindow.DrawText(10, iY1, "Main Menu")
  GraphicsWindow.DrawText(10, iY2, "player 1 :")
  GraphicsWindow.DrawText(10, iY3, "player 2 :")
  GraphicsWindow.DrawText(10, iY4, "games :")
  oTB1 = Controls.AddTextBox(120, iY2)
  oTB2 = Controls.AddTextBox(120, iY3)
  oTBG = Controls.AddTextBox(120, iY4)
  oBL1 = Controls.AddButton("<", 310, iY2)
  oBR1 = Controls.AddButton(">", 345, iY2)
  oBL2 = Controls.AddButton("<", 310, iY3)
  oBR2 = Controls.AddButton(">", 345, iY3)
  oBLG = Controls.AddButton("<", 310, iY4)
  oBRG = Controls.AddButton(">", 345, iY4)
  oBStart = Controls.AddButton("Start", 10, iY5)
  oBEnd = Controls.AddButton("End", 75, iY5)
  sPlayer[1] = sEntry[iE1]
  sPlayer[2] = sEntry[iE2]
  Controls.SetTextBoxText(oTB1, sPlayer[1])
  Controls.SetTextBoxText(oTB2, sPlayer[2])
  Controls.SetTextBoxText(oTBG, iTGMax)
  bStart = ""
  Controls.ButtonClicked = OnButtonClicked
  While bStart = ""
    Program.Delay(500)
  EndWhile  
EndSub

Sub DrawGrid
  iX0 = 100
  iY0 = 100
  iX1 = 700
  iY1 = 500
  GraphicsWindow.PenColor = "Cyan"
  GraphicsWindow.PenWidth = 1
  For iX = iX0 To iX1 Step iX0
    For iY = iY0 To iY1 Step iY0
      GraphicsWindow.DrawLine(iX, 0, iX, iY1)
      GraphicsWindow.DrawLine(0, iY, iX1, iY)
    EndFor
  EndFor
EndSub
'
' Continue ?
Sub Continue
  iY1 = 200
  GraphicsWindow.FontSize = 18
  GraphicsWindow.BrushColor = "Black"
  oBC = Controls.AddButton("Continue", 400, iY1)
  oBM = Controls.AddButton("Main", 500, iY1)
  bRestart = ""
  Controls.ButtonClicked = OnButtonClicked2
  While bRestart = ""
    Program.Delay(500)
  EndWhile  
EndSub
'
Sub OnButtonClicked
  oBu = Controls.LastClickedButton
  If oBu = oBStart Then
    bStart = "True"
  ElseIf oBu = oBEnd Then
    bStart = "False"
  ElseIf oBu = oBL1 Then
    iE1 = iE1 - 1
    If iE1 < 1 Then
      iE1 = iNE
    EndIf
    sPlayer[1] = sEntry[iE1]
    Controls.SetTextBoxText(oTB1, sPlayer[1])
  ElseIf oBu = oBR1 Then
    iE1 = iE1 + 1
    If iE1 > iNE Then
      iE1 = 1
    EndIf
    sPlayer[1] = sEntry[iE1]
    Controls.SetTextBoxText(oTB1, sPlayer[1])
  ElseIf oBu = oBL2 Then
    iE2 = iE2 - 1
    If iE2 < 1 Then
      iE2 = iNE
    EndIf
    sPlayer[2] = sEntry[iE2]
    Controls.SetTextBoxText(oTB2, sPlayer[2])
  ElseIf oBu = oBR2 Then
    iE2 = iE2 + 1
    If iE2 > iNE Then
      iE2 = 1
    EndIf
    sPlayer[2] = sEntry[iE2]
    Controls.SetTextBoxText(oTB2, sPlayer[2])
  ElseIf oBu = oBLG Then
    If itGMax > 1 Then
      iTGMax = iTGMax - 1
    Else
      iTGMax = GMAX
    EndIf
    Controls.SetTextBoxText(oTBG, iTGMax)
  ElseIf oBu = oBRG Then
    If iTGMax < GMAX Then
      iTGMax = iTGMax + 1
    Else
     iTGMax = 1
    EndIf
    Controls.SetTextBoxText(oTBG, iTGMax)
  EndIf  
EndSub
'
Sub OnButtonClicked2
  oBu = Controls.LastClickedButton
  If oBu = oBC Then
    bRestart = "True"
  ElseIf oBu = oBM Then
    bRestart = "False"
  EndIf  
EndSub
'
' Player HUMAN
' in: integer iPX[], iPY[] - possible puts
' in: integer iNumPuts - entry count of possible puts
' work: integer i - index of possible puts
' work: integer iMX, iMY - mouse position
' out: integer iX, iY - next put
Sub Human
  iX = iPX[1]
  iY = iPY[1]
lCurrentMouse:
  Program.Delay(200)  
  iMX = GraphicsWindow.MouseX
  iMY = GraphicsWindow.MouseY
  GetPosition()
  If Mouse.isLeftButtonDown Then
    Goto lCheckPut 
  Else
    Goto lCurrentMouse
  EndIf
lCheckPut:
  For i = 1 To iNumPuts
    If iPX[i] = iX And iPY[i] = iY Then
      Goto lReturnMouse
    EndIf  
  EndFor
  Goto lCurrentMouse
lReturnMouse:  
  iX = iPX[i]
  iY = iPY[i]
EndSub
'
' Get position of mouse clicked
' in: integer iMX, iMY - mouse position
' out: iX, iY - board position
Sub GetPosition
  If iMX < 150 Then
    iX = 1
  ElseIf iMX < 250 Then
    iX = 2
  Else
    iX = 3
  EndIf    
  If iMY < 150 Then
    iY = 1
  ElseIf iMY < 250 Then
    iY = 2
  Else
    iY = 3
  EndIf    
EndSub
'
' Record game score
' in: integer iX, iY - next put
' in: integer iS - stage
' out: iRX[], iRY[] - game score
Sub Record
  iRX[iS] = iX
  iRY[iS] = iY
EndSub
'
' Show game score to text window for debug
' in: integer iRX[], iRY[] - game score
' in: integer iS - put count (stage)
' work: integer i - index of game score
Sub ShowRecord
  For i = 1 to iS
    TextWindow.Write("[" + iRX[i] + "][" + iRY[i] + "],")
  EndFor    
  TextWindow.WriteLine("")
EndSub
'
' Show possible puts list to text window for debug
' in: integer iNumPuts - entry count of possible puts
' in: integer iPX[], iPY[] - possible puts
' work: integer i - index of possible puts
Sub ShowPutList
  For i = 1 To iNumPuts
    TextWindow.Write("iPX[" + i + "]=" + iPX[i])
    TextWindow.WriteLine(",iPY[" + i + "]=" + iPY[i])
  EndFor
EndSub    
'
' Save possible puts list
' in: integer iPX[], iPY[] - possible puts
' in: integer iNumPuts - entry count of possible puts
' work: integer i
' out: integer iSX[], iSX[] - saved possible puts
' out: integer iSNP - saved entry count of possible puts
Sub SavePutList
  iSNP = iNumPuts
  For i = 1 To iSNP
    iSX[i] = iPX[i]
    iSY[i] = iPY[i]
  EndFor
EndSub
'
' Restore possble puts list
' in: integer iSX[], iSY[] - saved possible puts
' in: integer iSNP - saved entry count of possible puts
' out: integer iPX[], iPY[] - (restored) possible puts
' out: iNumPuts - (restored) entry count of possible puts
Sub RestorePutList
  iNumPuts = iSNP
  For i = 1 To iNumPuts
    iPX[i] = iSX[i]
    iPY[i] = iSY[i]
  EndFor
EndSub
'
' Save current board
' in: integer iBoard[][] - board
' work: integer iX, iY
' out: integer iSaved[][] - saved current board
Sub SaveBoard
  For iY = 1 To iRo
    For iX = 1 To iRo
      iSaved[iX][iY] = iBoard[iX][iY]
    EndFor
  EndFor
EndSub  
'
' Restore current board
' in: integer iRo - 3
' in: integer iSaved[] - saved current board
' work: integer iX, iY
' out: iBoard[] - (restored) board
Sub RestoreBoard
  For iY = 1 To iRo
    For iX = 1 To iRo
      iBoard[iX][iY] = iSaved[iX][iY]
    EndFor
  EndFor
EndSub  
'
' Player MONTECARLO
' in: integer iS - stage
' in: integer iSNP - entry count of possible puts
' work: integer iSS - saved stage
' work: integer iTT - saved turn
' work: integer i - index of win counter
' work: integer iFP - first put
' work: integer iG - work out game count
' work: integer iTurn
' out: integer iX, iY
Sub WorkOut
  SavePutList()
  iSS = iS ' save stage
  iTT = iTurn ' save turn

  For i = 1 To iSNP ' instead of iNumPuts
    iWin[i] = 0 ' result clear
  EndFor
  For iG = 1 To iTW * iSNP
    iS = iSS - 1 ' temporaly stage
    RestoreBoard() ' board <- current board
    iTurn = TURN1
    If Math.Remainder(iS, 2) = 0 Then
      iTurn = TURN2
      Goto lNextO
    EndIf
'
lNextX:
    ' turn X
    GetPutList()
    iS = iS + 1
    RunOrStop()
    If iS = iSS Then
      iFP = iNP ' first put
    EndIf
    iBoard[iX][iY] = TURN1
    Judge()
    If sGame <> "continue" Then
      Goto lEndGame
    EndIf
'
lNextO:
    ' turn O
    GetPutList()
    iS = iS + 1
    RunOrStop()
    If iS = iSS Then
      iFP = iNP ' first put
    EndIf
    iBoard[iX][iY] = TURN2
    Judge()
    If sGame <> "continue" Then
      Goto lEndGame
    EndIf
'
    Goto lNextX
'
lEndGame:
    If sGame = sFigure[iTurn] + " win" Then
      iWin[iFP] = iWin[iFP] + 3 * (10 - iS)
    ElseIf sGame = "draw" then
      iWin[iFP] = iWin[iFP] + (10 - iS)
    Else
      iWin[iFP] = iWin[iFP] + 2 * (10 - iS)
    EndIf  
  EndFor
'
  iMax = 0
  For i = 1 to iSNP ' instead of p
    If iWin[i] >= iMax Then
      iMax = iWin[i]
      iNP = i
    EndIf
  EndFor    
  RestorePutList()
  iS = iSS ' restore stage
  iTurn = iTT ' restore turn
  iX = iPX[iNP]
  iY = iPY[iNP]
EndSub
'
' Player RANDOM
' in: boolean bDebug - is debug ?
' in/out: integer iSeed - seed for random number debug version
' in: integer iNumPuts - number of possible puts
' work: integer iNP - index of possible puts
' out: integer iX, iY - next put
Sub Random
  iNP = Math.GetRandomNumber(iNumPuts)
  If bDebug Then
    iSeed = iSeed + 1
    If iSeed > iNumPuts Then
      iSeed = 1
    EndIf
    iNP = iSeed
  EndIf
  iX = iPX[iNP]
  iY = iPY[iNP]
EndSub
'
' Player CENTER
' in: integer iBoard[][] - board
' out: integer iX, iY - next put
Sub Center
  If iBoard[2][2] = SPACE Then
    iX = 2
    iY = 2
  Else
    Random()
  EndIf
EndSub
'
' Player RUNORSTOP
' in: integer iNumPuts - entry count of possible puts
' in: integer iPX[], iPY[] - possible puts
' work: integer iRun[] - count of run (ex. X_X for X)
' work: integer iStop[] - count of stop (ex. O_O for X)
' work: integer i -  index of run and stop candidate
' work: integer iX0, iY0 - a possible put
' work: integer iMax - max count of run
' work: integer iX1, iY1, iX2, iY2 - points on a run
' out: integer iNP - final index of possble puts
' out: integer iX, iY - next put
Sub RunOrStop
  ' clear run and stop candidate
  For i = 1 To iNumPuts
    iRun[i] = 0
    iStop[i] = 0
  EndFor
  ' set next of candidate
  For i = 1 To iNumPuts
    iX0 = iPX[i]
    If iX0 = 1 Then
      iX1 = 2
      iX2 = 3
    ElseIf iX0 = 2 Then
      iX1 = 1
      iX2 = 3
    Else ' iX0 = 3
      iX1 = 1
      iX2 = 2
    EndIf
    iY0 = iPY[i]
    If iY0 = 1 Then
      iY1 = 2
      iY2 = 3
    ElseIf iY0 = 2 Then
      iY1 = 1
      iY2 = 3
    Else ' iY0 = 3
      iY1 = 1
      iY2 = 2
    EndIf
    '
    If iBoard[iX1][iY0] = iBoard[iX2][iY0] Then
      '  horizontal run or stop found
      If iBoard[iX1][iY0] = TURN1 Then
        ' X_X
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iRun[i] = iRun[i] + 1
        Else
          ' turn O
          iStop[i] = iStop[i] + 1
        EndIf
      EndIf
      If iBoard[iX1][iY0] = TURN2 Then
        ' O_O
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iStop[i] = iStop[i] + 1
        Else
          ' turn O
          iRun[i] = iRun[i] + 1
        EndIf
      EndIf
    EndIf
    If iBoard[iX0][iY1] = iBoard[iX0][iY2] Then
      '  vartical run or stop found
      If iBoard[iX0][iY1] = TURN1 Then
        ' X_X
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iRun[i] = iRun[i] + 1
        Else
          ' turn O
          iStop[i] = iStop[i] + 1
        EndIf
      EndIf
      If iBoard[iX0][iY1] = TURN2 Then
        ' O_O
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iStop[i] = iStop[i] + 1
        Else
          ' turn O
          iRun[i] = iRun[i] +1
        EndIf
      EndIf
    EndIf
    If iX0 = iY0 And iBoard[iX1][iY1] = iBoard[iX2][iY2] Then
      ' down run or stop found
      If iBoard[iX1][iY1] = TURN1 Then
        ' X_X
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iRun[i] = iRun[i] + 1
        Else
          ' turn O
          iStop[i] = iStop[i] + 1
        EndIf
      EndIf
      If iBoard[iX1][iY1] = TURN2 Then
        ' O_O
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iStop[i] = iStop[i] + 1
        Else
          ' turn O
          iRun[i] = iRun[i] + 1
        EndIf
      EndIf
    EndIf
    If iX0 + iY0 = 4 And iBoard[iX1][iY2] = iBoard[iX2][iY1] Then
      ' up run or stop found
      If iBoard[iX1][iY2] = TURN1 Then
        ' X_X
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iRun[i] = iRun[i] + 1
        Else
          ' turn O
          iStop[i] = iStop[i] + 1
        EndIf
      EndIf
      If iBoard[iX1][iY2] = TURN2 Then
        ' O_O
        If Math.Remainder(iS, 2) = 1 Then
          ' turn X
          iStop[i] = iStop[i] + 1
        Else
          ' turn O
          iRun[i] = iRun[i] + 1
        EndIf
      EndIf
    EndIf
  EndFor
  iMax = 0
  For i = 1 To iNumPuts
    If iRun[i] > iMax Then
      iMax = iRun[i]
      iNP = i
    EndIf
  EndFor
  If iMax > 0 Then
    Goto lReturnNP
  EndIf 
  For i = 1 To iNumPuts
    If iStop[i] > iMax Then
      iMax = iStop[i] 
      iNP = i
    EndIf
  EndFor
  If iMax > 0 Then
    Goto lReturnNP
  EndIf 
  Random()
lReturnNP:  
  iX = iPX[iNP]
  iY = iPY[iNP]
EndSub
'
' Show result of games
' in: integer iT1 - times X wins
' in: integer iT2 - times O wins
' in: integer iTD - times draw
' in: integer iTG - games
' in: string sPlayer[] - players logic names
Sub ShowResult
  GraphicsWindow.DrawText(400, 20, sFigure[1] + " win: " + iT1 + " (" + Math.Floor(iT1 / iTG * 100) + "%)")
  GraphicsWindow.DrawText(400, 40, sFigure[2] + " win: " + iT2 + " (" + Math.Floor(iT2 / iTG * 100) + "%)")
  GraphicsWindow.DrawText(400, 60, "draw : " + iTD + " (" + Math.Floor(iTD / iTG * 100) + "%)")
  GraphicsWindow.DrawText(400, 80, "games: " + iTG)
  GraphicsWindow.DrawText(400, 120, sFigure[1] + ": " + sPlayer[1])
  GraphicsWindow.DrawText(400, 140, sFigure[2] + ": " + sPlayer[2])
EndSub
'
' Check game end
' in: integer iNumPuts - entry count of possible puts
' in: integer iS - stage
' out: string sGame - game result "continue" or "X win" or "O win" or "draw"
Sub Judge
  sGame = "continue"
  If iNumPuts <= 6 Then
    If Math.Remainder(iS, 2) = 1 Then
      iTurn = TURN1
    Else
      iTurn = TURN2
    EndIF    
    CheckRun()
    If iNumPuts = 1 And sGame = "continue" Then
      sGame = "draw"
    EndIf
  EndIf
EndSub
'
' Check Run
' in: integer iTurn
' in: integer iBoard[][] - board
' out: string sGame
' out: integer iWX0, iWY0, iWX1, iWY1 - line of win
Sub CheckRun
  If iBoard[1][1] = iTurn And iBoard[2][1] = iTurn And iBoard[3][1] = iTurn Then
    iWX0 =  50
    iWY0 = 100
    iWX1 = 350
    iWY1 = 100
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[1][2] = iTurn And iBoard[2][2] = iTurn And iBoard[3][2] = iTurn Then
    iWX0 =  50
    iWY0 = 200
    iWX1 = 350
    iWY1 = 200
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[1][3] = iTurn And iBoard[2][3] = iTurn And iBoard[3][3] = iTurn Then
    iWX0 =  50
    iWY0 = 300
    iWX1 = 350
    iWY1 = 300
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[1][1] = iTurn And iBoard[1][2] = iTurn And iBoard[1][3] = iTurn Then
    iWX0 = 100
    iWY0 =  50
    iWX1 = 100
    iWY1 = 350
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[2][1] = iTurn And iBoard[2][2] = iTurn And iBoard[2][3] = iTurn Then
    iWX0 = 200
    iWY0 =  50
    iWX1 = 200
    iWY1 = 350
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[3][1] = iTurn And iBoard[3][2] = iTurn And iBoard[3][3] = iTurn Then
    iWX0 = 300
    iWY0 =  50
    iWX1 = 300
    iWY1 = 350
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[1][1] = iTurn And iBoard[2][2] = iTurn And iBoard[3][3] = iTurn Then
    iWX0 =  50
    iWY0 =  50
    iWX1 = 350
    iWY1 = 350
    sGame = sFigure[iTurn] + " win"
  ElseIf iBoard[1][3] = iTurn And iBoard[2][2] = iTurn And iBoard[3][1] = iTurn Then
    iWX0 = 350
    iWY0 =  50
    iWX1 =  50
    iWY1 = 350
    sGame = sFigure[iTurn] + " win"
  EndIf
EndSub
'
' Get possible puts list
' in: integer iBoard[][] - board
' out: integer iNumPuts - entry count of possible puts
' out: integer iPX[], iPY[] - possible puts
' work: integer iNP - instead of x, y for iBoard[][]
Sub GetPutList
  iNumPuts = 0
  For iNP = 0 To 8
    If iBoard[Math.Remainder(iNP, 3) + 1][Math.Floor(iNP / 3) + 1] = SPACE Then
      iNumPuts = iNumPuts + 1
      iPX[iNumPuts] = Math.Remainder(iNP, 3) + 1
      iPY[iNumPuts] = Math.Floor(iNP / 3) + 1
    EndIf  
  EndFor
EndSub
'
' Draw board on graphics window
' in: integer iRo - 3
' work: integer iX, iY
Sub DrawBoard
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.PenColor = "Black"
  GraphicsWindow.DrawLine(50, 150, 350, 150)
  GraphicsWindow.DrawLine(50, 250, 350, 250)
  GraphicsWindow.DrawLine(150, 50, 150, 350)
  GraphicsWindow.DrawLine(250, 50, 250, 350)
  GraphicsWindow.PenWidth = 4
  GraphicsWindow.PenColor = "Gray"
  For iY = 1 To iRo
    For iX = 1 To iRo
      If sFigure[iBoard[iX][iY]] = "O" Then
        GraphicsWindow.DrawEllipse(65 + (iX - 1) * 100, 65 + (iY - 1) * 100, 70, 70)
      ElseIf sFigure[iBoard[iX][iY]] = "X" Then
        GraphicsWindow.DrawLine(65 + (iX - 1) * 100, 65 + (iY - 1) * 100, 135 + (iX - 1) * 100, 135 + (iY - 1) * 100)
        GraphicsWindow.DrawLine(135 + (iX - 1) * 100, 65 + (iY - 1) * 100, 65 + (iX - 1) * 100, 135 + (iY - 1) * 100)
      EndIf
    EndFor
  EndFor    
EndSub
'
' Put figure onto board
' in: integer iSaved[][] - current board
' in: integer iRo - 3
' in: integer iX -x coordinate
' in: integer iY -y coordinate
' in: integer iTurn - 1 or 2
' in: string sAlpha[] - alphabet for SGF game score
Sub PutFigure
  If (iX > 0 And iX <= iRo And iY > 0 And iY <= iRo) Then
    iSaved[iX][iY] = iTurn
    If (iTurn = TURN1) Then
      sLine = ";B[" + sAlpha[iX] + sAlpha[iY] + "]C[" + sFigure[TURN1] + "(" + iX + "," + iY + ")]"
      OutputLine()
    ElseIf (iTurn = TURN2) Then
      sLine = ";W[" + sAlpha[iX] + sAlpha[iY] + "]C[" + sFigure[TURN2] + "(" + iX + "," + iY + ")]"
      OutputLine()
    ElseIf (iTurn = SPACE) Then
      sLine = ";E[" + sAlpha[iX] + sAlpha[iY] + "]C[-(" + iX + "," + iY + ")]"
      OutputLine()
    EndIf  
  EndIf
EndSub
'
' OutputLine
' in: string sLine - output line
Sub OutputLine
  iNR = iNR + 1
  sRec[iNR] = sLine
EndSub
'
' Get figure from board
' in: integer iSaved[][] - current board
' in: integer iX, iY - x, y coordinate
' out: integer iFigure - TURN1 or TURN2
Sub GetFigure
  If (iX >= 1 And iX <= iRo And iY >= 1 And iY <= iRo) Then
    iFigure = iSaved[iX][iY]
  Else
    iFigure = OB
  EndIf
EndSub
'
' Initialize board
' in: integer iRo - 3
' work: integer iX, iY, i
' out: integer iBoard - board
' out: string sAlpha[] - alphabet for SGF game score
Sub InitBoard
  For iY = 1 To iRo
    For iX = 1 To iRo
      iBoard[iX][iY] = SPACE
    EndFor
  EndFor
'
  For i = 0 To iRo + 1
    iBoard[i][0] = OB
    iBoard[i][iRo + 1] = OB
    iBoard[0][i] = OB
    iBoard[iRo + 1][i] = OB
  EndFor
'
  For i = 0 To iRo
    ' alphabet for SGF game score
    sAlpha[i] = Text.GetSubText(" abcdefghijklmnopqrs", i + 1, 1)
  EndFor
EndSub

Comentarii

Postări populare de pe acest blog

WINDOWS 10 COMPUTER FREEZING PROBLEM SOLVED

good news : a BIOS UPDATE can resolve the problem but just for a Windows 7 on 64 bits o.s. and the system is not stable all the time. even after  bios update the system can freeze.
new info : u can try to low the screen brightness and see if this error appear so often after 
news: last info !!! maybe a virus. scann our system now with an antivirus i generate this error using other device ( a tablet pc) connected in the same network and the laptop i have this problem just freeze  http://thehackernews.com/2013/10/backdoor-found-in-chinese-tenda.html

news : if u use a tenda router this make couse all this problems



what i discover so far :
1.the electric company have many failure and affect the main ISP router/switch for building  also the router/switch installed by the ISP may be affected by overheating and will crash after a long utilisation on heat conditions 2.the router/switch of ISP affect any router of the user between this router and pc/laptop of client 3.the router and any other device of t…

program principal cpp

#include "clasa.h" #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #define DELAY 9000000 void delay() { for(long i=0;i<DELAY;i++); } //constructor cu initializare de la tastatura BigInt::BigInt() {char x; signed char t[400]; int i; printf("\nNumarul cu semn "); do s=getche(); while((s!='+')&&(s!='-')); n=0; do {x=getche(); t[n]=x-'0'; n++; } while((x>='0')&&(x<='9')); n--; for(i=0;i<n;i++) nr[i]=t[n-i-1]; } //constructor cu initializare prin parametri BigInt::BigInt(char semn,signed char numar[],int dim) {int i; s=semn; n=dim; for(i=0;i<n;i++) nr[i]=numar[n-i-1]; } //transform un int negativ in pozitiv int BigInt::Pozitiv(int x) {int a,vb; a=0; vb=0; while(vb==0) if((x+a)==0) vb=1; else a=a+1; x=a; return x; } //constructor dintr-un nr int obisnuit BigInt::BigInt(int x) {int i; if(x>=0) s='+'…

o aplicatie php localitati romania

//APLICATIA SE REFERA LA BAZA DE DATE SIRUTA

//dragtable.js


/* dragtable v1.0 June 26, 2008 Dan Vanderkam, http://danvk.org/dragtable/ http://code.google.com/p/dragtable/ \Bsortabledraggable\B Instructions: - Download this file - Add <script src="dragtable.js"></script> to your HTML. - Add class="draggable" to any table you might like to reorder. - Drag the headers around to reorder them. This is code was based on: - Stuart Langridge's SortTable (kryogenix.org/code/browser/sorttable) - Mike Hall's draggable class (http://www.brainjar.com/dhtml/drag/) - A discussion of permuting table columns on comp.lang.javascript Licensed under the MIT license. */ // Here's the notice from Mike Hall's draggable script: //***************************************************************************** // Do not remove this notice. // // Copyright 2001 by Mike Hall. // See http…